diff --git a/.gitignore b/.gitignore index 30f0f0cbc2..e841cc4bf5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,11 @@ # Eclipse .settings/ +*.project +*.classpath .prefs *.prefs +.metadata/ # Intellij .idea/ @@ -21,3 +24,6 @@ # Maven log/ target/ + +spring-openid/src/main/resources/application.properties +.recommenders/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..9c5cdb8f2d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "testgitrepo"] + path = testgitrepo + url = /home/prd/Development/projects/idea/tutorials/spring-boot/src/main/resources/testgitrepo/ diff --git a/.project b/.project deleted file mode 100644 index 2d04570bfe..0000000000 --- a/.project +++ /dev/null @@ -1,11 +0,0 @@ - - - parent - - - - - - - - diff --git a/README.md b/README.md index da46989455..f0d3d29da7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ The "REST with Spring" Classes ============================== -After 5 months of work, here's the Master Class:
+After 5 months of work, here's the Master Class of REST With Spring:
**[>> THE REST WITH SPRING MASTER CLASS](http://www.baeldung.com/rest-with-spring-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=rws#master-class)** @@ -19,3 +19,8 @@ Any IDE can be used to work with the projects, but if you're using Eclipse, cons - import the included **formatter** in Eclipse: `https://github.com/eugenp/tutorials/tree/master/eclipse` + + +CI - Jenkins +================================ +This tutorials project is being built **[>> HERE](https://rest-security.ci.cloudbees.com/job/tutorials/)** diff --git a/RemoteSystemsTempFiles/.project b/RemoteSystemsTempFiles/.project deleted file mode 100644 index 5447a64fa9..0000000000 --- a/RemoteSystemsTempFiles/.project +++ /dev/null @@ -1,12 +0,0 @@ - - - RemoteSystemsTempFiles - - - - - - - org.eclipse.rse.ui.remoteSystemsTempNature - - diff --git a/annotations/annotation-processing/pom.xml b/annotations/annotation-processing/pom.xml new file mode 100644 index 0000000000..6d07394b87 --- /dev/null +++ b/annotations/annotation-processing/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + + com.baeldung + 1.0.0-SNAPSHOT + annotations + ../ + + + annotation-processing + + + 1.0-rc2 + 3.5.1 + + + + + + com.google.auto.service + auto-service + ${auto-service.version} + provided + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + + + + \ No newline at end of file diff --git a/annotations/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProcessor.java b/annotations/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProcessor.java new file mode 100644 index 0000000000..0883e108e7 --- /dev/null +++ b/annotations/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProcessor.java @@ -0,0 +1,132 @@ +package com.baeldung.annotation.processor; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.ExecutableType; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; + +import com.google.auto.service.AutoService; + +@SupportedAnnotationTypes("com.baeldung.annotation.processor.BuilderProperty") +@SupportedSourceVersion(SourceVersion.RELEASE_8) +@AutoService(Processor.class) +public class BuilderProcessor extends AbstractProcessor { + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (TypeElement annotation : annotations) { + + Set annotatedElements = roundEnv.getElementsAnnotatedWith(annotation); + + Map> annotatedMethods = annotatedElements.stream() + .collect(Collectors.partitioningBy(element -> + ((ExecutableType) element.asType()).getParameterTypes().size() == 1 + && element.getSimpleName().toString().startsWith("set"))); + + List setters = annotatedMethods.get(true); + List otherMethods = annotatedMethods.get(false); + + otherMethods.forEach(element -> + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, + "@BuilderProperty must be applied to a setXxx method with a single argument", element)); + + if (setters.isEmpty()) { + continue; + } + + String className = ((TypeElement) setters.get(0).getEnclosingElement()).getQualifiedName().toString(); + + Map setterMap = setters.stream().collect(Collectors.toMap( + setter -> setter.getSimpleName().toString(), + setter -> ((ExecutableType) setter.asType()) + .getParameterTypes().get(0).toString() + )); + + try { + writeBuilderFile(className, setterMap); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + return true; + } + + private void writeBuilderFile(String className, Map setterMap) throws IOException { + + String packageName = null; + int lastDot = className.lastIndexOf('.'); + if (lastDot > 0) { + packageName = className.substring(0, lastDot); + } + + String simpleClassName = className.substring(lastDot + 1); + String builderClassName = className + "Builder"; + String builderSimpleClassName = builderClassName.substring(lastDot + 1); + + JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(builderClassName); + try (PrintWriter out = new PrintWriter(builderFile.openWriter())) { + + if (packageName != null) { + out.print("package "); + out.print(packageName); + out.println(";"); + out.println(); + } + + out.print("public class "); + out.print(builderSimpleClassName); + out.println(" {"); + out.println(); + + out.print(" private "); + out.print(simpleClassName); + out.print(" object = new "); + out.print(simpleClassName); + out.println("();"); + out.println(); + + out.print(" public "); + out.print(simpleClassName); + out.println(" build() {"); + out.println(" return object;"); + out.println(" }"); + out.println(); + + setterMap.entrySet().forEach(setter -> { + String methodName = setter.getKey(); + String argumentType = setter.getValue(); + + out.print(" public "); + out.print(builderSimpleClassName); + out.print(" "); + out.print(methodName); + + out.print("("); + + out.print(argumentType); + out.println(" value) {"); + out.print(" object."); + out.print(methodName); + out.println("(value);"); + out.println(" return this;"); + out.println(" }"); + out.println(); + }); + + out.println("}"); + + } + } + +} diff --git a/annotations/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProperty.java b/annotations/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProperty.java new file mode 100644 index 0000000000..84fcc73850 --- /dev/null +++ b/annotations/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProperty.java @@ -0,0 +1,8 @@ +package com.baeldung.annotation.processor; + +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.SOURCE) +public @interface BuilderProperty { +} diff --git a/annotations/annotation-user/pom.xml b/annotations/annotation-user/pom.xml new file mode 100644 index 0000000000..f76f691f93 --- /dev/null +++ b/annotations/annotation-user/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + + annotations + com.baeldung + 1.0.0-SNAPSHOT + ../ + + + annotation-user + + + + + com.baeldung + annotation-processing + ${project.parent.version} + + + + junit + junit + 4.12 + test + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + + + + \ No newline at end of file diff --git a/annotations/annotation-user/src/main/java/com/baeldung/annotation/Person.java b/annotations/annotation-user/src/main/java/com/baeldung/annotation/Person.java new file mode 100644 index 0000000000..23787ba4f4 --- /dev/null +++ b/annotations/annotation-user/src/main/java/com/baeldung/annotation/Person.java @@ -0,0 +1,29 @@ +package com.baeldung.annotation; + +import com.baeldung.annotation.processor.BuilderProperty; + +public class Person { + + private int age; + + private String name; + + public int getAge() { + return age; + } + + @BuilderProperty + public void setAge(int age) { + this.age = age; + } + + public String getName() { + return name; + } + + @BuilderProperty + public void setName(String name) { + this.name = name; + } + +} diff --git a/annotations/annotation-user/src/test/java/com/baeldung/annotation/PersonBuilderTest.java b/annotations/annotation-user/src/test/java/com/baeldung/annotation/PersonBuilderTest.java new file mode 100644 index 0000000000..72f9ac8bc7 --- /dev/null +++ b/annotations/annotation-user/src/test/java/com/baeldung/annotation/PersonBuilderTest.java @@ -0,0 +1,22 @@ +package com.baeldung.annotation; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PersonBuilderTest { + + @Test + public void whenBuildPersonWithBuilder_thenObjectHasPropertyValues() { + + Person person = new PersonBuilder() + .setAge(25) + .setName("John") + .build(); + + assertEquals(25, person.getAge()); + assertEquals("John", person.getName()); + + } + +} diff --git a/annotations/pom.xml b/annotations/pom.xml new file mode 100644 index 0000000000..f691674cf1 --- /dev/null +++ b/annotations/pom.xml @@ -0,0 +1,20 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + annotations + pom + + + annotation-processing + annotation-user + + + \ No newline at end of file diff --git a/annotations/readme.md b/annotations/readme.md new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/annotations/readme.md @@ -0,0 +1 @@ + diff --git a/apache-cxf/cxf-introduction/pom.xml b/apache-cxf/cxf-introduction/pom.xml new file mode 100644 index 0000000000..232a4f0089 --- /dev/null +++ b/apache-cxf/cxf-introduction/pom.xml @@ -0,0 +1,47 @@ + + + + 4.0.0 + cxf-introduction + + com.baeldung + apache-cxf + 0.0.1-SNAPSHOT + + + 3.1.6 + + + + + org.codehaus.mojo + exec-maven-plugin + + com.baeldung.cxf.introduction.Server + + + + maven-surefire-plugin + 2.19.1 + + + **/StudentTest.java + + + + + + + + org.apache.cxf + cxf-rt-frontend-jaxws + ${cxf.version} + + + org.apache.cxf + cxf-rt-transports-http-jetty + ${cxf.version} + + + diff --git a/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/Baeldung.java b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/Baeldung.java new file mode 100644 index 0000000000..472d38b8e1 --- /dev/null +++ b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/Baeldung.java @@ -0,0 +1,16 @@ +package com.baeldung.cxf.introduction; + +import java.util.Map; + +import javax.jws.WebService; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +@WebService +public interface Baeldung { + public String hello(String name); + + public String helloStudent(Student student); + + @XmlJavaTypeAdapter(StudentMapAdapter.class) + public Map getStudents(); +} \ No newline at end of file diff --git a/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/BaeldungImpl.java b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/BaeldungImpl.java new file mode 100644 index 0000000000..240f6bb1da --- /dev/null +++ b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/BaeldungImpl.java @@ -0,0 +1,24 @@ +package com.baeldung.cxf.introduction; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.jws.WebService; + +@WebService(endpointInterface = "com.baeldung.cxf.introduction.Baeldung") +public class BaeldungImpl implements Baeldung { + private Map students = new LinkedHashMap(); + + public String hello(String name) { + return "Hello " + name; + } + + public String helloStudent(Student student) { + students.put(students.size() + 1, student); + return "Hello " + student.getName(); + } + + public Map getStudents() { + return students; + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/Server.java b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/Server.java new file mode 100644 index 0000000000..0e5af60b9d --- /dev/null +++ b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/Server.java @@ -0,0 +1,15 @@ +package com.baeldung.cxf.introduction; + +import javax.xml.ws.Endpoint; + +public class Server { + public static void main(String args[]) throws InterruptedException { + BaeldungImpl implementor = new BaeldungImpl(); + String address = "http://localhost:8080/baeldung"; + Endpoint.publish(address, implementor); + System.out.println("Server ready..."); + Thread.sleep(60 * 1000); + System.out.println("Server exiting"); + System.exit(0); + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/Student.java b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/Student.java new file mode 100644 index 0000000000..cad8f94d97 --- /dev/null +++ b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/Student.java @@ -0,0 +1,8 @@ +package com.baeldung.cxf.introduction; + +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +@XmlJavaTypeAdapter(StudentAdapter.class) +public interface Student { + public String getName(); +} \ No newline at end of file diff --git a/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentAdapter.java b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentAdapter.java new file mode 100644 index 0000000000..29b829d808 --- /dev/null +++ b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentAdapter.java @@ -0,0 +1,16 @@ +package com.baeldung.cxf.introduction; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +public class StudentAdapter extends XmlAdapter { + public StudentImpl marshal(Student student) throws Exception { + if (student instanceof StudentImpl) { + return (StudentImpl) student; + } + return new StudentImpl(student.getName()); + } + + public Student unmarshal(StudentImpl student) throws Exception { + return student; + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentImpl.java b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentImpl.java new file mode 100644 index 0000000000..bc9dd27afe --- /dev/null +++ b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentImpl.java @@ -0,0 +1,23 @@ +package com.baeldung.cxf.introduction; + +import javax.xml.bind.annotation.XmlType; + +@XmlType(name = "Student") +public class StudentImpl implements Student { + private String name; + + StudentImpl() { + } + + public StudentImpl(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentMap.java b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentMap.java new file mode 100644 index 0000000000..4c40886c42 --- /dev/null +++ b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentMap.java @@ -0,0 +1,39 @@ +package com.baeldung.cxf.introduction; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +@XmlType(name = "StudentMap") +public class StudentMap { + private List entries = new ArrayList(); + + @XmlElement(nillable = false, name = "entry") + public List getEntries() { + return entries; + } + + @XmlType(name = "StudentEntry") + public static class StudentEntry { + private Integer id; + private Student student; + + public void setId(Integer id) { + this.id = id; + } + + public Integer getId() { + return id; + } + + public void setStudent(Student student) { + this.student = student; + } + + public Student getStudent() { + return student; + } + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentMapAdapter.java b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentMapAdapter.java new file mode 100644 index 0000000000..f156676a5f --- /dev/null +++ b/apache-cxf/cxf-introduction/src/main/java/com/baeldung/cxf/introduction/StudentMapAdapter.java @@ -0,0 +1,27 @@ +package com.baeldung.cxf.introduction; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +public class StudentMapAdapter extends XmlAdapter> { + public StudentMap marshal(Map boundMap) throws Exception { + StudentMap valueMap = new StudentMap(); + for (Map.Entry boundEntry : boundMap.entrySet()) { + StudentMap.StudentEntry valueEntry = new StudentMap.StudentEntry(); + valueEntry.setStudent(boundEntry.getValue()); + valueEntry.setId(boundEntry.getKey()); + valueMap.getEntries().add(valueEntry); + } + return valueMap; + } + + public Map unmarshal(StudentMap valueMap) throws Exception { + Map boundMap = new LinkedHashMap(); + for (StudentMap.StudentEntry studentEntry : valueMap.getEntries()) { + boundMap.put(studentEntry.getId(), studentEntry.getStudent()); + } + return boundMap; + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-introduction/src/test/java/com/baeldung/cxf/introduction/StudentTest.java b/apache-cxf/cxf-introduction/src/test/java/com/baeldung/cxf/introduction/StudentTest.java new file mode 100644 index 0000000000..e1e5b60ec3 --- /dev/null +++ b/apache-cxf/cxf-introduction/src/test/java/com/baeldung/cxf/introduction/StudentTest.java @@ -0,0 +1,65 @@ +package com.baeldung.cxf.introduction; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.ws.Service; +import javax.xml.ws.soap.SOAPBinding; + +import com.baeldung.cxf.introduction.Baeldung; +import com.baeldung.cxf.introduction.Student; +import com.baeldung.cxf.introduction.StudentImpl; + +public class StudentTest { + private static QName SERVICE_NAME = new QName("http://introduction.cxf.baeldung.com/", "Baeldung"); + private static QName PORT_NAME = new QName("http://introduction.cxf.baeldung.com/", "BaeldungPort"); + + private Service service; + private Baeldung baeldungProxy; + private BaeldungImpl baeldungImpl; + + { + service = Service.create(SERVICE_NAME); + String endpointAddress = "http://localhost:8080/baeldung"; + service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress); + } + + @Before + public void reinstantiateBaeldungInstances() { + baeldungImpl = new BaeldungImpl(); + baeldungProxy = service.getPort(PORT_NAME, Baeldung.class); + } + + @Test + public void whenUsingHelloMethod_thenCorrect() { + String endpointResponse = baeldungProxy.hello("Baeldung"); + String localResponse = baeldungImpl.hello("Baeldung"); + assertEquals(localResponse, endpointResponse); + } + + @Test + public void whenUsingHelloStudentMethod_thenCorrect() { + Student student = new StudentImpl("John Doe"); + String endpointResponse = baeldungProxy.helloStudent(student); + String localResponse = baeldungImpl.helloStudent(student); + assertEquals(localResponse, endpointResponse); + } + + @Test + public void usingGetStudentsMethod_thenCorrect() { + Student student1 = new StudentImpl("Adam"); + baeldungProxy.helloStudent(student1); + + Student student2 = new StudentImpl("Eve"); + baeldungProxy.helloStudent(student2); + + Map students = baeldungProxy.getStudents(); + assertEquals("Adam", students.get(1).getName()); + assertEquals("Eve", students.get(2).getName()); + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-spring/.gitignore b/apache-cxf/cxf-spring/.gitignore new file mode 100644 index 0000000000..2f7896d1d1 --- /dev/null +++ b/apache-cxf/cxf-spring/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/apache-cxf/cxf-spring/pom.xml b/apache-cxf/cxf-spring/pom.xml new file mode 100644 index 0000000000..85e68300f0 --- /dev/null +++ b/apache-cxf/cxf-spring/pom.xml @@ -0,0 +1,129 @@ + + 4.0.0 + cxf-spring + war + + com.baeldung + apache-cxf + 0.0.1-SNAPSHOT + + + + + org.apache.cxf + cxf-rt-frontend-jaxws + ${cxf.version} + + + org.apache.cxf + cxf-rt-transports-http-jetty + ${cxf.version} + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-webmvc + ${spring.version} + + + javax.servlet + javax.servlet-api + 3.1.0 + + + + + + + maven-war-plugin + 2.6 + + false + + + + maven-surefire-plugin + ${surefire.version} + + + StudentTest.java + + + + + + + + + integration + + + + org.codehaus.cargo + cargo-maven2-plugin + 1.4.19 + + + tomcat8x + embedded + + + + localhost + 8081 + + + + + + start-server + pre-integration-test + + start + + + + stop-server + post-integration-test + + stop + + + + + + + maven-surefire-plugin + ${surefire.version} + + + integration-test + + test + + + + none + + + + + + + + + + + + + 3.1.6 + 4.3.1.RELEASE + 2.19.1 + + + diff --git a/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/AppInitializer.java b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/AppInitializer.java new file mode 100644 index 0000000000..a4faa0f287 --- /dev/null +++ b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/AppInitializer.java @@ -0,0 +1,21 @@ +package com.baeldung.cxf.spring; + +import javax.servlet.ServletContext; +import javax.servlet.ServletRegistration; + +import org.apache.cxf.transport.servlet.CXFServlet; +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; + +public class AppInitializer implements WebApplicationInitializer { + @Override + public void onStartup(ServletContext container) { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.register(ServiceConfiguration.class); + container.addListener(new ContextLoaderListener(context)); + + ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new CXFServlet()); + dispatcher.addMapping("/services/*"); + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/Baeldung.java b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/Baeldung.java new file mode 100644 index 0000000000..b66e4c2fbf --- /dev/null +++ b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/Baeldung.java @@ -0,0 +1,10 @@ +package com.baeldung.cxf.spring; + +import javax.jws.WebService; + +@WebService +public interface Baeldung { + String hello(String name); + + String register(Student student); +} \ No newline at end of file diff --git a/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/BaeldungImpl.java b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/BaeldungImpl.java new file mode 100644 index 0000000000..911ce7f876 --- /dev/null +++ b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/BaeldungImpl.java @@ -0,0 +1,17 @@ +package com.baeldung.cxf.spring; + +import javax.jws.WebService; + +@WebService(endpointInterface = "com.baeldung.cxf.spring.Baeldung") +public class BaeldungImpl implements Baeldung { + private int counter; + + public String hello(String name) { + return "Hello " + name + "!"; + } + + public String register(Student student) { + counter++; + return student.getName() + " is registered student number " + counter; + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/ClientConfiguration.java b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/ClientConfiguration.java new file mode 100644 index 0000000000..021bcc6f66 --- /dev/null +++ b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/ClientConfiguration.java @@ -0,0 +1,21 @@ +package com.baeldung.cxf.spring; + +import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ClientConfiguration { + @Bean(name = "client") + public Object generateProxy() { + return proxyFactoryBean().create(); + } + + @Bean + public JaxWsProxyFactoryBean proxyFactoryBean() { + JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean(); + proxyFactory.setServiceClass(Baeldung.class); + proxyFactory.setAddress("http://localhost:8081/services/baeldung"); + return proxyFactory; + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/ServiceConfiguration.java b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/ServiceConfiguration.java new file mode 100644 index 0000000000..0bc60fb790 --- /dev/null +++ b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/ServiceConfiguration.java @@ -0,0 +1,24 @@ +package com.baeldung.cxf.spring; + +import javax.xml.ws.Endpoint; + +import org.apache.cxf.Bus; +import org.apache.cxf.bus.spring.SpringBus; +import org.apache.cxf.jaxws.EndpointImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ServiceConfiguration { + @Bean(name = Bus.DEFAULT_BUS_ID) + public SpringBus springBus() { + return new SpringBus(); + } + + @Bean + public Endpoint endpoint() { + EndpointImpl endpoint = new EndpointImpl(springBus(), new BaeldungImpl()); + endpoint.publish("http://localhost:8081/services/baeldung"); + return endpoint; + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/Student.java b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/Student.java new file mode 100644 index 0000000000..eb58057eb6 --- /dev/null +++ b/apache-cxf/cxf-spring/src/main/java/com/baeldung/cxf/spring/Student.java @@ -0,0 +1,20 @@ +package com.baeldung.cxf.spring; + +public class Student { + private String name; + + Student() { + } + + public Student(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/apache-cxf/cxf-spring/src/test/java/com/baeldung/cxf/spring/StudentTest.java b/apache-cxf/cxf-spring/src/test/java/com/baeldung/cxf/spring/StudentTest.java new file mode 100644 index 0000000000..7466944e04 --- /dev/null +++ b/apache-cxf/cxf-spring/src/test/java/com/baeldung/cxf/spring/StudentTest.java @@ -0,0 +1,29 @@ +package com.baeldung.cxf.spring; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public class StudentTest { + private ApplicationContext context = new AnnotationConfigApplicationContext(ClientConfiguration.class); + private Baeldung baeldungProxy = (Baeldung) context.getBean("client"); + + @Test + public void whenUsingHelloMethod_thenCorrect() { + String response = baeldungProxy.hello("John Doe"); + assertEquals("Hello John Doe!", response); + } + + @Test + public void whenUsingRegisterMethod_thenCorrect() { + Student student1 = new Student("Adam"); + Student student2 = new Student("Eve"); + String student1Response = baeldungProxy.register(student1); + String student2Response = baeldungProxy.register(student2); + + assertEquals("Adam is registered student number 1", student1Response); + assertEquals("Eve is registered student number 2", student2Response); + } +} \ No newline at end of file diff --git a/apache-cxf/pom.xml b/apache-cxf/pom.xml new file mode 100644 index 0000000000..022fc59f9b --- /dev/null +++ b/apache-cxf/pom.xml @@ -0,0 +1,41 @@ + + 4.0.0 + com.baeldung + apache-cxf + 0.0.1-SNAPSHOT + pom + + cxf-introduction + cxf-spring + + + + junit + junit + 4.12 + test + + + + install + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.codehaus.mojo + exec-maven-plugin + 1.5.0 + + + + + diff --git a/apache-fop/.classpath b/apache-fop/.classpath deleted file mode 100644 index 63439b10fa..0000000000 --- a/apache-fop/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apache-fop/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/apache-fop/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/apache-fop/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/apache-fop/.project b/apache-fop/.project deleted file mode 100644 index d91e323034..0000000000 --- a/apache-fop/.project +++ /dev/null @@ -1,36 +0,0 @@ - - - apache-fop - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/apache-fop/.springBeans b/apache-fop/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/apache-fop/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/apache-fop/pom.xml b/apache-fop/pom.xml index 95505f9374..658d567a90 100644 --- a/apache-fop/pom.xml +++ b/apache-fop/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung apache-fop 0.1-SNAPSHOT @@ -142,16 +142,12 @@ - - 4.1.5.RELEASE - 3.2.5.RELEASE - - 4.3.8.Final - 5.1.34 + 4.3.11.Final + 5.1.38 - 2.5.5 + 2.7.2 1.7.9 @@ -161,7 +157,7 @@ 5.1.3.Final - 17.0 + 19.0 3.3.2 @@ -172,14 +168,14 @@ 4.4 4.4 - 2.4.0 + 2.9.0 - 3.2 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.12 + 1.4.18 diff --git a/assertj/pom.xml b/assertj/pom.xml new file mode 100644 index 0000000000..421afd40a5 --- /dev/null +++ b/assertj/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + com.baeldung + assertj + 1.0.0-SNAPSHOT + + + + com.google.guava + guava + 19.0 + + + junit + junit + 4.12 + test + + + org.assertj + assertj-core + 3.5.1 + test + + + org.assertj + assertj-guava + 3.0.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/assertj/src/main/java/com/baeldung/assertj/introduction/domain/Dog.java b/assertj/src/main/java/com/baeldung/assertj/introduction/domain/Dog.java new file mode 100644 index 0000000000..623f71214c --- /dev/null +++ b/assertj/src/main/java/com/baeldung/assertj/introduction/domain/Dog.java @@ -0,0 +1,19 @@ +package com.baeldung.assertj.introduction.domain; + +public class Dog { + private String name; + private Float weight; + + public Dog(String name, Float weight) { + this.name = name; + this.weight = weight; + } + + public String getName() { + return name; + } + + public Float getWeight() { + return weight; + } +} diff --git a/assertj/src/main/java/com/baeldung/assertj/introduction/domain/Person.java b/assertj/src/main/java/com/baeldung/assertj/introduction/domain/Person.java new file mode 100644 index 0000000000..90ef787ebe --- /dev/null +++ b/assertj/src/main/java/com/baeldung/assertj/introduction/domain/Person.java @@ -0,0 +1,19 @@ +package com.baeldung.assertj.introduction.domain; + +public class Person { + private String name; + private Integer age; + + public Person(String name, Integer age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public Integer getAge() { + return age; + } +} diff --git a/assertj/src/test/java/com/baeldung/assertj/introduction/AssertJCoreTest.java b/assertj/src/test/java/com/baeldung/assertj/introduction/AssertJCoreTest.java new file mode 100644 index 0000000000..fc134ece00 --- /dev/null +++ b/assertj/src/test/java/com/baeldung/assertj/introduction/AssertJCoreTest.java @@ -0,0 +1,141 @@ +package com.baeldung.assertj.introduction; + +import com.baeldung.assertj.introduction.domain.Dog; +import com.baeldung.assertj.introduction.domain.Person; +import org.assertj.core.util.Maps; +import org.junit.Ignore; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +import static org.assertj.core.api.Assertions.*; + +public class AssertJCoreTest { + + @Test + public void whenComparingReferences_thenNotEqual() throws Exception { + Dog fido = new Dog("Fido", 5.15f); + Dog fidosClone = new Dog("Fido", 5.15f); + + assertThat(fido).isNotEqualTo(fidosClone); + } + + @Test + public void whenComparingFields_thenEqual() throws Exception { + Dog fido = new Dog("Fido", 5.15f); + Dog fidosClone = new Dog("Fido", 5.15f); + + assertThat(fido).isEqualToComparingFieldByFieldRecursively(fidosClone); + } + + @Test + public void whenCheckingForElement_thenContains() throws Exception { + List list = Arrays.asList("1", "2", "3"); + + assertThat(list) + .contains("1"); + } + + @Test + public void whenCheckingForElement_thenMultipleAssertions() throws Exception { + List list = Arrays.asList("1", "2", "3"); + + assertThat(list).isNotEmpty(); + assertThat(list).startsWith("1"); + assertThat(list).doesNotContainNull(); + + assertThat(list) + .isNotEmpty() + .contains("1") + .startsWith("1") + .doesNotContainNull() + .containsSequence("2", "3"); + } + + @Test + public void whenCheckingRunnable_thenIsInterface() throws Exception { + assertThat(Runnable.class).isInterface(); + } + + @Test + public void whenCheckingCharacter_thenIsUnicode() throws Exception { + char someCharacter = 'c'; + + assertThat(someCharacter) + .isNotEqualTo('a') + .inUnicode() + .isGreaterThanOrEqualTo('b') + .isLowerCase(); + } + + @Test + public void whenAssigningNSEExToException_thenIsAssignable() throws Exception { + assertThat(Exception.class).isAssignableFrom(NoSuchElementException.class); + } + + @Test + public void whenComparingWithOffset_thenEquals() throws Exception { + assertThat(5.1).isEqualTo(5, withPrecision(1d)); + } + + @Test + public void whenCheckingString_then() throws Exception { + assertThat("".isEmpty()).isTrue(); + } + + @Test + public void whenCheckingFile_then() throws Exception { + final File someFile = File.createTempFile("aaa", "bbb"); + someFile.deleteOnExit(); + + assertThat(someFile) + .exists() + .isFile() + .canRead() + .canWrite(); + } + + @Test + public void whenCheckingIS_then() throws Exception { + InputStream given = new ByteArrayInputStream("foo".getBytes()); + InputStream expected = new ByteArrayInputStream("foo".getBytes()); + + assertThat(given).hasSameContentAs(expected); + } + + @Test + public void whenGivenMap_then() throws Exception { + Map map = Maps.newHashMap(2, "a"); + + assertThat(map) + .isNotEmpty() + .containsKey(2) + .doesNotContainKeys(10) + .contains(entry(2, "a")); + } + + @Test + public void whenGivenException_then() throws Exception { + Exception ex = new Exception("abc"); + + assertThat(ex) + .hasNoCause() + .hasMessageEndingWith("c"); + } + + @Ignore // IN ORDER TO TEST, REMOVE THIS LINE + @Test + public void whenRunningAssertion_thenDescribed() throws Exception { + Person person = new Person("Alex", 34); + + assertThat(person.getAge()) + .as("%s's age should be equal to 100") + .isEqualTo(100); + } +} diff --git a/assertj/src/test/java/com/baeldung/assertj/introduction/AssertJGuavaTest.java b/assertj/src/test/java/com/baeldung/assertj/introduction/AssertJGuavaTest.java new file mode 100644 index 0000000000..aee803ada1 --- /dev/null +++ b/assertj/src/test/java/com/baeldung/assertj/introduction/AssertJGuavaTest.java @@ -0,0 +1,121 @@ +package com.baeldung.assertj.introduction; + +import com.google.common.base.Optional; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.Range; +import com.google.common.collect.Table; +import com.google.common.collect.TreeRangeMap; +import com.google.common.io.Files; +import org.assertj.guava.data.MapEntry; +import org.junit.Test; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; + +import static org.assertj.guava.api.Assertions.assertThat; +import static org.assertj.guava.api.Assertions.entry; + +public class AssertJGuavaTest { + + @Test + public void givenTwoEmptyFiles_whenComparingContent_thenEqual() throws Exception { + final File temp1 = File.createTempFile("bael", "dung1"); + final File temp2 = File.createTempFile("bael", "dung2"); + + assertThat(Files.asByteSource(temp1)) + .hasSize(0) + .hasSameContentAs(Files.asByteSource(temp2)); + } + + @Test + public void givenMultimap_whenVerifying_thenCorrect() throws Exception { + final Multimap mmap = ArrayListMultimap.create(); + mmap.put(1, "one"); + mmap.put(1, "1"); + + assertThat(mmap) + .hasSize(2) + .containsKeys(1) + .contains(entry(1, "one")) + .contains(entry(1, "1")); + } + + @Test + public void givenMultimaps_whenVerifyingContent_thenCorrect() throws Exception { + final Multimap mmap1 = ArrayListMultimap.create(); + mmap1.put(1, "one"); + mmap1.put(1, "1"); + mmap1.put(2, "two"); + mmap1.put(2, "2"); + + final Multimap mmap1_clone = Multimaps.newSetMultimap(new HashMap<>(), HashSet::new); + mmap1_clone.put(1, "one"); + mmap1_clone.put(1, "1"); + mmap1_clone.put(2, "two"); + mmap1_clone.put(2, "2"); + + final Multimap mmap2 = Multimaps.newSetMultimap(new HashMap<>(), HashSet::new); + mmap2.put(1, "one"); + mmap2.put(1, "1"); + + assertThat(mmap1) + .containsAllEntriesOf(mmap2) + .containsAllEntriesOf(mmap1_clone) + .hasSameEntriesAs(mmap1_clone); + } + + @Test + public void givenOptional_whenVerifyingContent_thenShouldBeEqual() throws Exception { + final Optional something = Optional.of("something"); + + assertThat(something) + .isPresent() + .extractingValue() + .isEqualTo("something"); + } + + @Test + public void givenRange_whenVerifying_thenShouldBeCorrect() throws Exception { + final Range range = Range.openClosed("a", "g"); + + assertThat(range) + .hasOpenedLowerBound() + .isNotEmpty() + .hasClosedUpperBound() + .contains("b"); + } + + @Test + public void givenRangeMap_whenVerifying_thenShouldBeCorrect() throws Exception { + final TreeRangeMap map = TreeRangeMap.create(); + + map.put(Range.closed(0, 60), "F"); + map.put(Range.closed(61, 70), "D"); + + assertThat(map) + .isNotEmpty() + .containsKeys(0) + .contains(MapEntry.entry(34, "F")); + } + + @Test + public void givenTable_whenVerifying_thenShouldBeCorrect() throws Exception { + final Table table = HashBasedTable.create(2, 2); + + table.put(1, "A", "PRESENT"); + table.put(1, "B", "ABSENT"); + + assertThat(table) + .hasRowCount(1) + .containsValues("ABSENT") + .containsCell(1, "B", "ABSENT"); + } + + + + +} diff --git a/assertj/src/test/java/com/baeldung/assertj/introduction/AssertJJava8Test.java b/assertj/src/test/java/com/baeldung/assertj/introduction/AssertJJava8Test.java new file mode 100644 index 0000000000..0cdbd0f7ea --- /dev/null +++ b/assertj/src/test/java/com/baeldung/assertj/introduction/AssertJJava8Test.java @@ -0,0 +1,132 @@ +package com.baeldung.assertj.introduction; + +import org.junit.Test; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; + +import static java.time.LocalDate.ofYearDay; +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; + +public class AssertJJava8Test { + + @Test + public void givenOptional_shouldAssert() throws Exception { + final Optional givenOptional = Optional.of("something"); + + assertThat(givenOptional) + .isPresent() + .hasValue("something"); + } + + @Test + public void givenPredicate_shouldAssert() throws Exception { + final Predicate predicate = s -> s.length() > 4; + + assertThat(predicate) + .accepts("aaaaa", "bbbbb") + .rejects("a", "b") + .acceptsAll(asList("aaaaa", "bbbbb")) + .rejectsAll(asList("a", "b")); + } + + @Test + public void givenLocalDate_shouldAssert() throws Exception { + final LocalDate givenLocalDate = LocalDate.of(2016, 7, 8); + final LocalDate todayDate = LocalDate.now(); + + assertThat(givenLocalDate) + .isBefore(LocalDate.of(2020, 7, 8)) + .isAfterOrEqualTo(LocalDate.of(1989, 7, 8)); + + assertThat(todayDate) + .isAfter(LocalDate.of(1989, 7, 8)) + .isToday(); + } + + @Test + public void givenLocalDateTime_shouldAssert() throws Exception { + final LocalDateTime givenLocalDate = LocalDateTime.of(2016, 7, 8, 12, 0); + + assertThat(givenLocalDate) + .isBefore(LocalDateTime.of(2020, 7, 8, 11, 2)); + } + + @Test + public void givenLocalTime_shouldAssert() throws Exception { + final LocalTime givenLocalTime = LocalTime.of(12, 15); + + assertThat(givenLocalTime) + .isAfter(LocalTime.of(1, 0)) + .hasSameHourAs(LocalTime.of(12, 0)); + } + + @Test + public void givenList_shouldAssertFlatExtracting() throws Exception { + final List givenList = asList(ofYearDay(2016, 5), ofYearDay(2015, 6)); + + assertThat(givenList) + .flatExtracting(LocalDate::getYear) + .contains(2015); + } + + @Test + public void givenList_shouldAssertFlatExtractingLeapYear() throws Exception { + final List givenList = asList(ofYearDay(2016, 5), ofYearDay(2015, 6)); + + assertThat(givenList) + .flatExtracting(LocalDate::isLeapYear) + .contains(true); + } + + @Test + public void givenList_shouldAssertFlatExtractingClass() throws Exception { + final List givenList = asList(ofYearDay(2016, 5), ofYearDay(2015, 6)); + + assertThat(givenList) + .flatExtracting(Object::getClass) + .contains(LocalDate.class); + } + + @Test + public void givenList_shouldAssertMultipleFlatExtracting() throws Exception { + final List givenList = asList(ofYearDay(2016, 5), ofYearDay(2015, 6)); + + assertThat(givenList) + .flatExtracting(LocalDate::getYear, LocalDate::getDayOfMonth) + .contains(2015, 6); + } + + @Test + public void givenString_shouldSatisfy() throws Exception { + final String givenString = "someString"; + + assertThat(givenString) + .satisfies(s -> { + assertThat(s).isNotEmpty(); + assertThat(s).hasSize(10); + }); + } + + @Test + public void givenString_shouldMatch() throws Exception { + final String emptyString = ""; + + assertThat(emptyString) + .matches(String::isEmpty); + } + + @Test + public void givenList_shouldHasOnlyOneElementSatisfying() throws Exception { + final List givenList = Arrays.asList(""); + + assertThat(givenList) + .hasOnlyOneElementSatisfying(s -> assertThat(s).isEmpty()); + } +} diff --git a/autovalue-tutorial/pom.xml b/autovalue-tutorial/pom.xml new file mode 100644 index 0000000000..d1f8e825fc --- /dev/null +++ b/autovalue-tutorial/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + com.baeldung + autovalue-tutorial + 1.0 + AutoValue + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 7 + 7 + false + + + + + + + com.google.auto.value + auto-value + 1.2 + + + + junit + junit + 4.3 + test + + + + diff --git a/autovalue-tutorial/src/main/java/com/baeldung/autovalue/AutoValueMoney.java b/autovalue-tutorial/src/main/java/com/baeldung/autovalue/AutoValueMoney.java new file mode 100644 index 0000000000..ef39f499d1 --- /dev/null +++ b/autovalue-tutorial/src/main/java/com/baeldung/autovalue/AutoValueMoney.java @@ -0,0 +1,15 @@ +package com.baeldung.autovalue; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class AutoValueMoney { + public abstract String getCurrency(); + + public abstract long getAmount(); + + public static AutoValueMoney create(String currency, long amount) { + return new AutoValue_AutoValueMoney(currency, amount); + + } +} diff --git a/autovalue-tutorial/src/main/java/com/baeldung/autovalue/AutoValueMoneyWithBuilder.java b/autovalue-tutorial/src/main/java/com/baeldung/autovalue/AutoValueMoneyWithBuilder.java new file mode 100644 index 0000000000..a7ac93e45b --- /dev/null +++ b/autovalue-tutorial/src/main/java/com/baeldung/autovalue/AutoValueMoneyWithBuilder.java @@ -0,0 +1,23 @@ +package com.baeldung.autovalue; + +import com.google.auto.value.AutoValue; + +@AutoValue +public abstract class AutoValueMoneyWithBuilder { + public abstract String getCurrency(); + + public abstract long getAmount(); + + static Builder builder() { + return new AutoValue_AutoValueMoneyWithBuilder.Builder(); + } + + @AutoValue.Builder + abstract static class Builder { + abstract Builder setCurrency(String currency); + + abstract Builder setAmount(long amount); + + abstract AutoValueMoneyWithBuilder build(); + } +} diff --git a/autovalue-tutorial/src/main/java/com/baeldung/autovalue/Foo.java b/autovalue-tutorial/src/main/java/com/baeldung/autovalue/Foo.java new file mode 100644 index 0000000000..bb90070f6d --- /dev/null +++ b/autovalue-tutorial/src/main/java/com/baeldung/autovalue/Foo.java @@ -0,0 +1,51 @@ +package com.baeldung.autovalue; + +import java.util.Objects; + +public final class Foo { + private final String text; + private final int number; + + public Foo(String text, int number) { + this.text = text; + this.number = number; + } + + public String getText() { + return text; + } + + public int getNumber() { + return number; + } + + @Override + public int hashCode() { + return Objects.hash(text, number); + } + + @Override + public String toString() { + return "Foo [text=" + text + ", number=" + number + "]"; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Foo other = (Foo) obj; + if (number != other.number) + return false; + if (text == null) { + if (other.text != null) + return false; + } else if (!text.equals(other.text)) + return false; + return true; + } + +} diff --git a/autovalue-tutorial/src/main/java/com/baeldung/autovalue/ImmutableMoney.java b/autovalue-tutorial/src/main/java/com/baeldung/autovalue/ImmutableMoney.java new file mode 100644 index 0000000000..04d29b6b09 --- /dev/null +++ b/autovalue-tutorial/src/main/java/com/baeldung/autovalue/ImmutableMoney.java @@ -0,0 +1,52 @@ +package com.baeldung.autovalue; +public final class ImmutableMoney { + private final long amount; + private final String currency; + public ImmutableMoney(long amount, String currency) { + this.amount = amount; + this.currency = currency; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (amount ^ (amount >>> 32)); + result = prime * result + + ((currency == null) ? 0 : currency.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ImmutableMoney other = (ImmutableMoney) obj; + if (amount != other.amount) + return false; + if (currency == null) { + if (other.currency != null) + return false; + } else if (!currency.equals(other.currency)) + return false; + return true; + } + + public long getAmount() { + return amount; + } + + public String getCurrency() { + return currency; + } + + @Override + public String toString() { + return "ImmutableMoney [amount=" + amount + ", currency=" + currency + + "]"; + } + +} diff --git a/autovalue-tutorial/src/main/java/com/baeldung/autovalue/MutableMoney.java b/autovalue-tutorial/src/main/java/com/baeldung/autovalue/MutableMoney.java new file mode 100644 index 0000000000..6cf8b75f7d --- /dev/null +++ b/autovalue-tutorial/src/main/java/com/baeldung/autovalue/MutableMoney.java @@ -0,0 +1,35 @@ +package com.baeldung.autovalue; + +public class MutableMoney { + @Override + public String toString() { + return "MutableMoney [amount=" + amount + ", currency=" + currency + + "]"; + } + + public long getAmount() { + return amount; + } + + public void setAmount(long amount) { + this.amount = amount; + } + + public String getCurrency() { + return currency; + } + + public void setCurrency(String currency) { + this.currency = currency; + } + + private long amount; + private String currency; + + public MutableMoney(long amount, String currency) { + super(); + this.amount = amount; + this.currency = currency; + } + +} diff --git a/autovalue-tutorial/src/test/java/com/baeldung/autovalue/MoneyTest.java b/autovalue-tutorial/src/test/java/com/baeldung/autovalue/MoneyTest.java new file mode 100644 index 0000000000..af3afe84fb --- /dev/null +++ b/autovalue-tutorial/src/test/java/com/baeldung/autovalue/MoneyTest.java @@ -0,0 +1,59 @@ +package com.baeldung.autovalue; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class MoneyTest { + @Test + public void givenTwoSameValueMoneyObjects_whenEqualityTestFails_thenCorrect() { + MutableMoney m1 = new MutableMoney(10000, "USD"); + MutableMoney m2 = new MutableMoney(10000, "USD"); + assertFalse(m1.equals(m2)); + } + + @Test + public void givenTwoSameValueMoneyValueObjects_whenEqualityTestPasses_thenCorrect() { + ImmutableMoney m1 = new ImmutableMoney(10000, "USD"); + ImmutableMoney m2 = new ImmutableMoney(10000, "USD"); + assertTrue(m1.equals(m2)); + } + + @Test + public void givenValueTypeWithAutoValue_whenFieldsCorrectlySet_thenCorrect() { + AutoValueMoney m = AutoValueMoney.create("USD", 10000); + assertEquals(m.getAmount(), 10000); + assertEquals(m.getCurrency(), "USD"); + } + + @Test + public void given2EqualValueTypesWithAutoValue_whenEqual_thenCorrect() { + AutoValueMoney m1 = AutoValueMoney.create("USD", 5000); + AutoValueMoney m2 = AutoValueMoney.create("USD", 5000); + assertTrue(m1.equals(m2)); + } + @Test + public void given2DifferentValueTypesWithAutoValue_whenNotEqual_thenCorrect() { + AutoValueMoney m1 = AutoValueMoney.create("GBP", 5000); + AutoValueMoney m2 = AutoValueMoney.create("USD", 5000); + assertFalse(m1.equals(m2)); + } + @Test + public void given2EqualValueTypesWithBuilder_whenEqual_thenCorrect() { + AutoValueMoneyWithBuilder m1 = AutoValueMoneyWithBuilder.builder().setAmount(5000).setCurrency("USD").build(); + AutoValueMoneyWithBuilder m2 = AutoValueMoneyWithBuilder.builder().setAmount(5000).setCurrency("USD").build(); + assertTrue(m1.equals(m2)); + } + @Test + public void given2DifferentValueTypesBuilder_whenNotEqual_thenCorrect() { + AutoValueMoneyWithBuilder m1 = AutoValueMoneyWithBuilder.builder().setAmount(5000).setCurrency("USD").build(); + AutoValueMoneyWithBuilder m2 = AutoValueMoneyWithBuilder.builder().setAmount(5000).setCurrency("GBP").build(); + assertFalse(m1.equals(m2)); + } + @Test + public void givenValueTypeWithBuilder_whenFieldsCorrectlySet_thenCorrect() { + AutoValueMoneyWithBuilder m = AutoValueMoneyWithBuilder.builder().setAmount(5000).setCurrency("USD").build(); + assertEquals(m.getAmount(), 5000); + assertEquals(m.getCurrency(), "USD"); + } +} diff --git a/cdi/pom.xml b/cdi/pom.xml new file mode 100644 index 0000000000..b771857938 --- /dev/null +++ b/cdi/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + com.baeldung + cdi + 1.0-SNAPSHOT + + + + org.springframework + spring-core + ${spring.version} + + + org.springframework + spring-context + ${spring.version} + + + + org.aspectj + aspectjweaver + 1.8.9 + + + org.jboss.weld.se + weld-se-core + 2.3.5.Final + + + + junit + junit + 4.12 + test + + + org.springframework + spring-test + ${spring.version} + test + + + + + + 4.3.1.RELEASE + + + \ No newline at end of file diff --git a/cdi/src/main/java/com/baeldung/interceptor/Audited.java b/cdi/src/main/java/com/baeldung/interceptor/Audited.java new file mode 100644 index 0000000000..3df4bef95e --- /dev/null +++ b/cdi/src/main/java/com/baeldung/interceptor/Audited.java @@ -0,0 +1,14 @@ +package com.baeldung.interceptor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.interceptor.InterceptorBinding; + +@InterceptorBinding +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Audited { +} diff --git a/cdi/src/main/java/com/baeldung/interceptor/AuditedInterceptor.java b/cdi/src/main/java/com/baeldung/interceptor/AuditedInterceptor.java new file mode 100644 index 0000000000..c62d9a4127 --- /dev/null +++ b/cdi/src/main/java/com/baeldung/interceptor/AuditedInterceptor.java @@ -0,0 +1,20 @@ +package com.baeldung.interceptor; + +import javax.interceptor.AroundInvoke; +import javax.interceptor.Interceptor; +import javax.interceptor.InvocationContext; + +@Audited +@Interceptor +public class AuditedInterceptor { + public static boolean calledBefore = false; + public static boolean calledAfter = false; + + @AroundInvoke + public Object auditMethod(InvocationContext ctx) throws Exception { + calledBefore = true; + Object result = ctx.proceed(); + calledAfter = true; + return result; + } +} diff --git a/cdi/src/main/java/com/baeldung/service/SuperService.java b/cdi/src/main/java/com/baeldung/service/SuperService.java new file mode 100644 index 0000000000..e15f049342 --- /dev/null +++ b/cdi/src/main/java/com/baeldung/service/SuperService.java @@ -0,0 +1,10 @@ +package com.baeldung.service; + +import com.baeldung.interceptor.Audited; + +public class SuperService { + @Audited + public String deliverService(String uid) { + return uid; + } +} diff --git a/cdi/src/main/java/com/baeldung/spring/aspect/SpringTestAspect.java b/cdi/src/main/java/com/baeldung/spring/aspect/SpringTestAspect.java new file mode 100644 index 0000000000..e48039706d --- /dev/null +++ b/cdi/src/main/java/com/baeldung/spring/aspect/SpringTestAspect.java @@ -0,0 +1,23 @@ +package com.baeldung.spring.aspect; + +import java.util.List; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.beans.factory.annotation.Autowired; + +@Aspect +public class SpringTestAspect { + @Autowired + private List accumulator; + + @Around("execution(* com.baeldung.spring.service.SpringSuperService.*(..))") + public Object auditMethod(ProceedingJoinPoint jp) throws Throwable { + String methodName = jp.getSignature().getName(); + accumulator.add("Call to " + methodName); + Object obj = jp.proceed(); + accumulator.add("Method called successfully: " + methodName); + return obj; + } +} diff --git a/cdi/src/main/java/com/baeldung/spring/configuration/AppConfig.java b/cdi/src/main/java/com/baeldung/spring/configuration/AppConfig.java new file mode 100644 index 0000000000..b30c4a1326 --- /dev/null +++ b/cdi/src/main/java/com/baeldung/spring/configuration/AppConfig.java @@ -0,0 +1,30 @@ +package com.baeldung.spring.configuration; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +import com.baeldung.spring.aspect.SpringTestAspect; +import com.baeldung.spring.service.SpringSuperService; + +@Configuration +@EnableAspectJAutoProxy +public class AppConfig { + @Bean + public SpringSuperService springSuperService() { + return new SpringSuperService(); + } + + @Bean + public SpringTestAspect springTestAspect() { + return new SpringTestAspect(); + } + + @Bean + public List getAccumulator() { + return new ArrayList(); + } +} diff --git a/cdi/src/main/java/com/baeldung/spring/service/SpringSuperService.java b/cdi/src/main/java/com/baeldung/spring/service/SpringSuperService.java new file mode 100644 index 0000000000..082eb2e0f8 --- /dev/null +++ b/cdi/src/main/java/com/baeldung/spring/service/SpringSuperService.java @@ -0,0 +1,7 @@ +package com.baeldung.spring.service; + +public class SpringSuperService { + public String getInfoFromService(String code) { + return code; + } +} diff --git a/cdi/src/main/resources/META-INF/beans.xml b/cdi/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000000..d41b35e7d9 --- /dev/null +++ b/cdi/src/main/resources/META-INF/beans.xml @@ -0,0 +1,8 @@ + + + com.baeldung.interceptor.AuditedInterceptor + + \ No newline at end of file diff --git a/cdi/src/test/java/com/baeldung/test/TestInterceptor.java b/cdi/src/test/java/com/baeldung/test/TestInterceptor.java new file mode 100644 index 0000000000..3529a796d2 --- /dev/null +++ b/cdi/src/test/java/com/baeldung/test/TestInterceptor.java @@ -0,0 +1,38 @@ +package com.baeldung.test; + +import org.jboss.weld.environment.se.Weld; +import org.jboss.weld.environment.se.WeldContainer; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.interceptor.AuditedInterceptor; +import com.baeldung.service.SuperService; + +public class TestInterceptor { + Weld weld; + WeldContainer container; + + @Before + public void init() { + weld = new Weld(); + container = weld.initialize(); + } + + @After + public void shutdown() { + weld.shutdown(); + } + + @Test + public void givenTheService_whenMethodAndInterceptorExecuted_thenOK() { + SuperService superService = container.select(SuperService.class).get(); + String code = "123456"; + superService.deliverService(code); + + Assert.assertTrue(AuditedInterceptor.calledBefore); + Assert.assertTrue(AuditedInterceptor.calledAfter); + } + +} diff --git a/cdi/src/test/java/com/baeldung/test/TestSpringInterceptor.java b/cdi/src/test/java/com/baeldung/test/TestSpringInterceptor.java new file mode 100644 index 0000000000..1f3a8d83e3 --- /dev/null +++ b/cdi/src/test/java/com/baeldung/test/TestSpringInterceptor.java @@ -0,0 +1,34 @@ +package com.baeldung.test; + +import static org.hamcrest.CoreMatchers.is; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.spring.configuration.AppConfig; +import com.baeldung.spring.service.SpringSuperService; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = { AppConfig.class }) +public class TestSpringInterceptor { + @Autowired + SpringSuperService springSuperService; + + @Autowired + private List accumulator; + + @Test + public void givenService_whenServiceAndAspectExecuted_thenOk() { + String code = "123456"; + String result = springSuperService.getInfoFromService(code); + Assert.assertThat(accumulator.size(), is(2)); + Assert.assertThat(accumulator.get(0), is("Call to getInfoFromService")); + Assert.assertThat(accumulator.get(1), is("Method called successfully: getInfoFromService")); + } +} diff --git a/core-java-8/.classpath b/core-java-8/.classpath deleted file mode 100644 index 5efa587d72..0000000000 --- a/core-java-8/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/core-java-8/.project b/core-java-8/.project deleted file mode 100644 index 235c555abb..0000000000 --- a/core-java-8/.project +++ /dev/null @@ -1,24 +0,0 @@ - - - core-java-8 - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - diff --git a/core-java-8/.settings/.jsdtscope b/core-java-8/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/core-java-8/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/core-java-8/.settings/org.eclipse.jdt.core.prefs b/core-java-8/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index c38ccc1294..0000000000 --- a/core-java-8/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,101 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=warning -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/core-java-8/.settings/org.eclipse.jdt.ui.prefs b/core-java-8/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index d84d2a7f8c..0000000000 --- a/core-java-8/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,57 +0,0 @@ -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_functional_interfaces=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_anonymous_class_creation=false -sp_cleanup.use_blocks=true -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_lambda=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/core-java-8/.settings/org.eclipse.m2e.core.prefs b/core-java-8/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/core-java-8/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/core-java-8/.springBeans b/core-java-8/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/core-java-8/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/core-java-8/README.md b/core-java-8/README.md index 9bb6bb811c..c130e6bd41 100644 --- a/core-java-8/README.md +++ b/core-java-8/README.md @@ -3,4 +3,22 @@ ## Core Java 8 Cookbooks and Examples ### Relevant Articles: -// - [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda) +- [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda) +- [Java – Directory Size](http://www.baeldung.com/java-folder-size) +- [Java – Try with Resources](http://www.baeldung.com/java-try-with-resources) +- [A Guide to the Java ExecutorService](http://www.baeldung.com/java-executor-service-tutorial) +- [Java 8 New Features](http://www.baeldung.com/java-8-new-features) +- [Lambda Expressions and Functional Interfaces: Tips and Best Practices](http://www.baeldung.com/java-8-lambda-expressions-tips) +- [The Double Colon Operator in Java 8](http://www.baeldung.com/java-8-double-colon-operator) +- [Java 8 Streams Advanced](http://www.baeldung.com/java-8-streams) +- [Java 8 Collectors](http://www.baeldung.com/java-8-collectors) +- [Convert String to int or Integer in Java](http://www.baeldung.com/java-convert-string-to-int-or-integer) +- [Convert char to String in Java](http://www.baeldung.com/java-convert-char-to-string) +- [Guide to Java 8’s Functional Interfaces](http://www.baeldung.com/java-8-functional-interfaces) +- [Guide To CompletableFuture](http://www.baeldung.com/java-completablefuture) +- [Introduction to Thread Pools in Java](http://www.baeldung.com/thread-pool-java-and-guava) +- [Guide to Java 8 Collectors](http://www.baeldung.com/java-8-collectors) +- [The Java 8 Stream API Tutorial](http://www.baeldung.com/java-8-streams) +- [New Features in Java 8](http://www.baeldung.com/java-8-new-features) +- [Introduction to Java 8 Streams](http://www.baeldung.com/java-8-streams-introduction) +- [Guide to the Fork/Join Framework in Java](http://www.baeldung.com/java-fork-join) diff --git a/core-java-8/pom.xml b/core-java-8/pom.xml index 07d3bcd146..566eb4e43a 100644 --- a/core-java-8/pom.xml +++ b/core-java-8/pom.xml @@ -1,10 +1,12 @@ - + 4.0.0 - org.baeldung - spring-rest - 0.1-SNAPSHOT - spring-rest + com.baeldung + 1.0.0-SNAPSHOT + core-java8 + + core-java8 @@ -40,6 +42,12 @@ 3.3.2 + + org.slf4j + slf4j-api + ${org.slf4j.version} + + @@ -56,6 +64,13 @@ test + + org.assertj + assertj-core + 3.5.1 + test + + org.mockito mockito-core @@ -97,6 +112,9 @@ + + UTF-8 + 1.7.13 1.0.13 @@ -114,9 +132,9 @@ 1.10.19 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 diff --git a/core-java-8/src/main/java/com/baeldung/datetime/UseDuration.java b/core-java-8/src/main/java/com/baeldung/datetime/UseDuration.java new file mode 100644 index 0000000000..125b6fbe38 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/datetime/UseDuration.java @@ -0,0 +1,16 @@ +package com.baeldung.datetime; + +import java.time.Duration; +import java.time.LocalTime; +import java.time.Period; + +public class UseDuration { + + public LocalTime modifyDates(LocalTime localTime,Duration duration){ + return localTime.plus(duration); + } + + public Duration getDifferenceBetweenDates(LocalTime localTime1,LocalTime localTime2){ + return Duration.between(localTime1, localTime2); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/datetime/UseLocalDate.java b/core-java-8/src/main/java/com/baeldung/datetime/UseLocalDate.java new file mode 100644 index 0000000000..47b1b3f67d --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/datetime/UseLocalDate.java @@ -0,0 +1,46 @@ +package com.baeldung.datetime; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalAdjusters; + +public class UseLocalDate { + + public LocalDate getLocalDateUsingFactoryOfMethod(int year, int month, int dayOfMonth){ + return LocalDate.of(year, month, dayOfMonth); + } + + public LocalDate getLocalDateUsingParseMethod(String representation){ + return LocalDate.parse(representation); + } + + public LocalDate getLocalDateFromClock(){ + LocalDate localDate = LocalDate.now(); + return localDate; + } + + public LocalDate getNextDay(LocalDate localDate){ + return localDate.plusDays(1); + } + + public LocalDate getPreviousDay(LocalDate localDate){ + return localDate.minus(1, ChronoUnit.DAYS); + } + + public DayOfWeek getDayOfWeek(LocalDate localDate){ + DayOfWeek day = localDate.getDayOfWeek(); + return day; + } + + public LocalDate getFirstDayOfMonth(){ + LocalDate firstDayOfMonth = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()); + return firstDayOfMonth; + } + + public LocalDateTime getStartOfDay(LocalDate localDate){ + LocalDateTime startofDay = localDate.atStartOfDay(); + return startofDay; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/datetime/UseLocalDateTime.java b/core-java-8/src/main/java/com/baeldung/datetime/UseLocalDateTime.java new file mode 100644 index 0000000000..7aa1eaa276 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/datetime/UseLocalDateTime.java @@ -0,0 +1,11 @@ +package com.baeldung.datetime; + +import java.time.LocalDateTime; + +public class UseLocalDateTime { + + public LocalDateTime getLocalDateTimeUsingParseMethod(String representation){ + return LocalDateTime.parse(representation); + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/datetime/UseLocalTime.java b/core-java-8/src/main/java/com/baeldung/datetime/UseLocalTime.java new file mode 100644 index 0000000000..e13fd10d6f --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/datetime/UseLocalTime.java @@ -0,0 +1,35 @@ +package com.baeldung.datetime; + +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; + +public class UseLocalTime { + + public LocalTime getLocalTimeUsingFactoryOfMethod(int hour, int min, int seconds){ + LocalTime localTime = LocalTime.of(hour, min, seconds); + return localTime; + } + + public LocalTime getLocalTimeUsingParseMethod(String timeRepresentation){ + LocalTime localTime = LocalTime.parse(timeRepresentation); + return localTime; + } + + public LocalTime getLocalTimeFromClock(){ + LocalTime localTime = LocalTime.now(); + return localTime; + } + + public LocalTime addAnHour(LocalTime localTime){ + LocalTime newTime = localTime.plus(1,ChronoUnit.HOURS); + return newTime; + } + + public int getHourFromLocalTime(LocalTime localTime){ + return localTime.getHour(); + } + + public LocalTime getLocalTimeWithMinuteSetToValue(LocalTime localTime, int minute){ + return localTime.withMinute(minute); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/datetime/UsePeriod.java b/core-java-8/src/main/java/com/baeldung/datetime/UsePeriod.java new file mode 100644 index 0000000000..326cfad650 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/datetime/UsePeriod.java @@ -0,0 +1,15 @@ +package com.baeldung.datetime; + +import java.time.LocalDate; +import java.time.Period; + +public class UsePeriod { + + public LocalDate modifyDates(LocalDate localDate,Period period){ + return localDate.plus(period); + } + + public Period getDifferenceBetweenDates(LocalDate localDate1,LocalDate localDate2){ + return Period.between(localDate1, localDate2); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/datetime/UseToInstant.java b/core-java-8/src/main/java/com/baeldung/datetime/UseToInstant.java new file mode 100644 index 0000000000..1ddb096cf6 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/datetime/UseToInstant.java @@ -0,0 +1,19 @@ +package com.baeldung.datetime; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Calendar; +import java.util.Date; + +public class UseToInstant { + + public LocalDateTime convertDateToLocalDate(Date date){ + LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); + return localDateTime; + } + + public LocalDateTime convertDateToLocalDate(Calendar calendar){ + LocalDateTime localDateTime = LocalDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault()); + return localDateTime; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/datetime/UseZonedDateTime.java b/core-java-8/src/main/java/com/baeldung/datetime/UseZonedDateTime.java new file mode 100644 index 0000000000..0369de9835 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/datetime/UseZonedDateTime.java @@ -0,0 +1,13 @@ +package com.baeldung.datetime; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +public class UseZonedDateTime { + + public ZonedDateTime getZonedDateTime(LocalDateTime localDateTime,ZoneId zoneId){ + ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId); + return zonedDateTime; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/enums/Pizza.java b/core-java-8/src/main/java/com/baeldung/enums/Pizza.java new file mode 100644 index 0000000000..5bc2d9a9eb --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/enums/Pizza.java @@ -0,0 +1,91 @@ +package com.baeldung.enums; + +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; +import java.util.stream.Collectors; + +public class Pizza { + + private static EnumSet deliveredPizzaStatuses = + EnumSet.of(PizzaStatusEnum.DELIVERED); + + private PizzaStatusEnum status; + + public enum PizzaStatusEnum { + ORDERED(5) { + @Override + public boolean isOrdered() { + return true; + } + }, + READY(2) { + @Override + public boolean isReady() { + return true; + } + }, + DELIVERED(0) { + @Override + public boolean isDelivered() { + return true; + } + }; + + private int timeToDelivery; + + public boolean isOrdered() { + return false; + } + + public boolean isReady() { + return false; + } + + public boolean isDelivered() { + return false; + } + + public int getTimeToDelivery() { + return timeToDelivery; + } + + PizzaStatusEnum(int timeToDelivery) { + this.timeToDelivery = timeToDelivery; + } + } + + public PizzaStatusEnum getStatus() { + return status; + } + + public void setStatus(PizzaStatusEnum status) { + this.status = status; + } + + public boolean isDeliverable() { + return this.status.isReady(); + } + + public void printTimeToDeliver() { + System.out.println("Time to delivery is " + this.getStatus().getTimeToDelivery() + " days"); + } + + public static List getAllUndeliveredPizzas(List input) { + return input.stream().filter((s) -> !deliveredPizzaStatuses.contains(s.getStatus())).collect(Collectors.toList()); + } + + public static EnumMap> groupPizzaByStatus(List pzList) { + return pzList.stream().collect( + Collectors.groupingBy(Pizza::getStatus, + () -> new EnumMap<>(PizzaStatusEnum.class), Collectors.toList())); + } + + public void deliver() { + if (isDeliverable()) { + PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy().deliver(this); + this.setStatus(PizzaStatusEnum.DELIVERED); + } + } + +} \ No newline at end of file diff --git a/core-java-8/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java b/core-java-8/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java new file mode 100644 index 0000000000..ed65919387 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java @@ -0,0 +1,18 @@ +package com.baeldung.enums; + +public enum PizzaDeliveryStrategy { + EXPRESS { + @Override + public void deliver(Pizza pz) { + System.out.println("Pizza will be delivered in express mode"); + } + }, + NORMAL { + @Override + public void deliver(Pizza pz) { + System.out.println("Pizza will be delivered in normal mode"); + } + }; + + public abstract void deliver(Pizza pz); +} diff --git a/core-java-8/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java b/core-java-8/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java new file mode 100644 index 0000000000..5ccff5e959 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java @@ -0,0 +1,22 @@ +package com.baeldung.enums; + + +public enum PizzaDeliverySystemConfiguration { + INSTANCE; + + PizzaDeliverySystemConfiguration() { + // Do the configuration initialization which + // involves overriding defaults like delivery strategy + } + + private PizzaDeliveryStrategy deliveryStrategy = PizzaDeliveryStrategy.NORMAL; + + public static PizzaDeliverySystemConfiguration getInstance() { + return INSTANCE; + } + + public PizzaDeliveryStrategy getDeliveryStrategy() { + return deliveryStrategy; + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java b/core-java-8/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java new file mode 100644 index 0000000000..f1ab2d8d09 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/forkjoin/CustomRecursiveAction.java @@ -0,0 +1,49 @@ +package com.baeldung.forkjoin; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveAction; +import java.util.logging.Logger; + +public class CustomRecursiveAction extends RecursiveAction { + + private String workLoad = ""; + private static final int THRESHOLD = 4; + + private static Logger logger = Logger.getAnonymousLogger(); + + public CustomRecursiveAction(String workLoad) { + this.workLoad = workLoad; + } + + @Override + protected void compute() { + + if (workLoad.length() > THRESHOLD) { + ForkJoinTask.invokeAll(createSubtasks()); + } else { + processing(workLoad); + } + } + + private Collection createSubtasks() { + + List subtasks = + new ArrayList<>(); + + String partOne = workLoad.substring(0, workLoad.length() / 2); + String partTwo = workLoad.substring(workLoad.length() / 2, workLoad.length()); + + subtasks.add(new CustomRecursiveAction(partOne)); + subtasks.add(new CustomRecursiveAction(partTwo)); + + return subtasks; + } + + private void processing(String work) { + String result = work.toUpperCase(); + logger.info("This result - (" + result + ") - was processed by " + Thread.currentThread().getName()); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java b/core-java-8/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java new file mode 100644 index 0000000000..5d4d97b805 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/forkjoin/CustomRecursiveTask.java @@ -0,0 +1,51 @@ +package com.baeldung.forkjoin; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveTask; + +public class CustomRecursiveTask extends RecursiveTask { + + private int[] arr; + + private static final int THRESHOLD = 20; + + public CustomRecursiveTask(int[] arr) { + this.arr = arr; + } + + @Override + protected Integer compute() { + + if (arr.length > THRESHOLD) { + + return ForkJoinTask.invokeAll(createSubtasks()) + .stream() + .mapToInt(ForkJoinTask::join) + .sum(); + + } else { + return processing(arr); + } + } + + private Collection createSubtasks() { + List dividedTasks = new ArrayList<>(); + dividedTasks.add(new CustomRecursiveTask( + Arrays.copyOfRange(arr, 0, arr.length / 2))); + dividedTasks.add(new CustomRecursiveTask( + Arrays.copyOfRange(arr, arr.length / 2, arr.length))); + return dividedTasks; + } + + private Integer processing(int[] arr) { + return Arrays.stream(arr) + .filter(a -> a > 10 && a < 27) + .map(a -> a * 10) + .sum(); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java b/core-java-8/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java new file mode 100644 index 0000000000..521616600f --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/forkjoin/util/PoolUtil.java @@ -0,0 +1,10 @@ +package com.baeldung.forkjoin.util; + + +import java.util.concurrent.ForkJoinPool; + +public class PoolUtil { + + public static ForkJoinPool forkJoinPool = new ForkJoinPool(2); + +} diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/Address.java b/core-java-8/src/main/java/com/baeldung/java_8_features/Address.java new file mode 100644 index 0000000000..1f89503288 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/java_8_features/Address.java @@ -0,0 +1,14 @@ +package com.baeldung.java_8_features; + +public class Address { + + private String street; + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/CustomException.java b/core-java-8/src/main/java/com/baeldung/java_8_features/CustomException.java new file mode 100644 index 0000000000..ff9be6ab06 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/java_8_features/CustomException.java @@ -0,0 +1,4 @@ +package com.baeldung.java_8_features; + +public class CustomException extends RuntimeException { +} diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/Detail.java b/core-java-8/src/main/java/com/baeldung/java_8_features/Detail.java new file mode 100644 index 0000000000..811937dba7 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/java_8_features/Detail.java @@ -0,0 +1,13 @@ +package com.baeldung.java_8_features; + +import java.util.Arrays; +import java.util.List; + +public class Detail { + + private static final List PARTS = Arrays.asList("turbine", "pump"); + + public List getParts() { + return PARTS; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalAddress.java b/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalAddress.java new file mode 100644 index 0000000000..8d6c517ac5 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalAddress.java @@ -0,0 +1,16 @@ +package com.baeldung.java_8_features; + +import java.util.Optional; + +public class OptionalAddress { + + private String street; + + public Optional getStreet() { + return Optional.ofNullable(street); + } + + public void setStreet(String street) { + this.street = street; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalUser.java b/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalUser.java new file mode 100644 index 0000000000..ff06cd21d6 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/java_8_features/OptionalUser.java @@ -0,0 +1,16 @@ +package com.baeldung.java_8_features; + +import java.util.Optional; + +public class OptionalUser { + + private OptionalAddress address; + + public Optional getAddress() { + return Optional.of(address); + } + + public void setAddress(OptionalAddress address) { + this.address = address; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/User.java b/core-java-8/src/main/java/com/baeldung/java_8_features/User.java new file mode 100644 index 0000000000..3708d276c8 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/java_8_features/User.java @@ -0,0 +1,40 @@ +package com.baeldung.java_8_features; + +import java.util.Optional; + +public class User { + + private String name; + + private Address address; + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public User() { + } + + public User(String name) { + this.name = name; + } + + public static boolean isRealUser(User user) { + return true; + } + + public String getOrThrow() { + String value = null; + Optional valueOpt = Optional.ofNullable(value); + String result = valueOpt.orElseThrow(CustomException::new).toUpperCase(); + return result; + } + + public boolean isLegalName(String name) { + return name.length() > 3 && name.length() < 16; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/Vehicle.java b/core-java-8/src/main/java/com/baeldung/java_8_features/Vehicle.java new file mode 100644 index 0000000000..011173bcaf --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/java_8_features/Vehicle.java @@ -0,0 +1,18 @@ +package com.baeldung.java_8_features; + +public interface Vehicle { + + void moveTo(long altitude, long longitude); + + static String producer() { + return "N&F Vehicles"; + } + + default long[] startPosition() { + return new long[]{23, 15}; + } + + default String getOverview() { + return "ATV made by " + producer(); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/java_8_features/VehicleImpl.java b/core-java-8/src/main/java/com/baeldung/java_8_features/VehicleImpl.java new file mode 100644 index 0000000000..83e55f5f4d --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/java_8_features/VehicleImpl.java @@ -0,0 +1,9 @@ +package com.baeldung.java_8_features; + +public class VehicleImpl implements Vehicle { + + @Override + public void moveTo(long altitude, long longitude) { + //do nothing + } +} diff --git a/core-java-8/src/main/java/com/baeldung/streamApi/Product.java b/core-java-8/src/main/java/com/baeldung/streamApi/Product.java new file mode 100644 index 0000000000..18f3a61904 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/streamApi/Product.java @@ -0,0 +1,51 @@ +package com.baeldung.streamApi; + +import java.util.List; +import java.util.Optional; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +/** + * Created by Alex Vengr + */ +public class Product { + + private int price; + + private String name; + + private boolean utilize; + + public Product(int price, String name) { + this(price); + this.name = name; + } + + public Product(int price) { + this.price = price; + } + + public Product() { + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + public static Stream streamOf(List list) { + return (list == null || list.isEmpty()) ? Stream.empty() : list.stream(); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/threadpool/CountingTask.java b/core-java-8/src/main/java/com/baeldung/threadpool/CountingTask.java new file mode 100644 index 0000000000..05aa14c5ae --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/threadpool/CountingTask.java @@ -0,0 +1,22 @@ +package com.baeldung.threadpool; + +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveTask; +import java.util.stream.Collectors; + +public class CountingTask extends RecursiveTask { + + private final TreeNode node; + + public CountingTask(TreeNode node) { + this.node = node; + } + + @Override + protected Integer compute() { + return node.value + node.children.stream() + .map(childNode -> new CountingTask(childNode).fork()) + .collect(Collectors.summingInt(ForkJoinTask::join)); + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java b/core-java-8/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java new file mode 100644 index 0000000000..4775fde930 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/threadpool/ExitingExecutorServiceExample.java @@ -0,0 +1,29 @@ +package com.baeldung.threadpool; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import com.google.common.util.concurrent.MoreExecutors; + +/** + * This class demonstrates the usage of Guava's exiting executor services that keep the VM from hanging. + * Without the exiting executor service, the task would hang indefinitely. + * This behaviour cannot be demonstrated in JUnit tests, as JUnit kills the VM after the tests. + */ +public class ExitingExecutorServiceExample { + + public static void main(String... args) { + + ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5); + ExecutorService executorService = MoreExecutors.getExitingExecutorService(executor, 100, TimeUnit.MILLISECONDS); + + executorService.submit(() -> { + while (true) { + } + }); + + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/threadpool/TreeNode.java b/core-java-8/src/main/java/com/baeldung/threadpool/TreeNode.java new file mode 100644 index 0000000000..9b43152074 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/threadpool/TreeNode.java @@ -0,0 +1,18 @@ +package com.baeldung.threadpool; + +import java.util.Set; + +import com.google.common.collect.Sets; + +public class TreeNode { + + int value; + + Set children; + + public TreeNode(int value, TreeNode... children) { + this.value = value; + this.children = Sets.newHashSet(children); + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/unzip/UnzipFile.java b/core-java-8/src/main/java/com/baeldung/unzip/UnzipFile.java new file mode 100644 index 0000000000..6648d5f926 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/unzip/UnzipFile.java @@ -0,0 +1,30 @@ +package com.baeldung.unzip; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class UnzipFile { + public static void main(final String[] args) throws IOException { + final String fileZip = "src/main/resources/compressed.zip"; + final byte[] buffer = new byte[1024]; + final ZipInputStream zis = new ZipInputStream(new FileInputStream(fileZip)); + ZipEntry zipEntry = zis.getNextEntry(); + while (zipEntry != null) { + final String fileName = zipEntry.getName(); + final File newFile = new File("src/main/resources/unzipTest/" + fileName); + final FileOutputStream fos = new FileOutputStream(newFile); + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + fos.close(); + zipEntry = zis.getNextEntry(); + } + zis.closeEntry(); + zis.close(); + } +} \ No newline at end of file diff --git a/core-java-8/src/main/java/com/baeldung/zip/ZipDirectory.java b/core-java-8/src/main/java/com/baeldung/zip/ZipDirectory.java new file mode 100644 index 0000000000..7da71a093d --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/zip/ZipDirectory.java @@ -0,0 +1,43 @@ +package com.baeldung.zip; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public class ZipDirectory { + public static void main(final String[] args) throws IOException { + final String sourceFile = "src/main/resources/zipTest"; + final FileOutputStream fos = new FileOutputStream("src/main/resources/dirCompressed.zip"); + final ZipOutputStream zipOut = new ZipOutputStream(fos); + final File fileToZip = new File(sourceFile); + + zipFile(fileToZip, fileToZip.getName(), zipOut); + zipOut.close(); + fos.close(); + } + + private static void zipFile(final File fileToZip, final String fileName, final ZipOutputStream zipOut) throws IOException { + if (fileToZip.isHidden()) { + return; + } + if (fileToZip.isDirectory()) { + final File[] children = fileToZip.listFiles(); + for (final File childFile : children) { + zipFile(childFile, fileName + "/" + childFile.getName(), zipOut); + } + return; + } + final FileInputStream fis = new FileInputStream(fileToZip); + final ZipEntry zipEntry = new ZipEntry(fileName); + zipOut.putNextEntry(zipEntry); + final byte[] bytes = new byte[1024]; + int length; + while ((length = fis.read(bytes)) >= 0) { + zipOut.write(bytes, 0, length); + } + fis.close(); + } +} \ No newline at end of file diff --git a/core-java-8/src/main/java/com/baeldung/zip/ZipFile.java b/core-java-8/src/main/java/com/baeldung/zip/ZipFile.java new file mode 100644 index 0000000000..f9ccac9713 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/zip/ZipFile.java @@ -0,0 +1,28 @@ +package com.baeldung.zip; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public class ZipFile { + public static void main(final String[] args) throws IOException { + final String sourceFile = "src/main/resources/zipTest/test1.txt"; + final FileOutputStream fos = new FileOutputStream("src/main/resources/compressed.zip"); + final ZipOutputStream zipOut = new ZipOutputStream(fos); + final File fileToZip = new File(sourceFile); + final FileInputStream fis = new FileInputStream(fileToZip); + final ZipEntry zipEntry = new ZipEntry(fileToZip.getName()); + zipOut.putNextEntry(zipEntry); + final byte[] bytes = new byte[1024]; + int length; + while ((length = fis.read(bytes)) >= 0) { + zipOut.write(bytes, 0, length); + } + zipOut.close(); + fis.close(); + fos.close(); + } +} \ No newline at end of file diff --git a/core-java-8/src/main/java/com/baeldung/zip/ZipMultipleFiles.java b/core-java-8/src/main/java/com/baeldung/zip/ZipMultipleFiles.java new file mode 100644 index 0000000000..fc86147e43 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/zip/ZipMultipleFiles.java @@ -0,0 +1,33 @@ +package com.baeldung.zip; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public class ZipMultipleFiles { + public static void main(final String[] args) throws IOException { + final List srcFiles = Arrays.asList("src/main/resources/zipTest/test1.txt", "src/main/resources/zipTest/test2.txt"); + final FileOutputStream fos = new FileOutputStream("src/main/resources/multiCompressed.zip"); + final ZipOutputStream zipOut = new ZipOutputStream(fos); + for (final String srcFile : srcFiles) { + final File fileToZip = new File(srcFile); + final FileInputStream fis = new FileInputStream(fileToZip); + final ZipEntry zipEntry = new ZipEntry(fileToZip.getName()); + zipOut.putNextEntry(zipEntry); + + final byte[] bytes = new byte[1024]; + int length; + while ((length = fis.read(bytes)) >= 0) { + zipOut.write(bytes, 0, length); + } + fis.close(); + } + zipOut.close(); + fos.close(); + } +} \ No newline at end of file diff --git a/core-java-8/src/main/resources/compressed.zip b/core-java-8/src/main/resources/compressed.zip new file mode 100644 index 0000000000..03f840ae2b Binary files /dev/null and b/core-java-8/src/main/resources/compressed.zip differ diff --git a/core-java-8/src/main/resources/dirCompressed.zip b/core-java-8/src/main/resources/dirCompressed.zip new file mode 100644 index 0000000000..f42d3aa5c6 Binary files /dev/null and b/core-java-8/src/main/resources/dirCompressed.zip differ diff --git a/core-java-8/src/main/resources/fileTest.txt b/core-java-8/src/main/resources/fileTest.txt new file mode 100644 index 0000000000..ce4bea208b --- /dev/null +++ b/core-java-8/src/main/resources/fileTest.txt @@ -0,0 +1 @@ +Hello World from fileTest.txt!!! \ No newline at end of file diff --git a/core-java-8/src/main/resources/logback.xml b/core-java-8/src/main/resources/logback.xml index 62d0ea5037..eefdc7a337 100644 --- a/core-java-8/src/main/resources/logback.xml +++ b/core-java-8/src/main/resources/logback.xml @@ -10,7 +10,7 @@ - + \ No newline at end of file diff --git a/core-java-8/src/main/resources/multiCompressed.zip b/core-java-8/src/main/resources/multiCompressed.zip new file mode 100644 index 0000000000..002e70ef81 Binary files /dev/null and b/core-java-8/src/main/resources/multiCompressed.zip differ diff --git a/core-java-8/src/main/resources/unzipTest/test1.txt b/core-java-8/src/main/resources/unzipTest/test1.txt new file mode 100644 index 0000000000..c57eff55eb --- /dev/null +++ b/core-java-8/src/main/resources/unzipTest/test1.txt @@ -0,0 +1 @@ +Hello World! \ No newline at end of file diff --git a/core-java-8/src/main/resources/zipTest/test1.txt b/core-java-8/src/main/resources/zipTest/test1.txt new file mode 100644 index 0000000000..c57eff55eb --- /dev/null +++ b/core-java-8/src/main/resources/zipTest/test1.txt @@ -0,0 +1 @@ +Hello World! \ No newline at end of file diff --git a/core-java-8/src/main/resources/zipTest/test2.txt b/core-java-8/src/main/resources/zipTest/test2.txt new file mode 100644 index 0000000000..f0fb0f14d1 --- /dev/null +++ b/core-java-8/src/main/resources/zipTest/test2.txt @@ -0,0 +1 @@ +My Name is John \ No newline at end of file diff --git a/core-java-8/src/main/resources/zipTest/testFolder/test3.txt b/core-java-8/src/main/resources/zipTest/testFolder/test3.txt new file mode 100644 index 0000000000..882edb168e --- /dev/null +++ b/core-java-8/src/main/resources/zipTest/testFolder/test3.txt @@ -0,0 +1 @@ +My Name is Tom \ No newline at end of file diff --git a/core-java-8/src/main/resources/zipTest/testFolder/test4.txt b/core-java-8/src/main/resources/zipTest/testFolder/test4.txt new file mode 100644 index 0000000000..a78c3fadc8 --- /dev/null +++ b/core-java-8/src/main/resources/zipTest/testFolder/test4.txt @@ -0,0 +1 @@ +My Name is Jane \ No newline at end of file diff --git a/core-java-8/src/test/java/com/baeldung/CharToStringTest.java b/core-java-8/src/test/java/com/baeldung/CharToStringTest.java new file mode 100644 index 0000000000..d91016d104 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/CharToStringTest.java @@ -0,0 +1,53 @@ +package com.baeldung; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CharToStringTest { + + @Test + public void givenChar_whenCallingStringValueOf_shouldConvertToString(){ + final char givenChar = 'x'; + + final String result = String.valueOf(givenChar); + + assertThat(result).isEqualTo("x"); + } + + @Test + public void givenChar_whenCallingToStringOnCharacter_shouldConvertToString(){ + final char givenChar = 'x'; + + final String result = Character.toString(givenChar); + + assertThat(result).isEqualTo("x"); + } + + @Test + public void givenChar_whenCallingCharacterConstructor_shouldConvertToString3(){ + final char givenChar = 'x'; + + final String result = new Character(givenChar).toString(); + + assertThat(result).isEqualTo("x"); + } + + @Test + public void givenChar_whenConcatenated_shouldConvertToString4(){ + final char givenChar = 'x'; + + final String result = givenChar + ""; + + assertThat(result).isEqualTo("x"); + } + + @Test + public void givenChar_whenFormated_shouldConvertToString5(){ + final char givenChar = 'x'; + + final String result = String.format("%c", givenChar); + + assertThat(result).isEqualTo("x"); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/RandomListElementTest.java b/core-java-8/src/test/java/com/baeldung/RandomListElementTest.java new file mode 100644 index 0000000000..1918c801dc --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/RandomListElementTest.java @@ -0,0 +1,71 @@ +package com.baeldung; + +import com.google.common.collect.Lists; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +public class RandomListElementTest { + + @Test + public void givenList_whenRandomIndexChosen_shouldReturnARandomElementUsingRandom() { + List givenList = Lists.newArrayList(1, 2, 3); + Random rand = new Random(); + + givenList.get(rand.nextInt(givenList.size())); + } + + @Test + public void givenList_whenRandomIndexChosen_shouldReturnARandomElementUsingMathRandom() { + List givenList = Lists.newArrayList(1, 2, 3); + + givenList.get((int)(Math.random() * givenList.size())); + } + + @Test + public void givenList_whenNumberElementsChosen_shouldReturnRandomElementsRepeat() { + Random rand = new Random(); + List givenList = Lists.newArrayList("one", "two", "three", "four"); + + int numberOfElements = 2; + + for (int i = 0; i < numberOfElements; i++) { + int randomIndex = rand.nextInt(givenList.size()); + givenList.get(randomIndex); + } + } + + @Test + public void givenList_whenNumberElementsChosen_shouldReturnRandomElementsNoRepeat() { + Random rand = new Random(); + List givenList = Lists.newArrayList("one", "two", "three", "four"); + + int numberOfElements = 2; + + for (int i = 0; i < numberOfElements; i++) { + int randomIndex = rand.nextInt(givenList.size()); + givenList.get(randomIndex); + givenList.remove(randomIndex); + } + } + + @Test + public void givenList_whenSeriesLengthChosen_shouldReturnRandomSeries() { + List givenList = Lists.newArrayList(1, 2, 3, 4, 5, 6); + Collections.shuffle(givenList); + + int randomSeriesLength = 3; + + givenList.subList(0, randomSeriesLength - 1); + } + + @Test + public void givenList_whenRandomIndexChosen_shouldReturnElementThreadSafely() { + List givenList = Lists.newArrayList(1, 2, 3, 4, 5, 6); + int randomIndex = ThreadLocalRandom.current().nextInt(10) % givenList.size(); + + givenList.get(randomIndex); + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/StringToIntOrIntegerTest.java b/core-java-8/src/test/java/com/baeldung/StringToIntOrIntegerTest.java new file mode 100644 index 0000000000..6c1493d89b --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/StringToIntOrIntegerTest.java @@ -0,0 +1,62 @@ +package com.baeldung; + +import com.google.common.primitives.Ints; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class StringToIntOrIntegerTest { + + @Test + public void givenString_whenParsingInt_shouldConvertToInt() { + String givenString = "42"; + + int result = Integer.parseInt(givenString); + + assertThat(result).isEqualTo(42); + } + + + @Test + public void givenString_whenCallingIntegerValueOf_shouldConvertToInt() { + String givenString = "42"; + + Integer result = Integer.valueOf(givenString); + + assertThat(result).isEqualTo(new Integer(42)); + } + + @Test + public void givenString_whenCallingIntegerConstructor_shouldConvertToInt() { + String givenString = "42"; + + Integer result = new Integer(givenString); + + assertThat(result).isEqualTo(new Integer(42)); + } + + @Test + public void givenString_whenCallingIntegerDecode_shouldConvertToInt() { + String givenString = "42"; + + int result = Integer.decode(givenString); + + assertThat(result).isEqualTo(42); + } + + @Test + public void givenString_whenTryParse_shouldConvertToInt() { + String givenString = "42"; + + Integer result = Ints.tryParse(givenString); + + assertThat(result).isEqualTo(42); + } + + @Test(expected = NumberFormatException.class) + public void givenInvalidInput_whenParsingInt_shouldThrow() { + String givenString = "nan"; + Integer.parseInt(givenString); + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsTest.java b/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsTest.java new file mode 100644 index 0000000000..d94f72b685 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/collectors/Java8CollectorsTest.java @@ -0,0 +1,265 @@ +package com.baeldung.collectors; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.DoubleSummaryStatistics; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collector; + +import static com.google.common.collect.Sets.newHashSet; +import static java.util.stream.Collectors.averagingDouble; +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.counting; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.maxBy; +import static java.util.stream.Collectors.partitioningBy; +import static java.util.stream.Collectors.summarizingDouble; +import static java.util.stream.Collectors.summingDouble; +import static java.util.stream.Collectors.toCollection; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.toSet; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class Java8CollectorsTest { + + private final List givenList = Arrays.asList("a", "bb", "ccc", "dd"); + + @Test + public void whenCollectingToList_shouldCollectToList() throws Exception { + final List result = givenList.stream() + .collect(toList()); + + assertThat(result) + .containsAll(givenList); + } + + @Test + public void whenCollectingToList_shouldCollectToSet() throws Exception { + final Set result = givenList.stream() + .collect(toSet()); + + assertThat(result) + .containsAll(givenList); + } + + @Test + public void whenCollectingToCollection_shouldCollectToCollection() throws Exception { + final List result = givenList.stream() + .collect(toCollection(LinkedList::new)); + + assertThat(result) + .containsAll(givenList) + .isInstanceOf(LinkedList.class); + } + + @Test + public void whenCollectingToImmutableCollection_shouldThrowException() throws Exception { + assertThatThrownBy(() -> { + givenList.stream() + .collect(toCollection(ImmutableList::of)); + }).isInstanceOf(UnsupportedOperationException.class); + + } + + @Test + public void whenCollectingToMap_shouldCollectToMap() throws Exception { + final Map result = givenList.stream() + .collect(toMap(Function.identity(), String::length)); + + assertThat(result) + .containsEntry("a", 1) + .containsEntry("bb", 2) + .containsEntry("ccc", 3) + .containsEntry("dd", 2); + } + + @Test + public void whenCollectingToMap_shouldCollectToMapMerging() throws Exception { + final Map result = givenList.stream() + .collect(toMap(Function.identity(), String::length, (i1, i2) -> i1)); + + assertThat(result) + .containsEntry("a", 1) + .containsEntry("bb", 2) + .containsEntry("ccc", 3) + .containsEntry("dd", 2); + } + + @Test + public void whenCollectingAndThen_shouldCollect() throws Exception { + final List result = givenList.stream() + .collect(collectingAndThen(toList(), ImmutableList::copyOf)); + + assertThat(result) + .containsAll(givenList) + .isInstanceOf(ImmutableList.class); + } + + @Test + public void whenJoining_shouldJoin() throws Exception { + final String result = givenList.stream() + .collect(joining()); + + assertThat(result) + .isEqualTo("abbcccdd"); + } + + @Test + public void whenJoiningWithSeparator_shouldJoinWithSeparator() throws Exception { + final String result = givenList.stream() + .collect(joining(" ")); + + assertThat(result) + .isEqualTo("a bb ccc dd"); + } + + @Test + public void whenJoiningWithSeparatorAndPrefixAndPostfix_shouldJoinWithSeparatorPrePost() throws Exception { + final String result = givenList.stream() + .collect(joining(" ", "PRE-", "-POST")); + + assertThat(result) + .isEqualTo("PRE-a bb ccc dd-POST"); + } + + @Test + public void whenPartitioningBy_shouldPartition() throws Exception { + final Map> result = givenList.stream() + .collect(partitioningBy(s -> s.length() > 2)); + + assertThat(result) + .containsKeys(true, false) + .satisfies(booleanListMap -> { + assertThat(booleanListMap.get(true)) + .contains("ccc"); + + assertThat(booleanListMap.get(false)) + .contains("a", "bb", "dd"); + }); + } + + @Test + public void whenCounting_shouldCount() throws Exception { + final Long result = givenList.stream() + .collect(counting()); + + assertThat(result) + .isEqualTo(4); + } + + @Test + public void whenSummarizing_shouldSummarize() throws Exception { + final DoubleSummaryStatistics result = givenList.stream() + .collect(summarizingDouble(String::length)); + + assertThat(result.getAverage()) + .isEqualTo(2); + assertThat(result.getCount()) + .isEqualTo(4); + assertThat(result.getMax()) + .isEqualTo(3); + assertThat(result.getMin()) + .isEqualTo(1); + assertThat(result.getSum()) + .isEqualTo(8); + } + + @Test + public void whenAveraging_shouldAverage() throws Exception { + final Double result = givenList.stream() + .collect(averagingDouble(String::length)); + + assertThat(result) + .isEqualTo(2); + } + + @Test + public void whenSumming_shouldSum() throws Exception { + final Double result = givenList.stream() + .collect(summingDouble(String::length)); + + assertThat(result) + .isEqualTo(8); + } + + @Test + public void whenMaxingBy_shouldMaxBy() throws Exception { + final Optional result = givenList.stream() + .collect(maxBy(Comparator.naturalOrder())); + + assertThat(result) + .isPresent() + .hasValue("dd"); + } + + @Test + public void whenGroupingBy_shouldGroupBy() throws Exception { + final Map> result = givenList.stream() + .collect(groupingBy(String::length, toSet())); + + assertThat(result) + .containsEntry(1, newHashSet("a")) + .containsEntry(2, newHashSet("bb", "dd")) + .containsEntry(3, newHashSet("ccc")); + } + + + @Test + public void whenCreatingCustomCollector_shouldCollect() throws Exception { + final ImmutableSet result = givenList.stream() + .collect(toImmutableSet()); + + assertThat(result) + .isInstanceOf(ImmutableSet.class) + .contains("a", "bb", "ccc", "dd"); + + } + + private static ImmutableSetCollector toImmutableSet() { + return new ImmutableSetCollector<>(); + } + + private static class ImmutableSetCollector implements Collector, ImmutableSet> { + + @Override + public Supplier> supplier() { + return ImmutableSet::builder; + } + + @Override + public BiConsumer, T> accumulator() { + return ImmutableSet.Builder::add; + } + + @Override + public BinaryOperator> combiner() { + return (left, right) -> left.addAll(right.build()); + } + + @Override + public Function, ImmutableSet> finisher() { + return ImmutableSet.Builder::build; + } + + @Override + public Set characteristics() { + return Sets.immutableEnumSet(Characteristics.UNORDERED); + } + } +} diff --git a/core-java-8/src/test/java/com/baeldung/completablefuture/CompletableFutureTest.java b/core-java-8/src/test/java/com/baeldung/completablefuture/CompletableFutureTest.java new file mode 100644 index 0000000000..5363a73afa --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/completablefuture/CompletableFutureTest.java @@ -0,0 +1,209 @@ +package com.baeldung.completablefuture; + +import java.util.concurrent.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class CompletableFutureTest { + + @Test + public void whenRunningCompletableFutureAsynchronously_thenGetMethodWaitsForResult() throws InterruptedException, ExecutionException { + + Future completableFuture = calculateAsync(); + + String result = completableFuture.get(); + assertEquals("Hello", result); + + } + + public Future calculateAsync() throws InterruptedException { + CompletableFuture completableFuture = new CompletableFuture<>(); + + Executors.newCachedThreadPool().submit(() -> { + Thread.sleep(500); + completableFuture.complete("Hello"); + return null; + }); + + return completableFuture; + } + + @Test + public void whenRunningCompletableFutureWithResult_thenGetMethodReturnsImmediately() throws InterruptedException, ExecutionException { + + Future completableFuture = CompletableFuture.completedFuture("Hello"); + + String result = completableFuture.get(); + assertEquals("Hello", result); + + } + + + public Future calculateAsyncWithCancellation() throws InterruptedException { + CompletableFuture completableFuture = new CompletableFuture<>(); + + Executors.newCachedThreadPool().submit(() -> { + Thread.sleep(500); + completableFuture.cancel(false); + return null; + }); + + return completableFuture; + } + + + @Test(expected = CancellationException.class) + public void whenCancelingTheFuture_thenThrowsCancellationException() throws ExecutionException, InterruptedException { + + Future future = calculateAsyncWithCancellation(); + future.get(); + + } + + @Test + public void whenCreatingCompletableFutureWithSupplyAsync_thenFutureReturnsValue() throws ExecutionException, InterruptedException { + + CompletableFuture future = CompletableFuture.supplyAsync(() -> "Hello"); + + assertEquals("Hello", future.get()); + + } + + @Test + public void whenAddingThenAcceptToFuture_thenFunctionExecutesAfterComputationIsFinished() throws ExecutionException, InterruptedException { + + CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello"); + + CompletableFuture future = completableFuture.thenAccept(s -> System.out.println("Computation returned: " + s)); + + future.get(); + + } + + @Test + public void whenAddingThenRunToFuture_thenFunctionExecutesAfterComputationIsFinished() throws ExecutionException, InterruptedException { + + CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello"); + + CompletableFuture future = completableFuture.thenRun(() -> System.out.println("Computation finished.")); + + future.get(); + + } + + @Test + public void whenAddingThenApplyToFuture_thenFunctionExecutesAfterComputationIsFinished() throws ExecutionException, InterruptedException { + + CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello"); + + CompletableFuture future = completableFuture.thenApply(s -> s + " World"); + + assertEquals("Hello World", future.get()); + + } + + @Test + public void whenUsingThenCompose_thenFuturesExecuteSequentially() throws ExecutionException, InterruptedException { + + CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello") + .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World")); + + assertEquals("Hello World", completableFuture.get()); + + } + + @Test + public void whenUsingThenCombine_thenWaitForExecutionOfBothFutures() throws ExecutionException, InterruptedException { + + CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello") + .thenCombine(CompletableFuture.supplyAsync(() -> " World"), + (s1, s2) -> s1 + s2); + + assertEquals("Hello World", completableFuture.get()); + + } + + @Test + public void whenUsingThenAcceptBoth_thenWaitForExecutionOfBothFutures() throws ExecutionException, InterruptedException { + + CompletableFuture.supplyAsync(() -> "Hello") + .thenAcceptBoth(CompletableFuture.supplyAsync(() -> " World"), + (s1, s2) -> System.out.println(s1 + s2)); + + } + + @Test + public void whenFutureCombinedWithAllOfCompletes_thenAllFuturesAreDone() throws ExecutionException, InterruptedException { + + CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "Hello"); + CompletableFuture future2 = CompletableFuture.supplyAsync(() -> "Beautiful"); + CompletableFuture future3 = CompletableFuture.supplyAsync(() -> "World"); + + CompletableFuture combinedFuture = CompletableFuture.allOf(future1, future2, future3); + + // ... + + combinedFuture.get(); + + assertTrue(future1.isDone()); + assertTrue(future2.isDone()); + assertTrue(future3.isDone()); + + String combined = Stream.of(future1, future2, future3) + .map(CompletableFuture::join) + .collect(Collectors.joining(" ")); + + assertEquals("Hello Beautiful World", combined); + + } + + @Test + public void whenFutureThrows_thenHandleMethodReceivesException() throws ExecutionException, InterruptedException { + + String name = null; + + // ... + + CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> { + if (name == null) { + throw new RuntimeException("Computation error!"); + } + return "Hello, " + name; + }).handle((s, t) -> s != null ? s : "Hello, Stranger!"); + + assertEquals("Hello, Stranger!", completableFuture.get()); + + } + + @Test(expected = ExecutionException.class) + public void whenCompletingFutureExceptionally_thenGetMethodThrows() throws ExecutionException, InterruptedException { + + CompletableFuture completableFuture = new CompletableFuture<>(); + + // ... + + completableFuture.completeExceptionally(new RuntimeException("Calculation failed!")); + + // ... + + completableFuture.get(); + + } + + @Test + public void whenAddingThenApplyAsyncToFuture_thenFunctionExecutesAfterComputationIsFinished() throws ExecutionException, InterruptedException { + + CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> "Hello"); + + CompletableFuture future = completableFuture.thenApplyAsync(s -> s + " World"); + + assertEquals("Hello World", future.get()); + + } + +} \ No newline at end of file diff --git a/core-java-8/src/test/java/com/baeldung/dateapi/ConversionExample.java b/core-java-8/src/test/java/com/baeldung/dateapi/ConversionExample.java new file mode 100644 index 0000000000..a543c80eaf --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/dateapi/ConversionExample.java @@ -0,0 +1,19 @@ +package com.baeldung.dateapi; + +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +public class ConversionExample { + public static void main(String[] args) { + Instant instantFromCalendar = GregorianCalendar.getInstance().toInstant(); + ZonedDateTime zonedDateTimeFromCalendar = new GregorianCalendar().toZonedDateTime(); + Date dateFromInstant = Date.from(Instant.now()); + GregorianCalendar calendarFromZonedDateTime = GregorianCalendar.from(ZonedDateTime.now()); + Instant instantFromDate = new Date().toInstant(); + ZoneId zoneIdFromTimeZone = TimeZone.getTimeZone("PST").toZoneId(); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/dateapi/JavaUtilTimeTest.java b/core-java-8/src/test/java/com/baeldung/dateapi/JavaUtilTimeTest.java new file mode 100644 index 0000000000..4bce40c2d9 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/dateapi/JavaUtilTimeTest.java @@ -0,0 +1,89 @@ +package com.baeldung.dateapi; + +import org.junit.Test; + +import java.text.ParseException; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.Month; +import java.time.YearMonth; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JavaUtilTimeTest { + + @Test + public void currentTime() { + final LocalDate now = LocalDate.now(); + + System.out.println(now); + // there is not much to test here + } + + @Test + public void specificTime() { + LocalDate birthDay = LocalDate.of(1990, Month.DECEMBER, 15); + + System.out.println(birthDay); + // there is not much to test here + } + + @Test + public void extractMonth() { + Month month = LocalDate.of(1990, Month.DECEMBER, 15).getMonth(); + + assertThat(month).isEqualTo(Month.DECEMBER); + } + + @Test + public void subtractTime() { + LocalDateTime fiveHoursBefore = LocalDateTime.of(1990, Month.DECEMBER, 15, 15, 0).minusHours(5); + + assertThat(fiveHoursBefore.getHour()).isEqualTo(10); + } + + @Test + public void alterField() { + LocalDateTime inJune = LocalDateTime.of(1990, Month.DECEMBER, 15, 15, 0).with(Month.JUNE); + + assertThat(inJune.getMonth()).isEqualTo(Month.JUNE); + } + + @Test + public void truncate() { + LocalTime truncated = LocalTime.of(15, 12, 34).truncatedTo(ChronoUnit.HOURS); + + assertThat(truncated).isEqualTo(LocalTime.of(15, 0, 0)); + } + + @Test + public void getTimeSpan() { + LocalDateTime now = LocalDateTime.now(); + LocalDateTime hourLater = now.plusHours(1); + Duration span = Duration.between(now, hourLater); + + assertThat(span).isEqualTo(Duration.ofHours(1)); + } + + @Test + public void formatAndParse() throws ParseException { + LocalDate someDate = LocalDate.of(2016, 12, 7); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + String formattedDate = someDate.format(formatter); + LocalDate parsedDate = LocalDate.parse(formattedDate, formatter); + + assertThat(formattedDate).isEqualTo("2016-12-07"); + assertThat(parsedDate).isEqualTo(someDate); + } + + @Test + public void daysInMonth() { + int daysInMonth = YearMonth.of(1990, 2).lengthOfMonth(); + + assertThat(daysInMonth).isEqualTo(28); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/datetime/UseLocalDateTest.java b/core-java-8/src/test/java/com/baeldung/datetime/UseLocalDateTest.java new file mode 100644 index 0000000000..8af33393be --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/datetime/UseLocalDateTest.java @@ -0,0 +1,55 @@ +package com.baeldung.datetime; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.Month; + +import org.junit.Assert; +import org.junit.Test; + +public class UseLocalDateTest { + + UseLocalDate useLocalDate = new UseLocalDate(); + + @Test + public void givenValues_whenUsingFactoryOf_thenLocalDate(){ + Assert.assertEquals("2016-05-10",useLocalDate.getLocalDateUsingFactoryOfMethod(2016,5,10).toString()); + } + + @Test + public void givenString_whenUsingParse_thenLocalDate(){ + Assert.assertEquals("2016-05-10",useLocalDate.getLocalDateUsingParseMethod("2016-05-10").toString()); + } + + @Test + public void whenUsingClock_thenLocalDate(){ + Assert.assertEquals(LocalDate.now(),useLocalDate.getLocalDateFromClock()); + } + + @Test + public void givenDate_whenUsingPlus_thenNextDay(){ + Assert.assertEquals(LocalDate.now().plusDays(1),useLocalDate.getNextDay(LocalDate.now())); + } + + @Test + public void givenDate_whenUsingMinus_thenPreviousDay(){ + Assert.assertEquals(LocalDate.now().minusDays(1),useLocalDate.getPreviousDay(LocalDate.now())); + } + + @Test + public void givenToday_whenUsingGetDayOfWeek_thenDayOfWeek(){ + Assert.assertEquals(DayOfWeek.SUNDAY,useLocalDate.getDayOfWeek(LocalDate.parse("2016-05-22"))); + } + + @Test + public void givenToday_whenUsingWithTemporalAdjuster_thenFirstDayOfMonth(){ + Assert.assertEquals(1,useLocalDate.getFirstDayOfMonth().getDayOfMonth()); + } + + @Test + public void givenLocalDate_whenUsingAtStartOfDay_thenReturnMidnight(){ + Assert.assertEquals(LocalDateTime.parse("2016-05-22T00:00:00"),useLocalDate.getStartOfDay(LocalDate.parse("2016-05-22"))); + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/datetime/UseLocalDateTimeTest.java b/core-java-8/src/test/java/com/baeldung/datetime/UseLocalDateTimeTest.java new file mode 100644 index 0000000000..69a289fd02 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/datetime/UseLocalDateTimeTest.java @@ -0,0 +1,19 @@ +package com.baeldung.datetime; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.Month; + +import org.junit.Assert; +import org.junit.Test; + +public class UseLocalDateTimeTest { + + UseLocalDateTime useLocalDateTime = new UseLocalDateTime(); + + @Test + public void givenString_whenUsingParse_thenLocalDateTime(){ + Assert.assertEquals(LocalDate.of(2016, Month.MAY, 10),useLocalDateTime.getLocalDateTimeUsingParseMethod("2016-05-10T06:30").toLocalDate()); + Assert.assertEquals(LocalTime.of(6,30),useLocalDateTime.getLocalDateTimeUsingParseMethod("2016-05-10T06:30").toLocalTime()); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/datetime/UseLocalTimeTest.java b/core-java-8/src/test/java/com/baeldung/datetime/UseLocalTimeTest.java new file mode 100644 index 0000000000..7776fad363 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/datetime/UseLocalTimeTest.java @@ -0,0 +1,36 @@ +package com.baeldung.datetime; + +import java.time.LocalTime; + +import org.junit.Assert; +import org.junit.Test; + +public class UseLocalTimeTest { + + UseLocalTime useLocalTime = new UseLocalTime(); + + @Test + public void givenValues_whenUsingFactoryOf_thenLocalTime(){ + Assert.assertEquals("07:07:07",useLocalTime.getLocalTimeUsingFactoryOfMethod(7,7,7).toString()); + } + + @Test + public void givenString_whenUsingParse_thenLocalTime(){ + Assert.assertEquals("06:30",useLocalTime.getLocalTimeUsingParseMethod("06:30").toString()); + } + + @Test + public void givenTime_whenAddHour_thenLocalTime(){ + Assert.assertEquals("07:30",useLocalTime.addAnHour(LocalTime.of(6,30)).toString()); + } + + @Test + public void getHourFromLocalTime(){ + Assert.assertEquals(1, useLocalTime.getHourFromLocalTime(LocalTime.of(1,1))); + } + + @Test + public void getLocalTimeWithMinuteSetToValue(){ + Assert.assertEquals(LocalTime.of(10, 20), useLocalTime.getLocalTimeWithMinuteSetToValue(LocalTime.of(10,10), 20)); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/datetime/UsePeriodTest.java b/core-java-8/src/test/java/com/baeldung/datetime/UsePeriodTest.java new file mode 100644 index 0000000000..8a3228aaa5 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/datetime/UsePeriodTest.java @@ -0,0 +1,29 @@ +package com.baeldung.datetime; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.Period; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.junit.Assert; +import org.junit.Test; + +public class UsePeriodTest { + UsePeriod usingPeriod=new UsePeriod(); + + @Test + public void givenPeriodAndLocalDate_thenCalculateModifiedDate(){ + Period period = Period.ofDays(1); + LocalDate localDate = LocalDate.parse("2007-05-10"); + Assert.assertEquals(localDate.plusDays(1),usingPeriod.modifyDates(localDate, period)); + } + + @Test + public void givenDates_thenGetPeriod(){ + LocalDate localDate1 = LocalDate.parse("2007-05-10"); + LocalDate localDate2 = LocalDate.parse("2007-05-15"); + + Assert.assertEquals(Period.ofDays(5), usingPeriod.getDifferenceBetweenDates(localDate1, localDate2)); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/datetime/UseZonedDateTimeTest.java b/core-java-8/src/test/java/com/baeldung/datetime/UseZonedDateTimeTest.java new file mode 100644 index 0000000000..5af01ad678 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/datetime/UseZonedDateTimeTest.java @@ -0,0 +1,20 @@ +package com.baeldung.datetime; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.junit.Assert; +import org.junit.Test; + +public class UseZonedDateTimeTest { + + UseZonedDateTime zonedDateTime=new UseZonedDateTime(); + + @Test + public void givenZoneId_thenZonedDateTime(){ + ZoneId zoneId=ZoneId.of("Europe/Paris"); + ZonedDateTime zonedDatetime=zonedDateTime.getZonedDateTime(LocalDateTime.parse("2016-05-20T06:30"), zoneId); + Assert.assertEquals(zoneId,ZoneId.from(zonedDatetime)); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/doublecolon/TestComputerUtils.java b/core-java-8/src/test/java/com/baeldung/doublecolon/TestComputerUtils.java index 5ae6f02a56..85194f5aa6 100644 --- a/core-java-8/src/test/java/com/baeldung/doublecolon/TestComputerUtils.java +++ b/core-java-8/src/test/java/com/baeldung/doublecolon/TestComputerUtils.java @@ -6,7 +6,9 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import java.util.*; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; import java.util.function.BiFunction; import static com.baeldung.doublecolon.ComputerUtils.*; diff --git a/core-java-8/src/test/java/com/baeldung/enums/PizzaTest.java b/core-java-8/src/test/java/com/baeldung/enums/PizzaTest.java new file mode 100644 index 0000000000..deeebaa240 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/enums/PizzaTest.java @@ -0,0 +1,80 @@ +package com.baeldung.enums; + + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; + +import static junit.framework.TestCase.assertTrue; + +public class PizzaTest { + + @Test + public void givenPizaOrder_whenReady_thenDeliverable() { + Pizza testPz = new Pizza(); + testPz.setStatus(Pizza.PizzaStatusEnum.READY); + assertTrue(testPz.isDeliverable()); + } + + @Test + public void givenPizaOrders_whenRetrievingUnDeliveredPzs_thenCorrectlyRetrieved() { + List pzList = new ArrayList<>(); + Pizza pz1 = new Pizza(); + pz1.setStatus(Pizza.PizzaStatusEnum.DELIVERED); + + Pizza pz2 = new Pizza(); + pz2.setStatus(Pizza.PizzaStatusEnum.ORDERED); + + Pizza pz3 = new Pizza(); + pz3.setStatus(Pizza.PizzaStatusEnum.ORDERED); + + Pizza pz4 = new Pizza(); + pz4.setStatus(Pizza.PizzaStatusEnum.READY); + + pzList.add(pz1); + pzList.add(pz2); + pzList.add(pz3); + pzList.add(pz4); + + List undeliveredPzs = Pizza.getAllUndeliveredPizzas(pzList); + assertTrue(undeliveredPzs.size() == 3); + } + + @Test + public void givenPizaOrders_whenGroupByStatusCalled_thenCorrectlyGrouped() { + + List pzList = new ArrayList<>(); + Pizza pz1 = new Pizza(); + pz1.setStatus(Pizza.PizzaStatusEnum.DELIVERED); + + Pizza pz2 = new Pizza(); + pz2.setStatus(Pizza.PizzaStatusEnum.ORDERED); + + Pizza pz3 = new Pizza(); + pz3.setStatus(Pizza.PizzaStatusEnum.ORDERED); + + Pizza pz4 = new Pizza(); + pz4.setStatus(Pizza.PizzaStatusEnum.READY); + + pzList.add(pz1); + pzList.add(pz2); + pzList.add(pz3); + pzList.add(pz4); + + EnumMap> map = Pizza.groupPizzaByStatus(pzList); + assertTrue(map.get(Pizza.PizzaStatusEnum.DELIVERED).size() == 1); + assertTrue(map.get(Pizza.PizzaStatusEnum.ORDERED).size() == 2); + assertTrue(map.get(Pizza.PizzaStatusEnum.READY).size() == 1); + } + + @Test + public void givenPizaOrder_whenDelivered_thenPizzaGetsDeliveredAndStatusChanges() { + Pizza pz = new Pizza(); + pz.setStatus(Pizza.PizzaStatusEnum.READY); + pz.deliver(); + assertTrue(pz.getStatus() == Pizza.PizzaStatusEnum.DELIVERED); + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/file/FileOperationsTest.java b/core-java-8/src/test/java/com/baeldung/file/FileOperationsTest.java new file mode 100644 index 0000000000..1dd1be7808 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/file/FileOperationsTest.java @@ -0,0 +1,132 @@ +package com.baeldung.file; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.function.Consumer; +import java.util.stream.Stream; + +import org.apache.commons.io.FileUtils; +import org.hamcrest.CoreMatchers; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; + +public class FileOperationsTest { + + @Test + public void givenFileName_whenUsingClassloader_thenFileData() throws IOException { + String expectedData = "Hello World from fileTest.txt!!!"; + + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("fileTest.txt").getFile()); + InputStream inputStream = new FileInputStream(file); + String data = readFromInputStream(inputStream); + + Assert.assertEquals(expectedData, data.trim()); + } + + @Test + public void givenFileNameAsAbsolutePath_whenUsingClasspath_thenFileData() throws IOException { + String expectedData = "Hello World from fileTest.txt!!!"; + + Class clazz = FileOperationsTest.class; + InputStream inputStream = clazz.getResourceAsStream("/fileTest.txt"); + String data = readFromInputStream(inputStream); + + Assert.assertEquals(expectedData, data.trim()); + } + + @Test + public void givenFileName_whenUsingJarFile_thenFileData() throws IOException { + String expectedData = "BSD License"; + + Class clazz = Matchers.class; + InputStream inputStream = clazz.getResourceAsStream("/LICENSE.txt"); + String data = readFromInputStream(inputStream); + + Assert.assertThat(data.trim(), CoreMatchers.containsString(expectedData)); + } + + @Test + public void givenURLName_whenUsingURL_thenFileData() throws IOException { + String expectedData = "Baeldung"; + + URL urlObject = new URL("http://www.baeldung.com/"); + + URLConnection urlConnection = urlObject.openConnection(); + + InputStream inputStream = urlConnection.getInputStream(); + String data = readFromInputStream(inputStream); + + Assert.assertThat(data.trim(), CoreMatchers.containsString(expectedData)); + } + + @Test + public void givenFileName_whenUsingFileUtils_thenFileData() throws IOException { + String expectedData = "Hello World from fileTest.txt!!!"; + + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("fileTest.txt").getFile()); + String data = FileUtils.readFileToString(file); + + Assert.assertEquals(expectedData, data.trim()); + } + + @Test + public void givenFilePath_whenUsingFilesReadAllBytes_thenFileData() throws IOException { + String expectedData = "Hello World from fileTest.txt!!!"; + + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("fileTest.txt").getFile()); + Path path = Paths.get(file.getAbsolutePath()); + + byte[] fileBytes = Files.readAllBytes(path); + String data = new String(fileBytes); + + Assert.assertEquals(expectedData, data.trim()); + } + + @Test + public void givenFilePath_whenUsingFilesLines_thenFileData() throws IOException { + String expectedData = "Hello World from fileTest.txt!!!"; + + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("fileTest.txt").getFile()); + Path path = Paths.get(file.getAbsolutePath()); + + StringBuilder data = new StringBuilder(); + Stream lines = Files.lines(path); + lines.forEach(new Consumer() { + @Override + public void accept(String line) { + data.append(line).append("\n"); + } + }); + + Assert.assertEquals(expectedData, data.toString().trim()); + } + + private String readFromInputStream(InputStream inputStream) throws IOException { + InputStreamReader inputStreamReader = new InputStreamReader(inputStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + StringBuilder resultStringBuilder = new StringBuilder(); + String line; + while ((line = bufferedReader.readLine()) != null) { + resultStringBuilder.append(line); + resultStringBuilder.append("\n"); + } + bufferedReader.close(); + inputStreamReader.close(); + inputStream.close(); + return resultStringBuilder.toString(); + } +} \ No newline at end of file diff --git a/core-java-8/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceTest.java b/core-java-8/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceTest.java new file mode 100644 index 0000000000..ce878026d4 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceTest.java @@ -0,0 +1,199 @@ +package com.baeldung.functionalinterface; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.google.common.util.concurrent.Uninterruptibles; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class FunctionalInterfaceTest { + + @Test + public void whenPassingLambdaToComputeIfAbsent_thenTheValueGetsComputedAndPutIntoMap() { + + Map nameMap = new HashMap<>(); + Integer value = nameMap.computeIfAbsent("John", s -> s.length()); + + assertEquals(new Integer(4), nameMap.get("John")); + assertEquals(new Integer(4), value); + + } + + @Test + public void whenPassingMethodReferenceToComputeIfAbsent_thenTheValueGetsComputedAndPutIntoMap() { + + Map nameMap = new HashMap<>(); + Integer value = nameMap.computeIfAbsent("John", String::length); + + assertEquals(new Integer(4), nameMap.get("John")); + assertEquals(new Integer(4), value); + + } + + public byte[] transformArray(short[] array, ShortToByteFunction function) { + byte[] transformedArray = new byte[array.length]; + for (int i = 0; i < array.length; i++) { + transformedArray[i] = function.applyAsByte(array[i]); + } + return transformedArray; + } + + @Test + public void whenUsingCustomFunctionalInterfaceForPrimitives_thenCanUseItAsLambda() { + + short[] array = {(short) 1, (short) 2, (short) 3}; + byte[] transformedArray = transformArray(array, s -> (byte) (s * 2)); + + byte[] expectedArray = {(byte) 2, (byte) 4, (byte) 6}; + assertArrayEquals(expectedArray, transformedArray); + + } + + @Test + public void whenUsingBiFunction_thenCanUseItToReplaceMapValues() { + + Map salaries = new HashMap<>(); + salaries.put("John", 40000); + salaries.put("Freddy", 30000); + salaries.put("Samuel", 50000); + + salaries.replaceAll((name, oldValue) -> name.equals("Freddy") ? oldValue : oldValue + 10000); + + assertEquals(new Integer(50000), salaries.get("John")); + assertEquals(new Integer(30000), salaries.get("Freddy")); + assertEquals(new Integer(60000), salaries.get("Samuel")); + + } + + + @Test + public void whenPassingLambdaToThreadConstructor_thenLambdaInferredToRunnable() { + + Thread thread = new Thread(() -> System.out.println("Hello From Another Thread")); + thread.start(); + + } + + @Test + public void whenUsingSupplierToGenerateNumbers_thenCanUseItInStreamGenerate() { + + int[] fibs = {0, 1}; + Stream fibonacci = Stream.generate(() -> { + int result = fibs[1]; + int fib3 = fibs[0] + fibs[1]; + fibs[0] = fibs[1]; + fibs[1] = fib3; + return result; + }); + + List fibonacci5 = fibonacci.limit(5) + .collect(Collectors.toList()); + + assertEquals(new Integer(1), fibonacci5.get(0)); + assertEquals(new Integer(1), fibonacci5.get(1)); + assertEquals(new Integer(2), fibonacci5.get(2)); + assertEquals(new Integer(3), fibonacci5.get(3)); + assertEquals(new Integer(5), fibonacci5.get(4)); + + } + + @Test + public void whenUsingConsumerInForEach_thenConsumerExecutesForEachListElement() { + + List names = Arrays.asList("John", "Freddy", "Samuel"); + names.forEach(name -> System.out.println("Hello, " + name)); + + } + + @Test + public void whenUsingBiConsumerInForEach_thenConsumerExecutesForEachMapElement() { + + Map ages = new HashMap<>(); + ages.put("John", 25); + ages.put("Freddy", 24); + ages.put("Samuel", 30); + + ages.forEach((name, age) -> System.out.println(name + " is " + age + " years old")); + + } + + @Test + public void whenUsingPredicateInFilter_thenListValuesAreFilteredOut() { + + List names = Arrays.asList("Angela", "Aaron", "Bob", "Claire", "David"); + + List namesWithA = names.stream() + .filter(name -> name.startsWith("A")) + .collect(Collectors.toList()); + + assertEquals(2, namesWithA.size()); + assertTrue(namesWithA.contains("Angela")); + assertTrue(namesWithA.contains("Aaron")); + + } + + @Test + public void whenUsingUnaryOperatorWithReplaceAll_thenAllValuesInTheListAreReplaced() { + + List names = Arrays.asList("bob", "josh", "megan"); + + names.replaceAll(String::toUpperCase); + + assertEquals("BOB", names.get(0)); + assertEquals("JOSH", names.get(1)); + assertEquals("MEGAN", names.get(2)); + + } + + @Test + public void whenUsingBinaryOperatorWithStreamReduce_thenResultIsSumOfValues() { + + List values = Arrays.asList(3, 5, 8, 9, 12); + + int sum = values.stream() + .reduce(0, (i1, i2) -> i1 + i2); + + assertEquals(37, sum); + + } + + @Test + public void whenComposingTwoFunctions_thenFunctionsExecuteSequentially() { + + Function intToString = Object::toString; + Function quote = s -> "'" + s + "'"; + + Function quoteIntToString = quote.compose(intToString); + + assertEquals("'5'", quoteIntToString.apply(5)); + + } + + public double squareLazy(Supplier lazyValue) { + return Math.pow(lazyValue.get(), 2); + } + + @Test + public void whenUsingSupplierToGenerateValue_thenValueIsGeneratedLazily() { + + Supplier lazyValue = () -> { + Uninterruptibles.sleepUninterruptibly(1000, TimeUnit.MILLISECONDS); + return 9d; + }; + + double valueSquared = squareLazy(lazyValue); + + assertEquals(81d, valueSquared, 0); + + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java b/core-java-8/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java new file mode 100644 index 0000000000..3231d6244f --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java @@ -0,0 +1,8 @@ +package com.baeldung.functionalinterface; + +@FunctionalInterface +public interface ShortToByteFunction { + + byte applyAsByte(short s); + +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java index 9c248ad8ce..ef4b80c6e8 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java @@ -1,14 +1,13 @@ package com.baeldung.java8; -import static org.hamcrest.Matchers.hasSize; -import static org.junit.Assert.assertThat; +import com.google.common.collect.Lists; +import org.junit.Test; import java.util.List; import java.util.stream.Collectors; -import org.junit.Test; - -import com.google.common.collect.Lists; +import static org.hamcrest.Matchers.hasSize; +import static org.junit.Assert.assertThat; public class Java8CollectionCleanupUnitTest { diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8DefaultStaticIntefaceMethodsTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8DefaultStaticIntefaceMethodsTest.java new file mode 100644 index 0000000000..21a5e34b9b --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8DefaultStaticIntefaceMethodsTest.java @@ -0,0 +1,27 @@ +package com.baeldung.java8; + +import com.baeldung.java_8_features.Vehicle; +import com.baeldung.java_8_features.VehicleImpl; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class Java8DefaultStaticIntefaceMethodsTest { + + @Test + public void callStaticInterfaceMethdosMethods_whenExpectedResults_thenCorrect() { + Vehicle vehicle = new VehicleImpl(); + String overview = vehicle.getOverview(); + long[] startPosition = vehicle.startPosition(); + + assertEquals(overview, "ATV made by N&F Vehicles"); + assertEquals(startPosition[0], 23); + assertEquals(startPosition[1], 15); + } + + @Test + public void callDefaultInterfaceMethods_whenExpectedResults_thenCorrect() { + String producer = Vehicle.producer(); + assertEquals(producer, "N&F Vehicles"); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8ExecutorServiceTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8ExecutorServiceTest.java new file mode 100644 index 0000000000..581ccec182 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8ExecutorServiceTest.java @@ -0,0 +1,156 @@ +package com.baeldung.java8; + + +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + +import static org.junit.Assert.*; + + +public class Java8ExecutorServiceTest { + + private Runnable runnableTask; + private Callable callableTask; + private List> callableTasks; + + @Before + public void init() { + + runnableTask = () -> { + try { + TimeUnit.MILLISECONDS.sleep(300); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }; + + callableTask = () -> { + TimeUnit.MILLISECONDS.sleep(300); + return "Task's execution"; + }; + + callableTasks = new ArrayList<>(); + callableTasks.add(callableTask); + callableTasks.add(callableTask); + callableTasks.add(callableTask); + } + + @Test + public void creationSubmittingTaskShuttingDown_whenShutDown_thenCorrect() { + + ExecutorService executorService = Executors.newFixedThreadPool(10); + executorService.submit(runnableTask); + executorService.submit(callableTask); + executorService.shutdown(); + + assertTrue(executorService.isShutdown()); + } + + @Test + public void creationSubmittingTasksShuttingDownNow_whenShutDownAfterAwating_thenCorrect() { + + ExecutorService threadPoolExecutor = + new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<>()); + + for (int i = 0; i < 100; i++) { + threadPoolExecutor.submit(callableTask); + } + + List notExecutedTasks = smartShutdown(threadPoolExecutor); + + assertTrue(threadPoolExecutor.isShutdown()); + assertFalse(notExecutedTasks.isEmpty()); + assertTrue(notExecutedTasks.size() > 0 && notExecutedTasks.size() < 98); + } + + private List smartShutdown(ExecutorService executorService) { + + List notExecutedTasks = new ArrayList<>(); + executorService.shutdown(); + try { + if (!executorService.awaitTermination(800, TimeUnit.MILLISECONDS)) { + notExecutedTasks = executorService.shutdownNow(); + } + } catch (InterruptedException e) { + notExecutedTasks = executorService.shutdownNow(); + } + return notExecutedTasks; + } + + @Test + public void submittingTasks_whenExecutedOneAndAll_thenCorrect() { + + ExecutorService executorService = Executors.newFixedThreadPool(10); + + String result = null; + List> futures = new ArrayList<>(); + try { + result = executorService.invokeAny(callableTasks); + futures = executorService.invokeAll(callableTasks); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + + assertEquals("Task's execution", result); + assertTrue(futures.size() == 3); + } + + @Test + public void submittingTaskShuttingDown_whenGetExpectedResult_thenCorrect() { + + ExecutorService executorService = Executors.newFixedThreadPool(10); + + Future future = executorService.submit(callableTask); + String result = null; + try { + result = future.get(); + result = future.get(200, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + e.printStackTrace(); + } + + executorService.shutdown(); + + assertEquals("Task's execution", result); + } + + @Test + public void submittingTask_whenCanceled_thenCorrect() { + + ExecutorService executorService = Executors.newFixedThreadPool(10); + + Future future = executorService.submit(callableTask); + + boolean canceled = future.cancel(true); + boolean isCancelled = future.isCancelled(); + + executorService.shutdown(); + + assertTrue(canceled); + assertTrue(isCancelled); + } + + @Test + public void submittingTaskScheduling_whenExecuted_thenCorrect() { + + ScheduledExecutorService executorService = Executors + .newSingleThreadScheduledExecutor(); + + Future resultFuture = executorService.schedule(callableTask, 1, TimeUnit.SECONDS); + String result = null; + try { + result = resultFuture.get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + + executorService.shutdown(); + + assertEquals("Task's execution", result); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8ForkJoinTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8ForkJoinTest.java new file mode 100644 index 0000000000..273b2d78db --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8ForkJoinTest.java @@ -0,0 +1,100 @@ +package com.baeldung.java8; + + +import com.baeldung.forkjoin.CustomRecursiveAction; +import com.baeldung.forkjoin.CustomRecursiveTask; +import com.baeldung.forkjoin.util.PoolUtil; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; +import java.util.concurrent.ForkJoinPool; + +import static org.junit.Assert.*; + +public class Java8ForkJoinTest { + + private int[] arr; + private CustomRecursiveTask customRecursiveTask; + + @Before + public void init() { + Random random = new Random(); + arr = new int[50]; + for (int i = 0; i < arr.length; i++) { + arr[i] = random.nextInt(35); + } + customRecursiveTask = new CustomRecursiveTask(arr); + } + + + @Test + public void callPoolUtil_whenExistsAndExpectedType_thenCorrect() { + + ForkJoinPool forkJoinPool = PoolUtil.forkJoinPool; + ForkJoinPool forkJoinPoolTwo = PoolUtil.forkJoinPool; + + assertNotNull(forkJoinPool); + assertEquals(2, forkJoinPool.getParallelism()); + assertEquals(forkJoinPool, forkJoinPoolTwo); + + } + + @Test + public void callCommonPool_whenExistsAndExpectedType_thenCorrect() { + + ForkJoinPool commonPool = ForkJoinPool.commonPool(); + ForkJoinPool commonPoolTwo = ForkJoinPool.commonPool(); + + assertNotNull(commonPool); + assertEquals(commonPool, commonPoolTwo); + + } + + @Test + public void executeRecursiveAction_whenExecuted_thenCorrect() { + + CustomRecursiveAction myRecursiveAction = new CustomRecursiveAction("ddddffffgggghhhh"); + ForkJoinPool.commonPool().invoke(myRecursiveAction); + + assertTrue(myRecursiveAction.isDone()); + + } + + @Test + public void executeRecursiveTask_whenExecuted_thenCorrect() { + + ForkJoinPool forkJoinPool = ForkJoinPool.commonPool(); + + forkJoinPool.execute(customRecursiveTask); + int result = customRecursiveTask.join(); + assertTrue(customRecursiveTask.isDone()); + + forkJoinPool.submit(customRecursiveTask); + int resultTwo = customRecursiveTask.join(); + assertTrue(customRecursiveTask.isDone()); + + } + + @Test + public void executeRecursiveTaskWithFJ_whenExecuted_thenCorrect() { + + CustomRecursiveTask customRecursiveTaskFirst = new CustomRecursiveTask(arr); + CustomRecursiveTask customRecursiveTaskSecond = new CustomRecursiveTask(arr); + CustomRecursiveTask customRecursiveTaskLast = new CustomRecursiveTask(arr); + + customRecursiveTaskFirst.fork(); + customRecursiveTaskSecond.fork(); + customRecursiveTaskLast.fork(); + int result = 0; + result += customRecursiveTaskLast.join(); + result += customRecursiveTaskSecond.join(); + result += customRecursiveTaskFirst.join(); + + assertTrue(customRecursiveTaskFirst.isDone()); + assertTrue(customRecursiveTaskSecond.isDone()); + assertTrue(customRecursiveTaskLast.isDone()); + assertTrue(result != 0); + + } +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasTest.java index 94448fcc83..faaf3ae407 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasTest.java @@ -1,16 +1,15 @@ package com.baeldung.java8; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -import java.util.function.Function; - -import org.junit.Before; -import org.junit.Test; - import com.baeldung.Foo; import com.baeldung.FooExtended; import com.baeldung.UseFoo; +import org.junit.Before; +import org.junit.Test; + +import java.util.function.Function; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; public class Java8FunctionalInteracesLambdasTest { diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8MethodReferenceTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8MethodReferenceTest.java new file mode 100644 index 0000000000..d9d88c5052 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8MethodReferenceTest.java @@ -0,0 +1,67 @@ +package com.baeldung.java8; + +import com.baeldung.java_8_features.User; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +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 Java8MethodReferenceTest { + + private List list; + + @Before + public void init() { + list = new ArrayList<>(); + list.add("One"); + list.add("OneAndOnly"); + list.add("Derek"); + list.add("Change"); + list.add("factory"); + list.add("justBefore"); + list.add("Italy"); + list.add("Italy"); + list.add("Thursday"); + list.add(""); + list.add(""); + } + + @Test + public void checkStaticMethodReferences_whenWork_thenCorrect() { + + List users = new ArrayList<>(); + users.add(new User()); + users.add(new User()); + boolean isReal = users.stream().anyMatch(u -> User.isRealUser(u)); + boolean isRealRef = users.stream().anyMatch(User::isRealUser); + assertTrue(isReal); + assertTrue(isRealRef); + } + + @Test + public void checkInstanceMethodReferences_whenWork_thenCorrect() { + User user = new User(); + boolean isLegalName = list.stream().anyMatch(user::isLegalName); + assertTrue(isLegalName); + } + + @Test + public void checkParticularTypeReferences_whenWork_thenCorrect() { + long count = list.stream().filter(String::isEmpty).count(); + assertEquals(count, 2); + } + + @Test + public void checkConstructorReferences_whenWork_thenCorrect() { + Stream stream = list.stream().map(User::new); + List userList = stream.collect(Collectors.toList()); + assertEquals(userList.size(), list.size()); + assertTrue(userList.get(0) instanceof User); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8OptionalTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8OptionalTest.java new file mode 100644 index 0000000000..26de39bc0e --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8OptionalTest.java @@ -0,0 +1,118 @@ +package com.baeldung.java8; + +import com.baeldung.java_8_features.*; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.junit.Assert.*; + +public class Java8OptionalTest { + + private List list; + + @Before + public void init() { + list = new ArrayList<>(); + list.add("One"); + list.add("OneAndOnly"); + list.add("Derek"); + list.add("Change"); + list.add("factory"); + list.add("justBefore"); + list.add("Italy"); + list.add("Italy"); + list.add("Thursday"); + list.add(""); + list.add(""); + } + + @Test + public void checkOptional_whenAsExpected_thenCorrect() { + + Optional optionalEmpty = Optional.empty(); + assertFalse(optionalEmpty.isPresent()); + + String str = "value"; + Optional optional = Optional.of(str); + assertEquals(optional.get(), "value"); + + Optional optionalNullable = Optional.ofNullable(str); + Optional optionalNull = Optional.ofNullable(null); + assertEquals(optionalNullable.get(), "value"); + assertFalse(optionalNull.isPresent()); + + List listOpt = Optional.of(list).orElse(new ArrayList<>()); + List listNull = null; + List listOptNull = Optional.ofNullable(listNull).orElse(new ArrayList<>()); + assertTrue(listOpt == list); + assertTrue(listOptNull.isEmpty()); + + Optional user = Optional.ofNullable(getUser()); + String result = user.map(User::getAddress) + .map(Address::getStreet) + .orElse("not specified"); + assertEquals(result, "1st Avenue"); + + Optional optionalUser = Optional.ofNullable(getOptionalUser()); + String resultOpt = optionalUser.flatMap(OptionalUser::getAddress) + .flatMap(OptionalAddress::getStreet) + .orElse("not specified"); + assertEquals(resultOpt, "1st Avenue"); + + Optional userNull = Optional.ofNullable(getUserNull()); + String resultNull = userNull.map(User::getAddress) + .map(Address::getStreet) + .orElse("not specified"); + assertEquals(resultNull, "not specified"); + + Optional optionalUserNull = Optional.ofNullable(getOptionalUserNull()); + String resultOptNull = optionalUserNull.flatMap(OptionalUser::getAddress) + .flatMap(OptionalAddress::getStreet) + .orElse("not specified"); + assertEquals(resultOptNull, "not specified"); + + } + + @Test(expected = CustomException.class) + public void callMethod_whenCustomException_thenCorrect() { + User user = new User(); + String result = user.getOrThrow(); + } + + private User getUser() { + User user = new User(); + Address address = new Address(); + address.setStreet("1st Avenue"); + user.setAddress(address); + return user; + } + + private OptionalUser getOptionalUser() { + OptionalUser user = new OptionalUser(); + OptionalAddress address = new OptionalAddress(); + address.setStreet("1st Avenue"); + user.setAddress(address); + return user; + } + + private OptionalUser getOptionalUserNull() { + OptionalUser user = new OptionalUser(); + OptionalAddress address = new OptionalAddress(); + address.setStreet(null); + user.setAddress(address); + return user; + } + + private User getUserNull() { + User user = new User(); + Address address = new Address(); + address.setStreet(null); + user.setAddress(address); + return user; + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java index 2ba9e417d6..f371c0d7da 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java @@ -1,17 +1,16 @@ package com.baeldung.java8; -import static org.hamcrest.Matchers.equalTo; +import com.baeldung.java8.entity.Human; +import com.google.common.collect.Lists; +import com.google.common.primitives.Ints; +import org.junit.Assert; +import org.junit.Test; import java.util.Collections; import java.util.Comparator; import java.util.List; -import org.junit.Assert; -import org.junit.Test; - -import com.baeldung.java8.entity.Human; -import com.google.common.collect.Lists; -import com.google.common.primitives.Ints; +import static org.hamcrest.Matchers.equalTo; public class Java8SortUnitTest { diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8StreamApiTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8StreamApiTest.java new file mode 100644 index 0000000000..37326c6d26 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8StreamApiTest.java @@ -0,0 +1,263 @@ +package com.baeldung.java8; + +import com.baeldung.streamApi.Product; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.regex.Pattern; +import java.util.stream.*; + +import static org.junit.Assert.*; + +public class Java8StreamApiTest { + + private long counter; + + private static Logger log = LoggerFactory.getLogger(Java8StreamApiTest.class); + + private List productList; + + @Before + public void init() { + productList = Arrays.asList( + new Product(23, "potatoes"), new Product(14, "orange"), + new Product(13, "lemon"), new Product(23, "bread"), + new Product(13, "sugar")); + } + + @Test + public void checkPipeline_whenStreamOneElementShorter_thenCorrect() { + + List list = Arrays.asList("abc1", "abc2", "abc3"); + long size = list.stream().skip(1) + .map(element -> element.substring(0, 3)).count(); + assertEquals(list.size() - 1, size); + } + + @Test + public void checkOrder_whenChangeQuantityOfMethodCalls_thenCorrect() { + + List list = Arrays.asList("abc1", "abc2", "abc3"); + + counter = 0; + long sizeFirst = list.stream() + .skip(2).map(element -> { + wasCalled(); + return element.substring(0, 3); + }).count(); + assertEquals(1, counter); + + counter = 0; + long sizeSecond = list.stream().map(element -> { + wasCalled(); + return element.substring(0, 3); + }).skip(2).count(); + assertEquals(3, counter); + } + + @Test + public void createEmptyStream_whenEmpty_thenCorrect() { + + Stream streamEmpty = Stream.empty(); + assertEquals(0, streamEmpty.count()); + + List names = Collections.emptyList(); + Stream streamOf = Product.streamOf(names); + assertTrue(streamOf.count() == 0); + } + + @Test + public void createStream_whenCreated_thenCorrect() { + + Collection collection = Arrays.asList("a", "b", "c"); + Stream streamOfCollection = collection.stream(); + assertEquals(3, streamOfCollection.count()); + + Stream streamOfArray = Stream.of("a", "b", "c"); + assertEquals(3, streamOfArray.count()); + + String[] arr = new String[]{"a", "b", "c"}; + Stream streamOfArrayPart = Arrays.stream(arr, 1, 3); + assertEquals(2, streamOfArrayPart.count()); + + IntStream intStream = IntStream.range(1, 3); + LongStream longStream = LongStream.rangeClosed(1, 3); + Random random = new Random(); + DoubleStream doubleStream = random.doubles(3); + assertEquals(2, intStream.count()); + assertEquals(3, longStream.count()); + assertEquals(3, doubleStream.count()); + + IntStream streamOfChars = "abc".chars(); + IntStream str = "".chars(); + assertEquals(3, streamOfChars.count()); + + Stream streamOfString = Pattern.compile(", ").splitAsStream("a, b, c"); + assertEquals("a", streamOfString.findFirst().get()); + + Path path = getPath(); + Stream streamOfStrings = null; + try { + streamOfStrings = Files.lines(path, Charset.forName("UTF-8")); + } catch (IOException e) { + log.error("Error creating streams from paths {}", path, e.getMessage(), e); + } + assertEquals("a", streamOfStrings.findFirst().get()); + + Stream streamBuilder = Stream.builder().add("a").add("b").add("c").build(); + assertEquals(3, streamBuilder.count()); + + Stream streamGenerated = Stream.generate(() -> "element").limit(10); + assertEquals(10, streamGenerated.count()); + + Stream streamIterated = Stream.iterate(40, n -> n + 2).limit(20); + assertTrue(40 <= streamIterated.findAny().get()); + } + + @Test + public void runStreamPipeline_whenOrderIsRight_thenCorrect() { + + List list = Arrays.asList("abc1", "abc2", "abc3"); + Optional stream = list.stream() + .filter(element -> { + log.info("filter() was called"); + return element.contains("2"); + }).map(element -> { + log.info("map() was called"); + return element.toUpperCase(); + }).findFirst(); + } + + @Test + public void reduce_whenExpected_thenCorrect() { + + OptionalInt reduced = IntStream.range(1, 4).reduce((a, b) -> a + b); + assertEquals(6, reduced.getAsInt()); + + int reducedTwoParams = IntStream.range(1, 4).reduce(10, (a, b) -> a + b); + assertEquals(16, reducedTwoParams); + + int reducedThreeParams = Stream.of(1, 2, 3) + .reduce(10, (a, b) -> a + b, (a, b) -> { + log.info("combiner was called"); + return a + b; + }); + assertEquals(16, reducedThreeParams); + + int reducedThreeParamsParallel = Arrays.asList(1, 2, 3).parallelStream() + .reduce(10, (a, b) -> a + b, (a, b) -> { + log.info("combiner was called"); + return a + b; + }); + assertEquals(36, reducedThreeParamsParallel); + } + + @Test + public void collecting_whenAsExpected_thenCorrect() { + + List collectorCollection = productList.stream() + .map(Product::getName).collect(Collectors.toList()); + + assertTrue(collectorCollection instanceof List); + assertEquals(5, collectorCollection.size()); + + String listToString = productList.stream().map(Product::getName) + .collect(Collectors.joining(", ", "[", "]")); + + assertTrue(listToString.contains(",") && listToString.contains("[") && listToString.contains("]")); + + double averagePrice = productList.stream().collect(Collectors.averagingInt(Product::getPrice)); + assertTrue(17.2 == averagePrice); + + int summingPrice = productList.stream().collect(Collectors.summingInt(Product::getPrice)); + assertEquals(86, summingPrice); + + IntSummaryStatistics statistics = productList.stream() + .collect(Collectors.summarizingInt(Product::getPrice)); + assertEquals(23, statistics.getMax()); + + Map> collectorMapOfLists = productList.stream() + .collect(Collectors.groupingBy(Product::getPrice)); + assertEquals(3, collectorMapOfLists.keySet().size()); + + Map> mapPartioned = productList.stream() + .collect(Collectors.partitioningBy(element -> element.getPrice() > 15)); + assertEquals(2, mapPartioned.keySet().size()); + + } + + @Test(expected = UnsupportedOperationException.class) + public void collect_whenThrows_thenCorrect() { + Set unmodifiableSet = productList.stream() + .collect(Collectors.collectingAndThen(Collectors.toSet(), + Collections::unmodifiableSet)); + unmodifiableSet.add(new Product(4, "tea")); + } + + @Test + public void customCollector_whenResultContainsAllElementsFrSource_thenCorrect() { + Collector> toLinkedList = + Collector.of(LinkedList::new, LinkedList::add, + (first, second) -> { + first.addAll(second); + return first; + }); + + LinkedList linkedListOfPersons = productList.stream().collect(toLinkedList); + assertTrue(linkedListOfPersons.containsAll(productList)); + } + + @Test + public void parallelStream_whenWorks_thenCorrect() { + Stream streamOfCollection = productList.parallelStream(); + boolean isParallel = streamOfCollection.isParallel(); + boolean haveBigPrice = streamOfCollection.map(product -> product.getPrice() * 12) + .anyMatch(price -> price > 200); + assertTrue(isParallel && haveBigPrice); + } + + @Test + public void parallel_whenIsParallel_thenCorrect() { + IntStream intStreamParallel = + IntStream.range(1, 150).parallel().map(element -> element * 34); + boolean isParallel = intStreamParallel.isParallel(); + assertTrue(isParallel); + } + + @Test + public void parallel_whenIsSequential_thenCorrect() { + IntStream intStreamParallel = + IntStream.range(1, 150).parallel().map(element -> element * 34); + IntStream intStreamSequential = intStreamParallel.sequential(); + boolean isParallel = intStreamParallel.isParallel(); + assertFalse(isParallel); + } + + private Path getPath() { + Path path = null; + try { + path = Files.createTempFile(null, ".txt"); + } catch (IOException e) { + log.error(e.getMessage()); + } + + try (BufferedWriter writer = Files.newBufferedWriter(path)) { + writer.write("a\nb\nc"); + } catch (IOException e) { + log.error(e.getMessage()); + } + return path; + } + + private void wasCalled() { + counter++; + } +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8StreamsTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8StreamsTest.java new file mode 100644 index 0000000000..1f1dda49ce --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8StreamsTest.java @@ -0,0 +1,113 @@ +package com.baeldung.java8; + +import com.baeldung.java_8_features.Detail; +import org.junit.Before; +import org.junit.Test; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.*; + +public class Java8StreamsTest { + + private List list; + + @Before + public void init() { + list = new ArrayList<>(); + list.add("One"); + list.add("OneAndOnly"); + list.add("Derek"); + list.add("Change"); + list.add("factory"); + list.add("justBefore"); + list.add("Italy"); + list.add("Italy"); + list.add("Thursday"); + list.add(""); + list.add(""); + } + + @Test + public void checkStreamCount_whenCreating_givenDifferentSources() { + String[] arr = new String[]{"a", "b", "c"}; + Stream streamArr = Arrays.stream(arr); + assertEquals(streamArr.count(), 3); + + Stream streamOf = Stream.of("a", "b", "c"); + assertEquals(streamOf.count(), 3); + + long count = list.stream().distinct().count(); + assertEquals(count, 9); + } + + + @Test + public void checkStreamCount_whenOperationFilter_thanCorrect() { + Stream streamFilter = list.stream().filter(element -> element.isEmpty()); + assertEquals(streamFilter.count(), 2); + } + + + @Test + public void checkStreamCount_whenOperationMap_thanCorrect() { + List uris = new ArrayList<>(); + uris.add("C:\\My.txt"); + Stream streamMap = uris.stream().map(uri -> Paths.get(uri)); + assertEquals(streamMap.count(), 1); + + List details = new ArrayList<>(); + details.add(new Detail()); + details.add(new Detail()); + Stream streamFlatMap = details.stream() + .flatMap(detail -> detail.getParts().stream()); + assertEquals(streamFlatMap.count(), 4); + } + + + @Test + public void checkStreamCount_whenOperationMatch_thenCorrect() { + boolean isValid = list.stream().anyMatch(element -> element.contains("h")); + boolean isValidOne = list.stream().allMatch(element -> element.contains("h")); + boolean isValidTwo = list.stream().noneMatch(element -> element.contains("h")); + assertTrue(isValid); + assertFalse(isValidOne); + assertFalse(isValidTwo); + } + + + @Test + public void checkStreamReducedValue_whenOperationReduce_thenCorrect() { + List integers = new ArrayList<>(); + integers.add(1); + integers.add(1); + integers.add(1); + Integer reduced = integers.stream().reduce(23, (a, b) -> a + b); + assertTrue(reduced == 26); + } + + @Test + public void checkStreamContains_whenOperationCollect_thenCorrect() { + List resultList = list.stream() + .map(element -> element.toUpperCase()) + .collect(Collectors.toList()); + assertEquals(resultList.size(), list.size()); + assertTrue(resultList.contains("")); + } + + + @Test + public void checkParallelStream_whenDoWork() { + list.parallelStream().forEach(element -> doWork(element)); + } + + private void doWork(String string) { + assertTrue(true); //just imitate an amount of work + } +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/JavaFolderSizeTest.java b/core-java-8/src/test/java/com/baeldung/java8/JavaFolderSizeTest.java index 2ac16b5d1d..f2e7452137 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/JavaFolderSizeTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/JavaFolderSizeTest.java @@ -1,22 +1,18 @@ package com.baeldung.java8; -import static org.junit.Assert.assertEquals; +import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.Test; import java.io.File; import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; +import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.text.DecimalFormat; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.StreamSupport; -import org.apache.commons.io.FileUtils; -import org.junit.Before; -import org.junit.Test; +import static org.junit.Assert.assertEquals; public class JavaFolderSizeTest { @@ -25,7 +21,7 @@ public class JavaFolderSizeTest { @Before public void init() { final String separator = File.separator; - path = "src" + separator + "test" + separator + "resources"; + path = String.format("src%stest%sresources", separator, separator); } @Test @@ -83,7 +79,9 @@ public class JavaFolderSizeTest { final File folder = new File(path); final Iterable files = com.google.common.io.Files.fileTreeTraverser().breadthFirstTraversal(folder); - final long size = StreamSupport.stream(files.spliterator(), false).filter(f -> f.isFile()).mapToLong(File::length).sum(); + final long size = StreamSupport.stream(files.spliterator(), false) + .filter(File::isFile) + .mapToLong(File::length).sum(); assertEquals(expectedSize, size); } @@ -93,7 +91,7 @@ public class JavaFolderSizeTest { final File folder = new File(path); final long size = getFolderSize(folder); - final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" }; + final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"}; final int unitIndex = (int) (Math.log10(size) / 3); final double unitValue = 1 << (unitIndex * 10); @@ -105,13 +103,11 @@ public class JavaFolderSizeTest { long length = 0; final File[] files = folder.listFiles(); - final int count = files.length; - - for (int i = 0; i < count; i++) { - if (files[i].isFile()) { - length += files[i].length(); + for (File file : files) { + if (file.isFile()) { + length += file.length(); } else { - length += getFolderSize(files[i]); + length += getFolderSize(file); } } return length; diff --git a/core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesTest.java b/core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesTest.java index 18110b181d..224c4e9d6a 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesTest.java @@ -1,13 +1,13 @@ package com.baeldung.java8; +import org.junit.Assert; +import org.junit.Test; + import java.io.PrintWriter; import java.io.StringWriter; import java.util.Date; import java.util.Scanner; -import org.junit.Assert; -import org.junit.Test; - public class JavaTryWithResourcesTest { private static final String TEST_STRING_HELLO_WORLD = "Hello World"; diff --git a/core-java-8/src/test/java/com/baeldung/java8/base64/ApacheCommonsEncodeDecodeTest.java b/core-java-8/src/test/java/com/baeldung/java8/base64/ApacheCommonsEncodeDecodeTest.java index 07380cdd01..164a571817 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/base64/ApacheCommonsEncodeDecodeTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/base64/ApacheCommonsEncodeDecodeTest.java @@ -1,14 +1,12 @@ package com.baeldung.java8.base64; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; - -import java.io.UnsupportedEncodingException; - import org.apache.commons.codec.binary.Base64; import org.junit.Test; +import java.io.UnsupportedEncodingException; + +import static org.junit.Assert.*; + public class ApacheCommonsEncodeDecodeTest { // tests diff --git a/core-java-8/src/test/java/com/baeldung/java8/base64/Java8EncodeDecodeTest.java b/core-java-8/src/test/java/com/baeldung/java8/base64/Java8EncodeDecodeTest.java index 3c504edbf3..18dccf71ba 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/base64/Java8EncodeDecodeTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/base64/Java8EncodeDecodeTest.java @@ -1,14 +1,12 @@ package com.baeldung.java8.base64; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; +import org.junit.Test; import java.io.UnsupportedEncodingException; import java.util.Base64; import java.util.UUID; -import org.junit.Test; +import static org.junit.Assert.*; public class Java8EncodeDecodeTest { diff --git a/core-java-8/src/test/java/com/baeldung/threadpool/CoreThreadPoolTest.java b/core-java-8/src/test/java/com/baeldung/threadpool/CoreThreadPoolTest.java new file mode 100644 index 0000000000..df336f4a93 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/threadpool/CoreThreadPoolTest.java @@ -0,0 +1,146 @@ +package com.baeldung.threadpool; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class CoreThreadPoolTest { + + @Test(timeout = 1000) + public void whenCallingExecuteWithRunnable_thenRunnableIsExecuted() throws InterruptedException { + + CountDownLatch lock = new CountDownLatch(1); + + Executor executor = Executors.newSingleThreadExecutor(); + executor.execute(() -> { + System.out.println("Hello World"); + lock.countDown(); + }); + + lock.await(1000, TimeUnit.MILLISECONDS); + } + + @Test + public void whenUsingExecutorServiceAndFuture_thenCanWaitOnFutureResult() throws InterruptedException, ExecutionException { + + ExecutorService executorService = Executors.newFixedThreadPool(10); + Future future = executorService.submit(() -> "Hello World"); + String result = future.get(); + + assertEquals("Hello World", result); + + } + + @Test + public void whenUsingFixedThreadPool_thenCoreAndMaximumThreadSizeAreTheSame() { + + ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2); + executor.submit(() -> { + Thread.sleep(1000); + return null; + }); + executor.submit(() -> { + Thread.sleep(1000); + return null; + }); + executor.submit(() -> { + Thread.sleep(1000); + return null; + }); + + assertEquals(2, executor.getPoolSize()); + assertEquals(1, executor.getQueue().size()); + + } + + @Test + public void whenUsingCachedThreadPool_thenPoolSizeGrowsUnbounded() { + ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool(); + executor.submit(() -> { + Thread.sleep(1000); + return null; + }); + executor.submit(() -> { + Thread.sleep(1000); + return null; + }); + executor.submit(() -> { + Thread.sleep(1000); + return null; + }); + + assertEquals(3, executor.getPoolSize()); + assertEquals(0, executor.getQueue().size()); + + } + + @Test(timeout = 1000) + public void whenUsingSingleThreadPool_thenTasksExecuteSequentially() throws InterruptedException { + + CountDownLatch lock = new CountDownLatch(2); + AtomicInteger counter = new AtomicInteger(); + + ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.submit(() -> { + counter.set(1); + lock.countDown(); + }); + executor.submit(() -> { + counter.compareAndSet(1, 2); + lock.countDown(); + }); + + lock.await(1000, TimeUnit.MILLISECONDS); + assertEquals(2, counter.get()); + + } + + @Test(timeout = 1000) + public void whenSchedulingTask_thenTaskExecutesWithinGivenPeriod() throws InterruptedException { + + CountDownLatch lock = new CountDownLatch(1); + + ScheduledExecutorService executor = Executors.newScheduledThreadPool(5); + executor.schedule(() -> { + System.out.println("Hello World"); + lock.countDown(); + }, 500, TimeUnit.MILLISECONDS); + + lock.await(1000, TimeUnit.MILLISECONDS); + + } + + @Test(timeout = 1000) + public void whenSchedulingTaskWithFixedPeriod_thenTaskExecutesMultipleTimes() throws InterruptedException { + + CountDownLatch lock = new CountDownLatch(3); + + ScheduledExecutorService executor = Executors.newScheduledThreadPool(5); + ScheduledFuture future = executor.scheduleAtFixedRate(() -> { + System.out.println("Hello World"); + lock.countDown(); + }, 500, 100, TimeUnit.MILLISECONDS); + + lock.await(); + future.cancel(true); + + } + + @Test + public void whenUsingForkJoinPool_thenSumOfTreeElementsIsCalculatedCorrectly() { + + TreeNode tree = new TreeNode(5, + new TreeNode(3), new TreeNode(2, + new TreeNode(2), new TreeNode(8))); + + ForkJoinPool forkJoinPool = ForkJoinPool.commonPool(); + int sum = forkJoinPool.invoke(new CountingTask(tree)); + + assertEquals(20, sum); + } + + +} diff --git a/core-java-8/src/test/java/com/baeldung/threadpool/GuavaThreadPoolTest.java b/core-java-8/src/test/java/com/baeldung/threadpool/GuavaThreadPoolTest.java new file mode 100644 index 0000000000..92e0f9a8cb --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/threadpool/GuavaThreadPoolTest.java @@ -0,0 +1,56 @@ +package com.baeldung.threadpool; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class GuavaThreadPoolTest { + + @Test + public void whenExecutingTaskWithDirectExecutor_thenTheTaskIsExecutedInTheCurrentThread() { + + Executor executor = MoreExecutors.directExecutor(); + + AtomicBoolean executed = new AtomicBoolean(); + + executor.execute(() -> { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + executed.set(true); + }); + + assertTrue(executed.get()); + } + + @Test + public void whenJoiningFuturesWithAllAsList_thenCombinedFutureCompletesAfterAllFuturesComplete() throws ExecutionException, InterruptedException { + + ExecutorService executorService = Executors.newCachedThreadPool(); + ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService); + + ListenableFuture future1 = listeningExecutorService.submit(() -> "Hello"); + ListenableFuture future2 = listeningExecutorService.submit(() -> "World"); + + String greeting = Futures.allAsList(future1, future2).get() + .stream() + .collect(Collectors.joining(" ")); + assertEquals("Hello World", greeting); + + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/util/CurrentDateTimeTest.java b/core-java-8/src/test/java/com/baeldung/util/CurrentDateTimeTest.java new file mode 100644 index 0000000000..06d9394a5e --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/util/CurrentDateTimeTest.java @@ -0,0 +1,47 @@ +package com.baeldung.util; + +import static org.junit.Assert.assertEquals; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.temporal.ChronoField; +import java.util.Calendar; +import java.util.GregorianCalendar; + +import org.junit.Test; + +public class CurrentDateTimeTest { + + @Test + public void shouldReturnCurrentDate() { + + final LocalDate now = LocalDate.now(); + final Calendar calendar = GregorianCalendar.getInstance(); + + assertEquals("10-10-2010".length(), now.toString().length()); + assertEquals(calendar.get(Calendar.DATE), now.get(ChronoField.DAY_OF_MONTH)); + assertEquals(calendar.get(Calendar.MONTH), now.get(ChronoField.MONTH_OF_YEAR) - 1); + assertEquals(calendar.get(Calendar.YEAR), now.get(ChronoField.YEAR)); + } + + @Test + public void shouldReturnCurrentTime() { + + final LocalTime now = LocalTime.now(); + final Calendar calendar = GregorianCalendar.getInstance(); + + assertEquals(calendar.get(Calendar.HOUR_OF_DAY), now.get(ChronoField.HOUR_OF_DAY)); + assertEquals(calendar.get(Calendar.MINUTE), now.get(ChronoField.MINUTE_OF_HOUR)); + assertEquals(calendar.get(Calendar.SECOND), now.get(ChronoField.SECOND_OF_MINUTE)); + } + + @Test + public void shouldReturnCurrentTimestamp() { + + final Instant now = Instant.now(); + final Calendar calendar = GregorianCalendar.getInstance(); + + assertEquals(calendar.getTimeInMillis() / 1000, now.getEpochSecond()); + } +} diff --git a/core-java-8/src/test/resources/test.txt b/core-java-8/src/test/resources/test.txt new file mode 100644 index 0000000000..652d70630f --- /dev/null +++ b/core-java-8/src/test/resources/test.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse facilisis neque sed turpis venenatis, non dignissim risus volutpat. \ No newline at end of file diff --git a/core-java-8/src/test/resources/.gitignore b/core-java-9/.gitignore similarity index 100% rename from core-java-8/src/test/resources/.gitignore rename to core-java-9/.gitignore diff --git a/core-java-9/README.md b/core-java-9/README.md new file mode 100644 index 0000000000..b5d4dbef95 --- /dev/null +++ b/core-java-9/README.md @@ -0,0 +1,5 @@ +========= + +## Core Java 9 Examples + +http://inprogress.baeldung.com/java-9-new-features/ \ No newline at end of file diff --git a/core-java-9/pom.xml b/core-java-9/pom.xml new file mode 100644 index 0000000000..844ad6a782 --- /dev/null +++ b/core-java-9/pom.xml @@ -0,0 +1,93 @@ + + 4.0.0 + com.baeldung + core-java9 + 0.2-SNAPSHOT + + core-java9 + + + + apache.snapshots + http://repository.apache.org/snapshots/ + + + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + + + + junit + junit + ${junit.version} + test + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + + + core-java-9 + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.9 + 1.9 + true + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + + + + + + 1.7.13 + 1.0.13 + + + + 3.6-jigsaw-SNAPSHOT + 2.19.1 + + + 1.3 + 4.12 + 1.10.19 + + + diff --git a/mockito-mocks-spring-beans/.gitignore b/core-java-9/src/main/java/.gitignore similarity index 100% rename from mockito-mocks-spring-beans/.gitignore rename to core-java-9/src/main/java/.gitignore diff --git a/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java b/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java new file mode 100644 index 0000000000..fd6a496b18 --- /dev/null +++ b/core-java-9/src/main/java/com/baeldung/java9/language/PrivateInterface.java @@ -0,0 +1,23 @@ +package com.baeldung.java9.language; + +public interface PrivateInterface { + + private static String staticPrivate() { + return "static private"; + } + + private String instancePrivate() { + return "instance private"; + } + + public default void check(){ + String result = staticPrivate(); + if (!result.equals("static private")) + throw new AssertionError("Incorrect result for static private interface method"); + PrivateInterface pvt = new PrivateInterface() { + }; + result = pvt.instancePrivate(); + if (!result.equals("instance private")) + throw new AssertionError("Incorrect result for instance private interface method"); + } +} diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ProcessUtils.java b/core-java-9/src/main/java/com/baeldung/java9/process/ProcessUtils.java new file mode 100644 index 0000000000..d6682bd0c8 --- /dev/null +++ b/core-java-9/src/main/java/com/baeldung/java9/process/ProcessUtils.java @@ -0,0 +1,44 @@ +package com.baeldung.java9.process; + +import java.io.File; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.time.Duration; +import java.time.Instant; +import java.util.stream.Stream; + + +public class ProcessUtils { + + public static String getClassPath(){ + String cp = System.getProperty("java.class.path"); + System.out.println("ClassPath is "+cp); + return cp; + } + + public static File getJavaCmd() throws IOException{ + String javaHome = System.getProperty("java.home"); + File javaCmd; + if(System.getProperty("os.name").startsWith("Win")){ + javaCmd = new File(javaHome, "bin/java.exe"); + }else{ + javaCmd = new File(javaHome, "bin/java"); + } + if(javaCmd.canExecute()){ + return javaCmd; + }else{ + throw new UnsupportedOperationException(javaCmd.getCanonicalPath() + " is not executable"); + } + } + + public static String getMainClass(){ + return System.getProperty("sun.java.command"); + } + + public static String getSystemProperties(){ + StringBuilder sb = new StringBuilder(); + System.getProperties().forEach((s1, s2) -> sb.append(s1 +" - "+ s2) ); + return sb.toString(); + } +} diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java b/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java new file mode 100644 index 0000000000..458f746496 --- /dev/null +++ b/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java @@ -0,0 +1,22 @@ +package com.baeldung.java9.process; + +import java.util.Optional; + +public class ServiceMain { + + public static void main(String[] args) throws InterruptedException { + ProcessHandle thisProcess = ProcessHandle.current(); + long pid = thisProcess.getPid(); + + + Optional opArgs = Optional.ofNullable(args); + String procName = opArgs.map(str -> str.length > 0 ? str[0] : null).orElse(System.getProperty("sun.java.command")); + + for (int i = 0; i < 10000; i++) { + System.out.println("Process " + procName + " with ID " + pid + " is running!"); + Thread.sleep(10000); + } + + } + +} diff --git a/core-java-9/src/main/resources/logback.xml b/core-java-9/src/main/resources/logback.xml new file mode 100644 index 0000000000..eefdc7a337 --- /dev/null +++ b/core-java-9/src/main/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + \ No newline at end of file diff --git a/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamTest.java b/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamTest.java new file mode 100644 index 0000000000..b0684a94f8 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/Java9OptionalsStreamTest.java @@ -0,0 +1,71 @@ +package com.baeldung.java8; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.Before; +import org.junit.Test; + +public class Java9OptionalsStreamTest { + + private static List> listOfOptionals = Arrays.asList(Optional.empty(), Optional.of("foo"), Optional.empty(), Optional.of("bar")); + + @Test + public void filterOutPresentOptionalsWithFilter() { + assertEquals(4, listOfOptionals.size()); + + List filteredList = listOfOptionals.stream() + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList()); + + assertEquals(2, filteredList.size()); + assertEquals("foo", filteredList.get(0)); + assertEquals("bar", filteredList.get(1)); + } + + @Test + public void filterOutPresentOptionalsWithFlatMap() { + assertEquals(4, listOfOptionals.size()); + + List filteredList = listOfOptionals.stream() + .flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty()) + .collect(Collectors.toList()); + assertEquals(2, filteredList.size()); + + assertEquals("foo", filteredList.get(0)); + assertEquals("bar", filteredList.get(1)); + } + + @Test + public void filterOutPresentOptionalsWithFlatMap2() { + assertEquals(4, listOfOptionals.size()); + + List filteredList = listOfOptionals.stream() + .flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty)) + .collect(Collectors.toList()); + assertEquals(2, filteredList.size()); + + assertEquals("foo", filteredList.get(0)); + assertEquals("bar", filteredList.get(1)); + } + + @Test + public void filterOutPresentOptionalsWithJava9() { + assertEquals(4, listOfOptionals.size()); + + List filteredList = listOfOptionals.stream() + .flatMap(Optional::stream) + .collect(Collectors.toList()); + + assertEquals(2, filteredList.size()); + assertEquals("foo", filteredList.get(0)); + assertEquals("bar", filteredList.get(1)); + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageTest.java b/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageTest.java new file mode 100644 index 0000000000..a00646e4db --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/MultiResultionImageTest.java @@ -0,0 +1,47 @@ +package com.baeldung.java9; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import java.awt.Image; +import java.awt.image.BaseMultiResolutionImage; +import java.awt.image.BufferedImage; +import java.awt.image.MultiResolutionImage; +import java.util.List; + +import org.junit.Test; + +public class MultiResultionImageTest { + + + @Test + public void baseMultiResImageTest() { + int baseIndex = 1; + int length = 4; + BufferedImage[] resolutionVariants = new BufferedImage[length]; + for (int i = 0; i < length; i++) { + resolutionVariants[i] = createImage(i); + } + MultiResolutionImage bmrImage = new BaseMultiResolutionImage(baseIndex, resolutionVariants); + List rvImageList = bmrImage.getResolutionVariants(); + assertEquals("MultiResoltion Image shoudl contain the same number of resolution variants!", rvImageList.size(), length); + + for (int i = 0; i < length; i++) { + int imageSize = getSize(i); + Image testRVImage = bmrImage.getResolutionVariant(imageSize, imageSize); + assertSame("Images should be the same", testRVImage, resolutionVariants[i]); + } + + } + + private static int getSize(int i) { + return 8 * (i + 1); + } + + + private static BufferedImage createImage(int i) { + return new BufferedImage(getSize(i), getSize(i), + BufferedImage.TYPE_INT_RGB); + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/OptionalToStreamTest.java b/core-java-9/src/test/java/com/baeldung/java9/OptionalToStreamTest.java new file mode 100644 index 0000000000..56b4bb7b8c --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/OptionalToStreamTest.java @@ -0,0 +1,21 @@ +package com.baeldung.java9; + +import java.util.Optional; +import java.util.stream.Stream; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +public class OptionalToStreamTest { + + @Test + public void testOptionalToStream() { + Optional op = Optional.ofNullable("String value"); + Stream strOptionalStream = op.stream(); + Stream filteredStream = strOptionalStream.filter((str) -> { + return str != null && str.startsWith("String"); + }); + assertEquals(1, filteredStream.count()); + + } +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/README.MD b/core-java-9/src/test/java/com/baeldung/java9/README.MD new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/README.MD @@ -0,0 +1 @@ + diff --git a/core-java-9/src/test/java/com/baeldung/java9/SetExamplesTest.java b/core-java-9/src/test/java/com/baeldung/java9/SetExamplesTest.java new file mode 100644 index 0000000000..0f8db83d9c --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/SetExamplesTest.java @@ -0,0 +1,26 @@ +package com.baeldung.java9; + +import java.util.Set; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SetExamplesTest { + + @Test + public void testUnmutableSet() { + Set strKeySet = Set.of("key1", "key2", "key3"); + try { + strKeySet.add("newKey"); + } catch (UnsupportedOperationException uoe) { + } + assertEquals(strKeySet.size(), 3); + } + + @Test + public void testArrayToSet() { + Integer[] intArray = new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + Set intSet = Set.of(intArray); + assertEquals(intSet.size(), intArray.length); + } +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/httpclient/SimpleHttpRequestsTest.java b/core-java-9/src/test/java/com/baeldung/java9/httpclient/SimpleHttpRequestsTest.java new file mode 100644 index 0000000000..ab28b0a805 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/httpclient/SimpleHttpRequestsTest.java @@ -0,0 +1,126 @@ +package com.baeldung.java9.httpclient; + + + +import static java.net.HttpURLConnection.HTTP_OK; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.net.CookieManager; +import java.net.CookiePolicy; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpHeaders; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.security.NoSuchAlgorithmException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +import org.junit.Before; +import org.junit.Test; + +public class SimpleHttpRequestsTest { + + private URI httpURI; + + @Before + public void init() throws URISyntaxException { + httpURI = new URI("http://www.baeldung.com/"); + } + + @Test + public void quickGet() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.create( httpURI ).GET(); + HttpResponse response = request.response(); + int responseStatusCode = response.statusCode(); + String responseBody = response.body(HttpResponse.asString()); + assertTrue("Get response status code is bigger then 400", responseStatusCode < 400); + } + + @Test + public void asynchronousGet() throws URISyntaxException, IOException, InterruptedException, ExecutionException{ + HttpRequest request = HttpRequest.create(httpURI).GET(); + long before = System.currentTimeMillis(); + CompletableFuture futureResponse = request.responseAsync(); + futureResponse.thenAccept( response -> { + String responseBody = response.body(HttpResponse.asString()); + }); + HttpResponse resp = futureResponse.get(); + HttpHeaders hs = resp.headers(); + assertTrue("There should be more then 1 header.", hs.map().size() >1); + } + + @Test + public void postMehtod() throws URISyntaxException, IOException, InterruptedException { + HttpRequest.Builder requestBuilder = HttpRequest.create(httpURI); + requestBuilder.body(HttpRequest.fromString("param1=foo,param2=bar")).followRedirects(HttpClient.Redirect.SECURE); + HttpRequest request = requestBuilder.POST(); + HttpResponse response = request.response(); + int statusCode = response.statusCode(); + assertTrue("HTTP return code", statusCode == HTTP_OK); + } + + @Test + public void configureHttpClient() throws NoSuchAlgorithmException, URISyntaxException, IOException, InterruptedException{ + CookieManager cManager = new CookieManager(); + cManager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER); + + SSLParameters sslParam = new SSLParameters (new String[] { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" }, new String[] { "TLSv1.2" }); + + HttpClient.Builder hcBuilder = HttpClient.create(); + hcBuilder.cookieManager(cManager).sslContext(SSLContext.getDefault()).sslParameters(sslParam); + HttpClient httpClient = hcBuilder.build(); + HttpRequest.Builder reqBuilder = httpClient.request(new URI("https://www.facebook.com")); + + HttpRequest request = reqBuilder.followRedirects(HttpClient.Redirect.ALWAYS).GET(); + HttpResponse response = request.response(); + int statusCode = response.statusCode(); + assertTrue("HTTP return code", statusCode == HTTP_OK); + } + + SSLParameters getDefaultSSLParameters() throws NoSuchAlgorithmException{ + SSLParameters sslP1 = SSLContext.getDefault().getSupportedSSLParameters(); + String [] proto = sslP1.getApplicationProtocols(); + String [] cifers = sslP1.getCipherSuites(); + System.out.println(printStringArr(proto)); + System.out.println(printStringArr(cifers)); + return sslP1; + } + + String printStringArr(String ... args ){ + if(args == null){ + return null; + } + StringBuilder sb = new StringBuilder(); + for (String s : args){ + sb.append(s); + sb.append("\n"); + } + return sb.toString(); + } + + String printHeaders(HttpHeaders h){ + if(h == null){ + return null; + } + + StringBuilder sb = new StringBuilder(); + Map> hMap = h.map(); + for(String k : hMap.keySet()){ + sb.append(k).append(":"); + List l = hMap.get(k); + if( l != null ){ + l.forEach( s -> { sb.append(s).append(","); } ); + } + sb.append("\n"); + } + return sb.toString(); + } +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/DiamondTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/DiamondTest.java new file mode 100644 index 0000000000..33da6486f4 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/language/DiamondTest.java @@ -0,0 +1,36 @@ +package com.baeldung.java9.language; + +import org.junit.Test; + +public class DiamondTest { + + static class FooClass { + FooClass(X x) { + } + + FooClass(X x, Z z) { + } + } + + @Test + public void diamondTest() { + FooClass fc = new FooClass<>(1) { + }; + FooClass fc0 = new FooClass<>(1) { + }; + FooClass fc1 = new FooClass<>(1) { + }; + FooClass fc2 = new FooClass<>(1) { + }; + + FooClass fc3 = new FooClass<>(1, "") { + }; + FooClass fc4 = new FooClass<>(1, "") { + }; + FooClass fc5 = new FooClass<>(1, "") { + }; + FooClass fc6 = new FooClass<>(1, "") { + }; + + } +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceTest.java new file mode 100644 index 0000000000..29ef3930f8 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/language/PrivateInterfaceTest.java @@ -0,0 +1,15 @@ +package com.baeldung.java9.language; + +import com.baeldung.java9.language.PrivateInterface; +import org.junit.Test; + +public class PrivateInterfaceTest { + + @Test + public void test() { + PrivateInterface piClass = new PrivateInterface() { + }; + piClass.check(); + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesTest.java b/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesTest.java new file mode 100644 index 0000000000..687dfbc390 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/language/TryWithResourcesTest.java @@ -0,0 +1,70 @@ +package com.baeldung.java9.language; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class TryWithResourcesTest { + + static int closeCount = 0; + + static class MyAutoCloseable implements AutoCloseable{ + final FinalWrapper finalWrapper = new FinalWrapper(); + + public void close() { + closeCount++; + } + + static class FinalWrapper { + public final AutoCloseable finalCloseable = new AutoCloseable() { + @Override + public void close() throws Exception { + closeCount++; + } + }; + } + } + + @Test + public void tryWithResourcesTest() { + MyAutoCloseable mac = new MyAutoCloseable(); + + try (mac) { + assertEquals("Expected and Actual does not match", 0, closeCount); + } + + try (mac.finalWrapper.finalCloseable) { + assertEquals("Expected and Actual does not match", 1, closeCount); + } catch (Exception ex) { + } + + try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) { + assertEquals("Expected and Actual does not match", 2, closeCount); + } catch (Exception ex) { + } + + try ((closeCount > 0 ? mac : new MyAutoCloseable()).finalWrapper.finalCloseable) { + assertEquals("Expected and Actual does not match", 3, closeCount); + } catch (Exception ex) { + } + + try { + throw new CloseableException(); + } catch (CloseableException ex) { + try (ex) { + assertEquals("Expected and Actual does not match", 4, closeCount); + } + } + assertEquals("Expected and Actual does not match", 5, closeCount); + } + + + static class CloseableException extends Exception implements AutoCloseable { + @Override + public void close() { + closeCount++; + } + } + +} + + diff --git a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessApi.java b/core-java-9/src/test/java/com/baeldung/java9/process/ProcessApi.java new file mode 100644 index 0000000000..419516cb64 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/process/ProcessApi.java @@ -0,0 +1,112 @@ +package com.baeldung.java9.process; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; + +import org.junit.Before; +import org.junit.Test; + +import junit.framework.Assert; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class ProcessApi { + + + @Before + public void init() { + + } + + @Test + public void processInfoExample()throws NoSuchAlgorithmException{ + ProcessHandle self = ProcessHandle.current(); + long PID = self.getPid(); + ProcessHandle.Info procInfo = self.info(); + Optional args = procInfo.arguments(); + Optional cmd = procInfo.commandLine(); + Optional startTime = procInfo.startInstant(); + Optional cpuUsage = procInfo.totalCpuDuration(); + + waistCPU(); + System.out.println("Args "+ args); + System.out.println("Command " +cmd.orElse("EmptyCmd")); + System.out.println("Start time: "+ startTime.get().toString()); + System.out.println(cpuUsage.get().toMillis()); + + Stream allProc = ProcessHandle.current().children(); + allProc.forEach(p -> { + System.out.println("Proc "+ p.getPid()); + }); + + } + + @Test + public void createAndDestroyProcess() throws IOException, InterruptedException{ + int numberOfChildProcesses = 5; + for(int i=0; i < numberOfChildProcesses; i++){ + createNewJVM(ServiceMain.class, i).getPid(); + } + + Stream childProc = ProcessHandle.current().children(); + assertEquals( childProc.count(), numberOfChildProcesses); + + childProc = ProcessHandle.current().children(); + childProc.forEach(processHandle -> { + assertTrue("Process "+ processHandle.getPid() +" should be alive!", processHandle.isAlive()); + CompletableFuture onProcExit = processHandle.onExit(); + onProcExit.thenAccept(procHandle -> { + System.out.println("Process with PID "+ procHandle.getPid() + " has stopped"); + }); + }); + + Thread.sleep(10000); + + childProc = ProcessHandle.current().children(); + childProc.forEach(procHandle -> { + assertTrue("Could not kill process "+procHandle.getPid(), procHandle.destroy()); + }); + + Thread.sleep(5000); + + childProc = ProcessHandle.current().children(); + childProc.forEach(procHandle -> { + assertFalse("Process "+ procHandle.getPid() +" should not be alive!", procHandle.isAlive()); + }); + + } + + private Process createNewJVM(Class mainClass, int number) throws IOException{ + ArrayList cmdParams = new ArrayList(5); + cmdParams.add(ProcessUtils.getJavaCmd().getAbsolutePath()); + cmdParams.add("-cp"); + cmdParams.add(ProcessUtils.getClassPath()); + cmdParams.add(mainClass.getName()); + cmdParams.add("Service "+ number); + ProcessBuilder myService = new ProcessBuilder(cmdParams); + myService.inheritIO(); + return myService.start(); + } + + private void waistCPU() throws NoSuchAlgorithmException{ + ArrayList randArr = new ArrayList(4096); + SecureRandom sr = SecureRandom.getInstanceStrong(); + Duration somecpu = Duration.ofMillis(4200L); + Instant end = Instant.now().plus(somecpu); + while (Instant.now().isBefore(end)) { + //System.out.println(sr.nextInt()); + randArr.add( sr.nextInt() ); + } + } + +} diff --git a/mockito/src/test/resources/.gitignore b/core-java-9/src/test/resources/.gitignore similarity index 100% rename from mockito/src/test/resources/.gitignore rename to core-java-9/src/test/resources/.gitignore diff --git a/core-java/.classpath b/core-java/.classpath deleted file mode 100644 index f9b079e8c9..0000000000 --- a/core-java/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/core-java/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/core-java/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/core-java/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/core-java/.project b/core-java/.project deleted file mode 100644 index 12bfa7d869..0000000000 --- a/core-java/.project +++ /dev/null @@ -1,36 +0,0 @@ - - - core-java - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/core-java/.settings/.jsdtscope b/core-java/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/core-java/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/core-java/.settings/org.eclipse.jdt.core.prefs b/core-java/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 046168cf24..0000000000 --- a/core-java/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 -org.eclipse.jdt.core.compiler.compliance=1.7 -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.7 diff --git a/core-java/.settings/org.eclipse.jdt.ui.prefs b/core-java/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/core-java/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/core-java/.settings/org.eclipse.m2e.core.prefs b/core-java/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/core-java/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/core-java/.settings/org.eclipse.m2e.wtp.prefs b/core-java/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/core-java/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/core-java/.settings/org.eclipse.wst.common.component b/core-java/.settings/org.eclipse.wst.common.component deleted file mode 100644 index e98377cb0f..0000000000 --- a/core-java/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/core-java/.settings/org.eclipse.wst.common.project.facet.core.xml b/core-java/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index bc0009a455..0000000000 --- a/core-java/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/core-java/.settings/org.eclipse.wst.jsdt.ui.superType.container b/core-java/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/core-java/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/core-java/.settings/org.eclipse.wst.jsdt.ui.superType.name b/core-java/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/core-java/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/core-java/.settings/org.eclipse.wst.validation.prefs b/core-java/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index cacf5451ae..0000000000 --- a/core-java/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,14 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.303.v201202090300 -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/core-java/.settings/org.eclipse.wst.ws.service.policy.prefs b/core-java/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/core-java/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/core-java/.springBeans b/core-java/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/core-java/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/core-java/README.md b/core-java/README.md index 772681ad57..23fe12465f 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -6,4 +6,10 @@ - [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list) - [Java - Reading a Large File Efficiently](http://www.baeldung.com/java-read-lines-large-file) - [Java InputStream to String](http://www.baeldung.com/convert-input-stream-to-string) - +- [Converting between an Array and a List in Java](http://www.baeldung.com/convert-array-to-list-and-list-to-array) +- [Converting between an Array and a Set in Java](http://www.baeldung.com/convert-array-to-set-and-set-to-array) +- [Converting between a List and a Set in Java](http://www.baeldung.com/convert-list-to-set-and-set-to-list) +- [Convert a Map to an Array, List or Set in Java](http://www.baeldung.com/convert-map-values-to-array-list-set) +- [Java – Write to File](http://www.baeldung.com/java-write-to-file) +- [Java Scanner](http://www.baeldung.com/java-scanner) +- [Java Timer](http://www.baeldung.com/java-timer-and-timertask) diff --git a/core-java/pom.xml b/core-java/pom.xml index b439b41f22..bce97d1148 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -1,15 +1,19 @@ 4.0.0 - org.baeldung + com.baeldung core-java - 0.1-SNAPSHOT + 0.1.0-SNAPSHOT core-java - + + net.sourceforge.collections + collections-generic + 4.01 + com.google.guava guava @@ -97,12 +101,34 @@ test + + org.assertj + assertj-core + ${assertj.version} + test + + + + org.testng + testng + ${testng.version} + test + + + + org.mockito mockito-core ${mockito.version} test + + + commons-codec + commons-codec + 1.10 + @@ -122,8 +148,8 @@ maven-compiler-plugin ${maven-compiler-plugin.version} - 1.7 - 1.7 + 1.8 + 1.8 @@ -143,16 +169,12 @@ - - 4.1.5.RELEASE - 3.2.5.RELEASE - - 4.3.10.Final - 5.1.35 + 4.3.11.Final + 5.1.38 - 2.5.5 + 2.7.2 1.7.13 @@ -169,18 +191,20 @@ 1.3 4.12 1.10.19 + 6.8 + 3.5.1 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.14 + 1.4.18 diff --git a/core-java/src/main/java/com/baeldung/enums/Pizza.java b/core-java/src/main/java/com/baeldung/enums/Pizza.java new file mode 100644 index 0000000000..7742781081 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/enums/Pizza.java @@ -0,0 +1,110 @@ +package com.baeldung.enums; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.collections15.Predicate; + +import java.io.IOException; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; +import java.util.stream.Collectors; + +public class Pizza { + + private static EnumSet undeliveredPizzaStatuses = + EnumSet.of(PizzaStatus.ORDERED, PizzaStatus.READY); + + private PizzaStatus status; + + @JsonFormat(shape = JsonFormat.Shape.OBJECT) + public enum PizzaStatus { + ORDERED(5) { + @Override + public boolean isOrdered() { + return true; + } + }, + READY(2) { + @Override + public boolean isReady() { + return true; + } + }, + DELIVERED(0) { + @Override + public boolean isDelivered() { + return true; + } + }; + + private int timeToDelivery; + + public boolean isOrdered() { + return false; + } + + public boolean isReady() { + return false; + } + + public boolean isDelivered() { + return false; + } + + @JsonProperty("timeToDelivery") + public int getTimeToDelivery() { + return timeToDelivery; + } + + PizzaStatus(int timeToDelivery) { + this.timeToDelivery = timeToDelivery; + } + } + + public PizzaStatus getStatus() { + return status; + } + + public void setStatus(PizzaStatus status) { + this.status = status; + } + + public boolean isDeliverable() { + return this.status.isReady(); + } + + public void printTimeToDeliver() { + System.out.println("Time to delivery is " + this.getStatus().getTimeToDelivery() + " days"); + } + + public static List getAllUndeliveredPizzas(List input) { + return input.stream().filter( + (s) -> undeliveredPizzaStatuses.contains(s.getStatus())) + .collect(Collectors.toList()); + } + + public static EnumMap> + groupPizzaByStatus(List pzList) { + return pzList.stream().collect( + Collectors.groupingBy(Pizza::getStatus, + () -> new EnumMap<>(PizzaStatus.class), Collectors.toList())); + } + + public void deliver() { + if (isDeliverable()) { + PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy().deliver(this); + this.setStatus(PizzaStatus.DELIVERED); + } + } + + public static String getJsonString(Pizza pz) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(pz); + } + + private static Predicate thatAreNotDelivered() { + return entry -> undeliveredPizzaStatuses.contains(entry.getStatus()); + } +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java b/core-java/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java new file mode 100644 index 0000000000..ed65919387 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java @@ -0,0 +1,18 @@ +package com.baeldung.enums; + +public enum PizzaDeliveryStrategy { + EXPRESS { + @Override + public void deliver(Pizza pz) { + System.out.println("Pizza will be delivered in express mode"); + } + }, + NORMAL { + @Override + public void deliver(Pizza pz) { + System.out.println("Pizza will be delivered in normal mode"); + } + }; + + public abstract void deliver(Pizza pz); +} diff --git a/core-java/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java b/core-java/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java new file mode 100644 index 0000000000..a276b3c000 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java @@ -0,0 +1,21 @@ +package com.baeldung.enums; + +public enum PizzaDeliverySystemConfiguration { + INSTANCE; + + PizzaDeliverySystemConfiguration() { + // Do the configuration initialization which + // involves overriding defaults like delivery strategy + } + + private PizzaDeliveryStrategy deliveryStrategy = PizzaDeliveryStrategy.NORMAL; + + public static PizzaDeliverySystemConfiguration getInstance() { + return INSTANCE; + } + + public PizzaDeliveryStrategy getDeliveryStrategy() { + return deliveryStrategy; + } + +} diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Animal.java b/core-java/src/main/java/com/baeldung/java/reflection/Animal.java new file mode 100644 index 0000000000..3f36243c29 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java/reflection/Animal.java @@ -0,0 +1,23 @@ +package com.baeldung.java.reflection; + +public abstract class Animal implements Eating { + + public static final String CATEGORY = "domestic"; + + private String name; + + public Animal(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + protected abstract String getSound(); + +} diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Bird.java b/core-java/src/main/java/com/baeldung/java/reflection/Bird.java new file mode 100644 index 0000000000..bd6f13094c --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java/reflection/Bird.java @@ -0,0 +1,36 @@ +package com.baeldung.java.reflection; + +public class Bird extends Animal { + private boolean walks; + + public Bird() { + super("bird"); + } + + public Bird(String name, boolean walks) { + super(name); + setWalks(walks); + } + + public Bird(String name) { + super(name); + } + + @Override + public String eats() { + return "grains"; + } + + @Override + protected String getSound() { + return "chaps"; + } + + public boolean walks() { + return walks; + } + + public void setWalks(boolean walks) { + this.walks = walks; + } +} diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Eating.java b/core-java/src/main/java/com/baeldung/java/reflection/Eating.java new file mode 100644 index 0000000000..479425cad4 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java/reflection/Eating.java @@ -0,0 +1,5 @@ +package com.baeldung.java.reflection; + +public interface Eating { + String eats(); +} diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Goat.java b/core-java/src/main/java/com/baeldung/java/reflection/Goat.java new file mode 100644 index 0000000000..503717ae5e --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java/reflection/Goat.java @@ -0,0 +1,24 @@ +package com.baeldung.java.reflection; + +public class Goat extends Animal implements Locomotion { + + public Goat(String name) { + super(name); + } + + @Override + protected String getSound() { + return "bleat"; + } + + @Override + public String getLocomotion() { + return "walks"; + } + + @Override + public String eats() { + return "grass"; + } + +} diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Locomotion.java b/core-java/src/main/java/com/baeldung/java/reflection/Locomotion.java new file mode 100644 index 0000000000..047c00cb13 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java/reflection/Locomotion.java @@ -0,0 +1,5 @@ +package com.baeldung.java.reflection; + +public interface Locomotion { + String getLocomotion(); +} diff --git a/core-java/src/main/java/com/baeldung/java/reflection/Person.java b/core-java/src/main/java/com/baeldung/java/reflection/Person.java new file mode 100644 index 0000000000..f3d7f9f001 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java/reflection/Person.java @@ -0,0 +1,6 @@ +package com.baeldung.java.reflection; + +public class Person { + private String name; + private int age; +} diff --git a/core-java/src/main/java/org/baeldung/equalshashcode/entities/ComplexClass.java b/core-java/src/main/java/org/baeldung/equalshashcode/entities/ComplexClass.java new file mode 100644 index 0000000000..d4a6a0f42e --- /dev/null +++ b/core-java/src/main/java/org/baeldung/equalshashcode/entities/ComplexClass.java @@ -0,0 +1,65 @@ +package org.baeldung.equalshashcode.entities; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class ComplexClass { + + private List genericList; + private Set integerSet; + + public ComplexClass(ArrayList genericArrayList, HashSet integerHashSet) { + super(); + this.genericList = genericArrayList; + this.integerSet = integerHashSet; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((genericList == null) ? 0 : genericList.hashCode()); + result = prime * result + ((integerSet == null) ? 0 : integerSet.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof ComplexClass)) + return false; + ComplexClass other = (ComplexClass) obj; + if (genericList == null) { + if (other.genericList != null) + return false; + } else if (!genericList.equals(other.genericList)) + return false; + if (integerSet == null) { + if (other.integerSet != null) + return false; + } else if (!integerSet.equals(other.integerSet)) + return false; + return true; + } + + protected List getGenericList() { + return genericList; + } + + protected void setGenericArrayList(List genericList) { + this.genericList = genericList; + } + + protected Set getIntegerSet() { + return integerSet; + } + + protected void setIntegerSet(Set integerSet) { + this.integerSet = integerSet; + } +} diff --git a/core-java/src/main/java/org/baeldung/equalshashcode/entities/PrimitiveClass.java b/core-java/src/main/java/org/baeldung/equalshashcode/entities/PrimitiveClass.java new file mode 100644 index 0000000000..ebe005688c --- /dev/null +++ b/core-java/src/main/java/org/baeldung/equalshashcode/entities/PrimitiveClass.java @@ -0,0 +1,54 @@ +package org.baeldung.equalshashcode.entities; + +public class PrimitiveClass { + + private boolean primitiveBoolean; + private int primitiveInt; + + public PrimitiveClass(boolean primitiveBoolean, int primitiveInt) { + super(); + this.primitiveBoolean = primitiveBoolean; + this.primitiveInt = primitiveInt; + } + + protected boolean isPrimitiveBoolean() { + return primitiveBoolean; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (primitiveBoolean ? 1231 : 1237); + result = prime * result + primitiveInt; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PrimitiveClass other = (PrimitiveClass) obj; + if (primitiveBoolean != other.primitiveBoolean) + return false; + if (primitiveInt != other.primitiveInt) + return false; + return true; + } + + protected void setPrimitiveBoolean(boolean primitiveBoolean) { + this.primitiveBoolean = primitiveBoolean; + } + + protected int getPrimitiveInt() { + return primitiveInt; + } + + protected void setPrimitiveInt(int primitiveInt) { + this.primitiveInt = primitiveInt; + } +} diff --git a/core-java/src/main/java/org/baeldung/equalshashcode/entities/Rectangle.java b/core-java/src/main/java/org/baeldung/equalshashcode/entities/Rectangle.java new file mode 100644 index 0000000000..1e1423f0b3 --- /dev/null +++ b/core-java/src/main/java/org/baeldung/equalshashcode/entities/Rectangle.java @@ -0,0 +1,58 @@ +package org.baeldung.equalshashcode.entities; + +public class Rectangle extends Shape { + private double width; + private double length; + + public Rectangle(double width, double length) { + this.width = width; + this.length = length; + } + + @Override + public double area() { + return width * length; + } + + @Override + public double perimeter() { + return 2 * (width + length); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(length); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(width); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Rectangle other = (Rectangle) obj; + if (Double.doubleToLongBits(length) != Double.doubleToLongBits(other.length)) + return false; + if (Double.doubleToLongBits(width) != Double.doubleToLongBits(other.width)) + return false; + return true; + } + + protected double getWidth() { + return width; + } + + protected double getLength() { + return length; + } + +} \ No newline at end of file diff --git a/core-java/src/main/java/org/baeldung/equalshashcode/entities/Shape.java b/core-java/src/main/java/org/baeldung/equalshashcode/entities/Shape.java new file mode 100644 index 0000000000..3bfc81da8f --- /dev/null +++ b/core-java/src/main/java/org/baeldung/equalshashcode/entities/Shape.java @@ -0,0 +1,7 @@ +package org.baeldung.equalshashcode.entities; + +public abstract class Shape { + public abstract double area(); + + public abstract double perimeter(); +} diff --git a/core-java/src/main/java/org/baeldung/equalshashcode/entities/Square.java b/core-java/src/main/java/org/baeldung/equalshashcode/entities/Square.java new file mode 100644 index 0000000000..f11e34f0ba --- /dev/null +++ b/core-java/src/main/java/org/baeldung/equalshashcode/entities/Square.java @@ -0,0 +1,58 @@ +package org.baeldung.equalshashcode.entities; + +import java.awt.Color; + +public class Square extends Rectangle { + + Color color; + + public Square(double width, Color color) { + super(width, width); + this.color = color; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((color == null) ? 0 : color.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (!(obj instanceof Square)) { + return false; + } + Square other = (Square) obj; + if (color == null) { + if (other.color != null) { + return false; + } + } else if (!color.equals(other.color)) { + return false; + } + return true; + } + + protected Color getColor() { + return color; + } + + protected void setColor(Color color) { + this.color = color; + } + +} diff --git a/core-java/src/main/resources/targetFile.tmp b/core-java/src/main/resources/targetFile.tmp deleted file mode 100644 index 20f137b416..0000000000 --- a/core-java/src/main/resources/targetFile.tmp +++ /dev/null @@ -1,2 +0,0 @@ -line 1 -a second line \ No newline at end of file diff --git a/core-java/src/main/webapp/WEB-INF/api-servlet.xml b/core-java/src/main/webapp/WEB-INF/api-servlet.xml deleted file mode 100644 index 4c74be8912..0000000000 --- a/core-java/src/main/webapp/WEB-INF/api-servlet.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/core-java/src/main/webapp/WEB-INF/web.xml b/core-java/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 935beae648..0000000000 --- a/core-java/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - Spring MVC Application - - - - contextClass - - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - contextConfigLocation - org.baeldung.config - - - - org.springframework.web.context.ContextLoaderListener - - - - - api - org.springframework.web.servlet.DispatcherServlet - 1 - - - api - / - - - - - - - \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/java/reflection/ReflectionTest.java b/core-java/src/test/java/com/baeldung/java/reflection/ReflectionTest.java new file mode 100644 index 0000000000..a12a2f205f --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java/reflection/ReflectionTest.java @@ -0,0 +1,326 @@ +package com.baeldung.java.reflection; + +import org.junit.Test; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; +import static org.junit.Assert.*; + +public class ReflectionTest { + + @Test + public void givenObject_whenGetsFieldNamesAtRuntime_thenCorrect() { + Object person = new Person(); + Field[] fields = person.getClass().getDeclaredFields(); + + List actualFieldNames = getFieldNames(fields); + + assertTrue(Arrays.asList("name", "age") + .containsAll(actualFieldNames)); + } + + @Test + public void givenObject_whenGetsClassName_thenCorrect() { + Object goat = new Goat("goat"); + Class clazz = goat.getClass(); + + assertEquals("Goat", clazz.getSimpleName()); + assertEquals("com.baeldung.java.reflection.Goat", clazz.getName()); + assertEquals("com.baeldung.java.reflection.Goat", clazz.getCanonicalName()); + } + + @Test + public void givenClassName_whenCreatesObject_thenCorrect() + throws ClassNotFoundException { + Class clazz = Class.forName("com.baeldung.java.reflection.Goat"); + + assertEquals("Goat", clazz.getSimpleName()); + assertEquals("com.baeldung.java.reflection.Goat", clazz.getName()); + assertEquals("com.baeldung.java.reflection.Goat", clazz.getCanonicalName()); + } + + @Test + public void givenClass_whenRecognisesModifiers_thenCorrect() + throws ClassNotFoundException { + Class goatClass = Class.forName("com.baeldung.java.reflection.Goat"); + Class animalClass = Class.forName("com.baeldung.java.reflection.Animal"); + int goatMods = goatClass.getModifiers(); + int animalMods = animalClass.getModifiers(); + + assertTrue(Modifier.isPublic(goatMods)); + assertTrue(Modifier.isAbstract(animalMods)); + assertTrue(Modifier.isPublic(animalMods)); + } + + @Test + public void givenClass_whenGetsPackageInfo_thenCorrect() { + Goat goat = new Goat("goat"); + Class goatClass = goat.getClass(); + Package pkg = goatClass.getPackage(); + + assertEquals("com.baeldung.java.reflection", pkg.getName()); + } + + @Test + public void givenClass_whenGetsSuperClass_thenCorrect() { + Goat goat = new Goat("goat"); + String str = "any string"; + + Class goatClass = goat.getClass(); + Class goatSuperClass = goatClass.getSuperclass(); + + assertEquals("Animal", goatSuperClass.getSimpleName()); + assertEquals("Object", str.getClass().getSuperclass().getSimpleName()); + + } + + @Test + public void givenClass_whenGetsImplementedInterfaces_thenCorrect() + throws ClassNotFoundException { + Class goatClass = Class.forName("com.baeldung.java.reflection.Goat"); + Class animalClass = Class.forName("com.baeldung.java.reflection.Animal"); + Class[] goatInterfaces = goatClass.getInterfaces(); + Class[] animalInterfaces = animalClass.getInterfaces(); + + assertEquals(1, goatInterfaces.length); + assertEquals(1, animalInterfaces.length); + assertEquals("Locomotion", goatInterfaces[0].getSimpleName()); + assertEquals("Eating", animalInterfaces[0].getSimpleName()); + } + + @Test + public void givenClass_whenGetsConstructor_thenCorrect() + throws ClassNotFoundException { + Class goatClass = Class.forName("com.baeldung.java.reflection.Goat"); + Constructor[] constructors = goatClass.getConstructors(); + + assertEquals(1, constructors.length); + assertEquals("com.baeldung.java.reflection.Goat", constructors[0].getName()); + } + + @Test + public void givenClass_whenGetsFields_thenCorrect() + throws ClassNotFoundException { + Class animalClass = Class.forName("com.baeldung.java.reflection.Animal"); + Field[] fields = animalClass.getDeclaredFields(); + + List actualFields = getFieldNames(fields); + + assertEquals(2, actualFields.size()); + assertTrue(actualFields.containsAll(Arrays.asList("name", "CATEGORY"))); + } + + @Test + public void givenClass_whenGetsMethods_thenCorrect() + throws ClassNotFoundException { + Class animalClass = Class.forName("com.baeldung.java.reflection.Animal"); + Method[] methods = animalClass.getDeclaredMethods(); + List actualMethods = getMethodNames(methods); + + assertEquals(4, actualMethods.size()); + assertTrue(actualMethods.containsAll(Arrays.asList("getName", + "setName", "getSound"))); + } + + @Test + public void givenClass_whenGetsAllConstructors_thenCorrect() + throws ClassNotFoundException { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Constructor[] constructors = birdClass.getConstructors(); + + assertEquals(3, constructors.length); + } + + @Test + public void givenClass_whenGetsEachConstructorByParamTypes_thenCorrect() + throws Exception { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Constructor cons1 = birdClass.getConstructor(); + Constructor cons2 = birdClass.getConstructor(String.class); + Constructor cons3 = birdClass.getConstructor(String.class, + boolean.class); + } + + @Test + public void givenClass_whenInstantiatesObjectsAtRuntime_thenCorrect() + throws Exception { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + + Constructor cons1 = birdClass.getConstructor(); + Constructor cons2 = birdClass.getConstructor(String.class); + Constructor cons3 = birdClass.getConstructor(String.class, + boolean.class); + + Bird bird1 = (Bird) cons1.newInstance(); + Bird bird2 = (Bird) cons2.newInstance("Weaver bird"); + Bird bird3 = (Bird) cons3.newInstance("dove", true); + + assertEquals("bird", bird1.getName()); + assertEquals("Weaver bird", bird2.getName()); + assertEquals("dove", bird3.getName()); + assertFalse(bird1.walks()); + assertTrue(bird3.walks()); + } + + @Test + public void givenClass_whenGetsPublicFields_thenCorrect() + throws ClassNotFoundException { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Field[] fields = birdClass.getFields(); + assertEquals(1, fields.length); + assertEquals("CATEGORY", fields[0].getName()); + + } + + @Test + public void givenClass_whenGetsPublicFieldByName_thenCorrect() + throws Exception { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Field field = birdClass.getField("CATEGORY"); + assertEquals("CATEGORY", field.getName()); + + } + + @Test + public void givenClass_whenGetsDeclaredFields_thenCorrect() + throws ClassNotFoundException { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Field[] fields = birdClass.getDeclaredFields(); + assertEquals(1, fields.length); + assertEquals("walks", fields[0].getName()); + } + + @Test + public void givenClass_whenGetsFieldsByName_thenCorrect() + throws Exception { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Field field = birdClass.getDeclaredField("walks"); + assertEquals("walks", field.getName()); + + } + + @Test + public void givenClassField_whenGetsType_thenCorrect() + throws Exception { + Field field = Class.forName("com.baeldung.java.reflection.Bird") + .getDeclaredField("walks"); + Class fieldClass = field.getType(); + assertEquals("boolean", fieldClass.getSimpleName()); + } + + @Test + public void givenClassField_whenSetsAndGetsValue_thenCorrect() + throws Exception { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Bird bird = (Bird) birdClass.newInstance(); + Field field = birdClass.getDeclaredField("walks"); + field.setAccessible(true); + + assertFalse(field.getBoolean(bird)); + assertFalse(bird.walks()); + + field.set(bird, true); + + assertTrue(field.getBoolean(bird)); + assertTrue(bird.walks()); + + } + + @Test + public void givenClassField_whenGetsAndSetsWithNull_thenCorrect() + throws Exception { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Field field = birdClass.getField("CATEGORY"); + field.setAccessible(true); + + assertEquals("domestic", field.get(null)); + } + + @Test + public void givenClass_whenGetsAllPublicMethods_thenCorrect() + throws ClassNotFoundException { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Method[] methods = birdClass.getMethods(); + List methodNames = getMethodNames(methods); + + assertTrue(methodNames.containsAll(Arrays + .asList("equals", "notifyAll", "hashCode", + "walks", "eats", "toString"))); + + } + + @Test + public void givenClass_whenGetsOnlyDeclaredMethods_thenCorrect() + throws ClassNotFoundException { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + List actualMethodNames = getMethodNames(birdClass.getDeclaredMethods()); + + List expectedMethodNames = Arrays.asList("setWalks", "walks", "getSound", "eats"); + + assertEquals(expectedMethodNames.size(), actualMethodNames.size()); + assertTrue(expectedMethodNames.containsAll(actualMethodNames)); + assertTrue(actualMethodNames.containsAll(expectedMethodNames)); + + } + + @Test + public void givenMethodName_whenGetsMethod_thenCorrect() + throws Exception { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Method walksMethod = birdClass.getDeclaredMethod("walks"); + Method setWalksMethod = birdClass.getDeclaredMethod("setWalks", + boolean.class); + + assertFalse(walksMethod.isAccessible()); + assertFalse(setWalksMethod.isAccessible()); + + walksMethod.setAccessible(true); + setWalksMethod.setAccessible(true); + + assertTrue(walksMethod.isAccessible()); + assertTrue(setWalksMethod.isAccessible()); + + } + + @Test + public void givenMethod_whenInvokes_thenCorrect() + throws Exception { + Class birdClass = Class.forName("com.baeldung.java.reflection.Bird"); + Bird bird = (Bird) birdClass.newInstance(); + Method setWalksMethod = birdClass.getDeclaredMethod("setWalks", + boolean.class); + Method walksMethod = birdClass.getDeclaredMethod("walks"); + boolean walks = (boolean) walksMethod.invoke(bird); + + assertFalse(walks); + assertFalse(bird.walks()); + + setWalksMethod.invoke(bird, true); + boolean walks2 = (boolean) walksMethod.invoke(bird); + + assertTrue(walks2); + assertTrue(bird.walks()); + + } + + private static List getFieldNames(Field[] fields) { + List fieldNames = new ArrayList<>(); + for (Field field : fields) + fieldNames.add(field.getName()); + return fieldNames; + + } + + private static List getMethodNames(Method[] methods) { + List methodNames = new ArrayList<>(); + for (Method method : methods) + methodNames.add(method.getName()); + return methodNames; + } + +} diff --git a/core-java/src/test/java/com/baeldung/java/regex/RegexTest.java b/core-java/src/test/java/com/baeldung/java/regex/RegexTest.java new file mode 100644 index 0000000000..414401eb85 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java/regex/RegexTest.java @@ -0,0 +1,502 @@ +package com.baeldung.java.regex; + +import static org.junit.Assert.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Test; + +public class RegexTest { + private static Pattern pattern; + private static Matcher matcher; + + @Test + public void givenText_whenSimpleRegexMatches_thenCorrect() { + Pattern pattern = Pattern.compile("foo"); + Matcher matcher = pattern.matcher("foo"); + assertTrue(matcher.find()); + } + + @Test + public void givenText_whenSimpleRegexMatchesTwice_thenCorrect() { + Pattern pattern = Pattern.compile("foo"); + Matcher matcher = pattern.matcher("foofoo"); + int matches = 0; + while (matcher.find()) + matches++; + assertEquals(matches, 2); + + } + + @Test + public void givenText_whenMatchesWithDotMetach_thenCorrect() { + int matches = runTest(".", "foo"); + assertTrue(matches > 0); + } + + @Test + public void givenRepeatedText_whenMatchesOnceWithDotMetach_thenCorrect() { + int matches = runTest("foo.", "foofoo"); + assertTrue(matches > 0); + assertEquals(matches, 1); + } + + @Test + public void givenORSet_whenMatchesAny_thenCorrect() { + int matches = runTest("[abc]", "b"); + assertTrue(matches > 0); + assertEquals(matches, 1); + } + + @Test + public void givenORSet_whenMatchesAnyAndAll_thenCorrect() { + int matches = runTest("[abc]", "cab"); + assertTrue(matches > 0); + assertEquals(matches, 3); + } + + @Test + public void givenORSet_whenMatchesAllCombinations_thenCorrect() { + int matches = runTest("[bcr]at", "bat cat rat"); + assertTrue(matches > 0); + assertEquals(matches, 3); + } + + @Test + public void givenNORSet_whenMatchesNon_thenCorrect() { + int matches = runTest("[^abc]", "g"); + assertTrue(matches > 0); + } + + @Test + public void givenNORSet_whenMatchesAllExceptElements_thenCorrect() { + int matches = runTest("[^bcr]at", "sat mat eat"); + assertTrue(matches > 0); + } + + @Test + public void givenUpperCaseRange_whenMatchesUpperCase_thenCorrect() { + int matches = runTest("[A-Z]", "Two Uppercase alphabets 34 overall"); + assertTrue(matches > 0); + assertEquals(matches, 2); + } + + @Test + public void givenLowerCaseRange_whenMatchesLowerCase_thenCorrect() { + int matches = runTest("[a-z]", "Two Uppercase alphabets 34 overall"); + assertTrue(matches > 0); + assertEquals(matches, 26); + } + + @Test + public void givenBothLowerAndUpperCaseRange_whenMatchesAllLetters_thenCorrect() { + int matches = runTest("[a-zA-Z]", "Two Uppercase alphabets 34 overall"); + assertTrue(matches > 0); + assertEquals(matches, 28); + } + + @Test + public void givenNumberRange_whenMatchesAccurately_thenCorrect() { + int matches = runTest("[1-5]", "Two Uppercase alphabets 34 overall"); + assertTrue(matches > 0); + assertEquals(matches, 2); + } + + @Test + public void givenNumberRange_whenMatchesAccurately_thenCorrect2() { + int matches = runTest("[30-35]", "Two Uppercase alphabets 34 overall"); + assertTrue(matches > 0); + assertEquals(matches, 1); + } + + @Test + public void givenTwoSets_whenMatchesUnion_thenCorrect() { + int matches = runTest("[1-3[7-9]]", "123456789"); + assertTrue(matches > 0); + assertEquals(matches, 6); + } + + @Test + public void givenTwoSets_whenMatchesIntersection_thenCorrect() { + int matches = runTest("[1-6&&[3-9]]", "123456789"); + assertTrue(matches > 0); + assertEquals(matches, 4); + } + + @Test + public void givenSetWithSubtraction_whenMatchesAccurately_thenCorrect() { + int matches = runTest("[0-9&&[^2468]]", "123456789"); + assertTrue(matches > 0); + assertEquals(matches, 5); + } + + @Test + public void givenDigits_whenMatches_thenCorrect() { + int matches = runTest("\\d", "123"); + assertTrue(matches > 0); + assertEquals(matches, 3); + } + + @Test + public void givenNonDigits_whenMatches_thenCorrect() { + int matches = runTest("\\D", "a6c"); + assertTrue(matches > 0); + assertEquals(matches, 2); + } + + @Test + public void givenWhiteSpace_whenMatches_thenCorrect() { + int matches = runTest("\\s", "a c"); + assertTrue(matches > 0); + assertEquals(matches, 1); + } + + @Test + public void givenNonWhiteSpace_whenMatches_thenCorrect() { + int matches = runTest("\\S", "a c"); + assertTrue(matches > 0); + assertEquals(matches, 2); + } + + @Test + public void givenWordCharacter_whenMatches_thenCorrect() { + int matches = runTest("\\w", "hi!"); + assertTrue(matches > 0); + assertEquals(matches, 2); + } + + @Test + public void givenNonWordCharacter_whenMatches_thenCorrect() { + int matches = runTest("\\W", "hi!"); + assertTrue(matches > 0); + assertEquals(matches, 1); + } + + @Test + public void givenZeroOrOneQuantifier_whenMatches_thenCorrect() { + int matches = runTest("\\a?", "hi"); + assertTrue(matches > 0); + assertEquals(matches, 3); + } + + @Test + public void givenZeroOrOneQuantifier_whenMatches_thenCorrect2() { + int matches = runTest("\\a{0,1}", "hi"); + assertTrue(matches > 0); + assertEquals(matches, 3); + } + + @Test + public void givenZeroOrManyQuantifier_whenMatches_thenCorrect() { + int matches = runTest("\\a*", "hi"); + assertTrue(matches > 0); + assertEquals(matches, 3); + } + + @Test + public void givenZeroOrManyQuantifier_whenMatches_thenCorrect2() { + int matches = runTest("\\a{0,}", "hi"); + assertTrue(matches > 0); + assertEquals(matches, 3); + } + + @Test + public void givenOneOrManyQuantifier_whenMatches_thenCorrect() { + int matches = runTest("\\a+", "hi"); + assertFalse(matches > 0); + } + + @Test + public void givenOneOrManyQuantifier_whenMatches_thenCorrect2() { + int matches = runTest("\\a{1,}", "hi"); + assertFalse(matches > 0); + } + + @Test + public void givenBraceQuantifier_whenMatches_thenCorrect() { + int matches = runTest("a{3}", "aaaaaa"); + assertTrue(matches > 0); + assertEquals(matches, 2); + } + + @Test + public void givenBraceQuantifier_whenFailsToMatch_thenCorrect() { + int matches = runTest("a{3}", "aa"); + assertFalse(matches > 0); + } + + @Test + public void givenBraceQuantifierWithRange_whenMatches_thenCorrect() { + int matches = runTest("a{2,3}", "aaaa"); + assertTrue(matches > 0); + assertEquals(matches, 1); + } + + @Test + public void givenBraceQuantifierWithRange_whenMatchesLazily_thenCorrect() { + int matches = runTest("a{2,3}?", "aaaa"); + assertTrue(matches > 0); + assertEquals(matches, 2); + } + + @Test + public void givenCapturingGroup_whenMatches_thenCorrect() { + int matches = runTest("(\\d\\d)", "12"); + assertTrue(matches > 0); + assertEquals(matches, 1); + } + + @Test + public void givenCapturingGroup_whenMatches_thenCorrect2() { + int matches = runTest("(\\d\\d)", "1212"); + assertTrue(matches > 0); + assertEquals(matches, 2); + } + + @Test + public void givenCapturingGroup_whenMatches_thenCorrect3() { + int matches = runTest("(\\d\\d)(\\d\\d)", "1212"); + assertTrue(matches > 0); + assertEquals(matches, 1); + } + + @Test + public void givenCapturingGroup_whenMatchesWithBackReference_thenCorrect() { + int matches = runTest("(\\d\\d)\\1", "1212"); + assertTrue(matches > 0); + assertEquals(matches, 1); + } + + @Test + public void givenCapturingGroup_whenMatchesWithBackReference_thenCorrect2() { + int matches = runTest("(\\d\\d)\\1\\1\\1", "12121212"); + assertTrue(matches > 0); + assertEquals(matches, 1); + } + + @Test + public void givenCapturingGroupAndWrongInput_whenMatchFailsWithBackReference_thenCorrect() { + int matches = runTest("(\\d\\d)\\1", "1213"); + assertFalse(matches > 0); + } + + @Test + public void givenText_whenMatchesAtBeginning_thenCorrect() { + int matches = runTest("^dog", "dogs are friendly"); + assertTrue(matches > 0); + } + + @Test + public void givenTextAndWrongInput_whenMatchFailsAtBeginning_thenCorrect() { + int matches = runTest("^dog", "are dogs are friendly?"); + assertFalse(matches > 0); + } + + @Test + public void givenText_whenMatchesAtEnd_thenCorrect() { + int matches = runTest("dog$", "Man's best friend is a dog"); + assertTrue(matches > 0); + } + + @Test + public void givenTextAndWrongInput_whenMatchFailsAtEnd_thenCorrect() { + int matches = runTest("dog$", "is a dog man's best friend?"); + assertFalse(matches > 0); + } + + @Test + public void givenText_whenMatchesAtWordBoundary_thenCorrect() { + int matches = runTest("\\bdog\\b", "a dog is friendly"); + assertTrue(matches > 0); + } + + @Test + public void givenText_whenMatchesAtWordBoundary_thenCorrect2() { + int matches = runTest("\\bdog\\b", "dog is man's best friend"); + assertTrue(matches > 0); + } + + @Test + public void givenWrongText_whenMatchFailsAtWordBoundary_thenCorrect() { + int matches = runTest("\\bdog\\b", "snoop dogg is a rapper"); + assertFalse(matches > 0); + } + + @Test + public void givenText_whenMatchesAtWordAndNonBoundary_thenCorrect() { + int matches = runTest("\\bdog\\B", "snoop dogg is a rapper"); + assertTrue(matches > 0); + } + + @Test + public void givenRegexWithoutCanonEq_whenMatchFailsOnEquivalentUnicode_thenCorrect() { + int matches = runTest("\u00E9", "\u0065\u0301"); + assertFalse(matches > 0); + } + + @Test + public void givenRegexWithCanonEq_whenMatchesOnEquivalentUnicode_thenCorrect() { + int matches = runTest("\u00E9", "\u0065\u0301", Pattern.CANON_EQ); + assertTrue(matches > 0); + } + + @Test + public void givenRegexWithDefaultMatcher_whenMatchFailsOnDifferentCases_thenCorrect() { + int matches = runTest("dog", "This is a Dog"); + assertFalse(matches > 0); + } + + @Test + public void givenRegexWithCaseInsensitiveMatcher_whenMatchesOnDifferentCases_thenCorrect() { + int matches = runTest("dog", "This is a Dog", Pattern.CASE_INSENSITIVE); + assertTrue(matches > 0); + } + + @Test + public void givenRegexWithEmbeddedCaseInsensitiveMatcher_whenMatchesOnDifferentCases_thenCorrect() { + int matches = runTest("(?i)dog", "This is a Dog"); + assertTrue(matches > 0); + } + + @Test + public void givenRegexWithComments_whenMatchFailsWithoutFlag_thenCorrect() { + int matches = runTest("dog$ #check for word dog at end of text", "This is a dog"); + assertFalse(matches > 0); + } + + @Test + public void givenRegexWithComments_whenMatchesWithFlag_thenCorrect() { + int matches = runTest("dog$ #check for word dog at end of text", "This is a dog", Pattern.COMMENTS); + assertTrue(matches > 0); + } + + @Test + public void givenRegexWithComments_whenMatchesWithEmbeddedFlag_thenCorrect() { + int matches = runTest("(?x)dog$ #check for word dog at end of text", "This is a dog"); + assertTrue(matches > 0); + } + + @Test + public void givenRegexWithLineTerminator_whenMatchFails_thenCorrect() { + Pattern pattern = Pattern.compile("(.*)"); + Matcher matcher = pattern.matcher("this is a text" + System.getProperty("line.separator") + " continued on another line"); + matcher.find(); + assertEquals("this is a text", matcher.group(1)); + } + + @Test + public void givenRegexWithLineTerminator_whenMatchesWithDotall_thenCorrect() { + Pattern pattern = Pattern.compile("(.*)", Pattern.DOTALL); + Matcher matcher = pattern.matcher("this is a text" + System.getProperty("line.separator") + " continued on another line"); + matcher.find(); + assertEquals("this is a text" + System.getProperty("line.separator") + " continued on another line", matcher.group(1)); + } + + @Test + public void givenRegexWithLineTerminator_whenMatchesWithEmbeddedDotall_thenCorrect() { + Pattern pattern = Pattern.compile("(?s)(.*)"); + Matcher matcher = pattern.matcher("this is a text" + System.getProperty("line.separator") + " continued on another line"); + matcher.find(); + assertEquals("this is a text" + System.getProperty("line.separator") + " continued on another line", matcher.group(1)); + } + + @Test + public void givenRegex_whenMatchesWithoutLiteralFlag_thenCorrect() { + int matches = runTest("(.*)", "text"); + assertTrue(matches > 0); + } + + @Test + public void givenRegex_whenMatchFailsWithLiteralFlag_thenCorrect() { + int matches = runTest("(.*)", "text", Pattern.LITERAL); + assertFalse(matches > 0); + } + + @Test + public void givenRegex_whenMatchesWithLiteralFlag_thenCorrect() { + int matches = runTest("(.*)", "text(.*)", Pattern.LITERAL); + assertTrue(matches > 0); + } + + @Test + public void givenRegex_whenMatchFailsWithoutMultilineFlag_thenCorrect() { + int matches = runTest("dog$", "This is a dog" + System.getProperty("line.separator") + "this is a fox"); + assertFalse(matches > 0); + } + + @Test + public void givenRegex_whenMatchesWithMultilineFlag_thenCorrect() { + int matches = runTest("dog$", "This is a dog" + System.getProperty("line.separator") + "this is a fox", Pattern.MULTILINE); + assertTrue(matches > 0); + } + + @Test + public void givenRegex_whenMatchesWithEmbeddedMultilineFlag_thenCorrect() { + int matches = runTest("(?m)dog$", "This is a dog" + System.getProperty("line.separator") + "this is a fox"); + assertTrue(matches > 0); + } + + @Test + public void givenMatch_whenGetsIndices_thenCorrect() { + Pattern pattern = Pattern.compile("dog"); + Matcher matcher = pattern.matcher("This dog is mine"); + matcher.find(); + assertEquals(5, matcher.start()); + assertEquals(8, matcher.end()); + } + + @Test + public void whenStudyMethodsWork_thenCorrect() { + Pattern pattern = Pattern.compile("dog"); + Matcher matcher = pattern.matcher("dogs are friendly"); + assertTrue(matcher.lookingAt()); + assertFalse(matcher.matches()); + + } + + @Test + public void whenMatchesStudyMethodWorks_thenCorrect() { + Pattern pattern = Pattern.compile("dog"); + Matcher matcher = pattern.matcher("dog"); + assertTrue(matcher.matches()); + + } + + @Test + public void whenReplaceFirstWorks_thenCorrect() { + Pattern pattern = Pattern.compile("dog"); + Matcher matcher = pattern.matcher("dogs are domestic animals, dogs are friendly"); + String newStr = matcher.replaceFirst("cat"); + assertEquals("cats are domestic animals, dogs are friendly", newStr); + + } + + @Test + public void whenReplaceAllWorks_thenCorrect() { + Pattern pattern = Pattern.compile("dog"); + Matcher matcher = pattern.matcher("dogs are domestic animals, dogs are friendly"); + String newStr = matcher.replaceAll("cat"); + assertEquals("cats are domestic animals, cats are friendly", newStr); + + } + + public synchronized static int runTest(String regex, String text) { + pattern = Pattern.compile(regex); + matcher = pattern.matcher(text); + int matches = 0; + while (matcher.find()) + matches++; + return matches; + } + + public synchronized static int runTest(String regex, String text, int flags) { + pattern = Pattern.compile(regex, flags); + matcher = pattern.matcher(text); + int matches = 0; + while (matcher.find()) + matches++; + return matches; + } +} + diff --git a/core-java/src/test/java/org/baeldung/core/exceptions/FileNotFoundExceptionTest.java b/core-java/src/test/java/org/baeldung/core/exceptions/FileNotFoundExceptionTest.java new file mode 100644 index 0000000000..23be2200d3 --- /dev/null +++ b/core-java/src/test/java/org/baeldung/core/exceptions/FileNotFoundExceptionTest.java @@ -0,0 +1,57 @@ +package org.baeldung.core.exceptions; + +import org.apache.log4j.Logger; +import org.junit.Test; + +import java.io.*; + +public class FileNotFoundExceptionTest { + + private static final Logger LOG = Logger.getLogger(FileNotFoundExceptionTest.class); + + private String fileName = Double.toString(Math.random()); + + @Test(expected = BusinessException.class) + public void raiseBusinessSpecificException() throws IOException { + try { + readFailingFile(); + } catch (FileNotFoundException ex) { + throw new BusinessException("BusinessException: necessary file was not present.", ex); + } + } + + @Test + public void createFile() throws IOException { + try { + readFailingFile(); + } catch (FileNotFoundException ex) { + try { + new File(fileName).createNewFile(); + readFailingFile(); + } catch (IOException ioe) { + throw new RuntimeException("BusinessException: even creation is not possible.", ioe); + } + } + } + + @Test + public void logError() throws IOException { + try { + readFailingFile(); + } catch (FileNotFoundException ex) { + LOG.error("Optional file " + fileName + " was not found.", ex); + } + } + + private void readFailingFile() throws IOException { + BufferedReader rd = new BufferedReader(new FileReader(new File(fileName))); + rd.readLine(); + // no need to close file + } + + private class BusinessException extends RuntimeException { + BusinessException(String string, FileNotFoundException ex) { + super(string, ex); + } + } +} diff --git a/core-java/src/test/java/org/baeldung/equalshashcode/entities/ComplexClassTest.java b/core-java/src/test/java/org/baeldung/equalshashcode/entities/ComplexClassTest.java new file mode 100644 index 0000000000..75d96e5989 --- /dev/null +++ b/core-java/src/test/java/org/baeldung/equalshashcode/entities/ComplexClassTest.java @@ -0,0 +1,33 @@ +package org.baeldung.equalshashcode.entities; + +import java.util.ArrayList; +import java.util.HashSet; + +import org.junit.Assert; +import org.junit.Test; + +public class ComplexClassTest { + + @Test + public void testEqualsAndHashcodes() { + + ArrayList strArrayList = new ArrayList(); + strArrayList.add("abc"); + strArrayList.add("def"); + ComplexClass aObject = new ComplexClass(strArrayList, new HashSet(45, 67)); + ComplexClass bObject = new ComplexClass(strArrayList, new HashSet(45, 67)); + + ArrayList strArrayListD = new ArrayList(); + strArrayListD.add("lmn"); + strArrayListD.add("pqr"); + ComplexClass dObject = new ComplexClass(strArrayListD, new HashSet(45, 67)); + + Assert.assertTrue(aObject.equals(bObject) && bObject.equals(aObject)); + + Assert.assertTrue(aObject.hashCode() == bObject.hashCode()); + + Assert.assertFalse(aObject.equals(dObject)); + Assert.assertFalse(aObject.hashCode() == dObject.hashCode()); + } + +} diff --git a/core-java/src/test/java/org/baeldung/equalshashcode/entities/PrimitiveClassTest.java b/core-java/src/test/java/org/baeldung/equalshashcode/entities/PrimitiveClassTest.java new file mode 100644 index 0000000000..16f25ae021 --- /dev/null +++ b/core-java/src/test/java/org/baeldung/equalshashcode/entities/PrimitiveClassTest.java @@ -0,0 +1,23 @@ +package org.baeldung.equalshashcode.entities; + +import org.junit.Assert; +import org.junit.Test; + +public class PrimitiveClassTest { + + @Test + public void testTwoEqualsObjects() { + + PrimitiveClass aObject = new PrimitiveClass(false, 2); + PrimitiveClass bObject = new PrimitiveClass(false, 2); + PrimitiveClass dObject = new PrimitiveClass(true, 2); + + Assert.assertTrue(aObject.equals(bObject) && bObject.equals(aObject)); + + Assert.assertTrue(aObject.hashCode() == bObject.hashCode()); + + Assert.assertFalse(aObject.equals(dObject)); + Assert.assertFalse(aObject.hashCode() == dObject.hashCode()); + } + +} diff --git a/core-java/src/test/java/org/baeldung/equalshashcode/entities/SquareClassTest.java b/core-java/src/test/java/org/baeldung/equalshashcode/entities/SquareClassTest.java new file mode 100644 index 0000000000..52d024a696 --- /dev/null +++ b/core-java/src/test/java/org/baeldung/equalshashcode/entities/SquareClassTest.java @@ -0,0 +1,26 @@ +package org.baeldung.equalshashcode.entities; + +import java.awt.Color; + +import org.junit.Assert; +import org.junit.Test; + +public class SquareClassTest { + + @Test + public void testEqualsAndHashcodes() { + + Square aObject = new Square(10, Color.BLUE); + Square bObject = new Square(10, Color.BLUE); + + Square dObject = new Square(20, Color.BLUE); + + Assert.assertTrue(aObject.equals(bObject) && bObject.equals(aObject)); + + Assert.assertTrue(aObject.hashCode() == bObject.hashCode()); + + Assert.assertFalse(aObject.equals(dObject)); + Assert.assertFalse(aObject.hashCode() == dObject.hashCode()); + } + +} diff --git a/core-java/src/test/java/org/baeldung/java/arrays/ArraysJoinAndSplitJUnitTest.java b/core-java/src/test/java/org/baeldung/java/arrays/ArraysJoinAndSplitJUnitTest.java new file mode 100644 index 0000000000..ad1f2dc70c --- /dev/null +++ b/core-java/src/test/java/org/baeldung/java/arrays/ArraysJoinAndSplitJUnitTest.java @@ -0,0 +1,44 @@ +package org.baeldung.java.arrays; + +import java.util.Arrays; + +import org.junit.Assert; +import org.junit.Test; + +public class ArraysJoinAndSplitJUnitTest { + + private final String[] sauces = {"Marinara", "Olive Oil"}; + private final String[] cheeses = {"Mozzarella", "Feta", "Parmesan"}; + private final String[] vegetables = {"Olives", "Spinach", "Green Peppers"}; + + private final String[] customers = {"Jay", "Harry", "Ronnie", "Gary", "Ross"}; + + @Test + public void givenThreeStringArrays_whenJoiningIntoOneStringArray_shouldSucceed() { + String[] toppings = new String[sauces.length + cheeses.length + vegetables.length]; + + System.arraycopy(sauces, 0, toppings, 0, sauces.length); + int AddedSoFar = sauces.length; + + System.arraycopy(cheeses, 0, toppings, AddedSoFar, cheeses.length); + AddedSoFar += cheeses.length; + + System.arraycopy(vegetables, 0, toppings, AddedSoFar, vegetables.length); + + Assert.assertArrayEquals(toppings, + new String[]{"Marinara", "Olive Oil", "Mozzarella", "Feta", + "Parmesan", "Olives", "Spinach", "Green Peppers"}); + } + + + @Test + public void givenOneStringArray_whenSplittingInHalfTwoStringArrays_shouldSucceed() { + int ordersHalved = (customers.length / 2) + (customers.length % 2); + + String[] driverOne = Arrays.copyOf(customers, ordersHalved); + String[] driverTwo = Arrays.copyOfRange(customers, ordersHalved, customers.length); + + Assert.assertArrayEquals(driverOne, new String[]{"Jay", "Harry", "Ronnie"}); + Assert.assertArrayEquals(driverTwo, new String[]{"Gary", "Ross"}); + } +} diff --git a/core-java/src/test/java/org/baeldung/java/collections/ArrayListTest.java b/core-java/src/test/java/org/baeldung/java/collections/ArrayListTest.java new file mode 100644 index 0000000000..30b0111555 --- /dev/null +++ b/core-java/src/test/java/org/baeldung/java/collections/ArrayListTest.java @@ -0,0 +1,146 @@ +package org.baeldung.java.collections; + +import com.google.common.collect.Sets; +import org.junit.Before; +import org.junit.Test; + +import java.util.*; +import java.util.stream.*; + +import static java.util.stream.Collectors.*; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.*; + +public class ArrayListTest { + + private List stringsToSearch; + + @Before + public void setUp() { + List list = LongStream.range(0, 16) + .boxed() + .map(Long::toHexString) + .collect(toCollection(ArrayList::new)); + stringsToSearch = new ArrayList<>(list); + stringsToSearch.addAll(list); + } + + @Test + public void givenNewArrayList_whenCheckCapacity_thenDefaultValue() { + List list = new ArrayList<>(); + assertTrue(list.isEmpty()); + } + + @Test + public void givenCollection_whenProvideItToArrayListCtor_thenArrayListIsPopulatedWithItsElements() { + Collection numbers = + IntStream.range(0, 10).boxed().collect(toSet()); + + List list = new ArrayList<>(numbers); + assertEquals(10, list.size()); + assertTrue(numbers.containsAll(list)); + } + + @Test + public void givenElement_whenAddToArrayList_thenIsAdded() { + List list = new ArrayList<>(); + + list.add(1L); + list.add(2L); + list.add(1, 3L); + + assertThat(Arrays.asList(1L, 3L, 2L), equalTo(list)); + } + + @Test + public void givenCollection_whenAddToArrayList_thenIsAdded() { + List list = new ArrayList<>(Arrays.asList(1L, 2L, 3L)); + LongStream.range(4, 10).boxed() + .collect(collectingAndThen(toCollection(ArrayList::new), ys -> list.addAll(0, ys))); + + assertThat(Arrays.asList(4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L), equalTo(list)); + } + + @Test + public void givenExistingElement_whenCallIndexOf_thenReturnCorrectIndex() { + assertEquals(10, stringsToSearch.indexOf("a")); + assertEquals(26, stringsToSearch.lastIndexOf("a")); + } + + @Test + public void givenCondition_whenIterateArrayList_thenFindAllElementsSatisfyingCondition() { + Iterator it = stringsToSearch.iterator(); + Set matchingStrings = new HashSet<>(Arrays.asList("a", "c", "9")); + + List result = new ArrayList<>(); + while (it.hasNext()) { + String s = it.next(); + if (matchingStrings.contains(s)) { + result.add(s); + } + } + + assertEquals(6, result.size()); + } + + @Test + public void givenPredicate_whenIterateArrayList_thenFindAllElementsSatisfyingPredicate() { + Set matchingStrings = new HashSet<>(Arrays.asList("a", "c", "9")); + + List result = stringsToSearch + .stream() + .filter(matchingStrings::contains) + .collect(toCollection(ArrayList::new)); + + assertEquals(6, result.size()); + } + + @Test + public void givenSortedArray_whenUseBinarySearch_thenFindElement() { + List copy = new ArrayList<>(stringsToSearch); + Collections.sort(copy); + int index = Collections.binarySearch(copy, "f"); + assertThat(index, not(equalTo(-1))); + } + + @Test + public void givenIndex_whenRemove_thenCorrectElementRemoved() { + List list = IntStream.range(0, 10).boxed().collect(toCollection(ArrayList::new)); + Collections.reverse(list); + + list.remove(0); + assertThat(list.get(0), equalTo(8)); + + list.remove(Integer.valueOf(0)); + assertFalse(list.contains(0)); + } + + @Test + public void givenListIterator_whenReverseTraversal_thenRetrieveElementsInOppositeOrder() { + List list = IntStream.range(0, 10).boxed().collect(toCollection(ArrayList::new)); + ListIterator it = list.listIterator(list.size()); + List result = new ArrayList<>(list.size()); + while (it.hasPrevious()) { + result.add(it.previous()); + } + + Collections.reverse(list); + assertThat(result, equalTo(list)); + } + + @Test + public void givenCondition_whenIterateArrayList_thenRemoveAllElementsSatisfyingCondition() { + Set matchingStrings + = Sets.newHashSet("a", "b", "c", "d", "e", "f"); + + Iterator it = stringsToSearch.iterator(); + while (it.hasNext()) { + if (matchingStrings.contains(it.next())) { + it.remove(); + } + } + + assertEquals(20, stringsToSearch.size()); + } +} diff --git a/core-java/src/test/java/org/baeldung/java/collections/CollectionsJoinAndSplitJUnitTest.java b/core-java/src/test/java/org/baeldung/java/collections/CollectionsJoinAndSplitJUnitTest.java new file mode 100644 index 0000000000..c288cf499d --- /dev/null +++ b/core-java/src/test/java/org/baeldung/java/collections/CollectionsJoinAndSplitJUnitTest.java @@ -0,0 +1,62 @@ +package org.baeldung.java.collections; + +import java.util.ArrayList; +import java.util.Collections; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class CollectionsJoinAndSplitJUnitTest { + + private ArrayList sauces = new ArrayList<>(); + private ArrayList cheeses = new ArrayList<>(); + private ArrayList vegetables = new ArrayList<>(); + + private ArrayList> ingredients = new ArrayList<>(); + + @Before + public void init() { + sauces.add("Olive Oil"); + sauces.add("Marinara"); + + cheeses.add("Mozzarella"); + cheeses.add("Feta"); + cheeses.add("Parmesan"); + + vegetables.add("Olives"); + vegetables.add("Spinach"); + vegetables.add("Green Peppers"); + + ingredients.add(sauces); + ingredients.add(cheeses); + ingredients.add(vegetables); + } + + @Test + public void givenThreeArrayLists_whenJoiningIntoOneArrayList_shouldSucceed() { + ArrayList> toppings = new ArrayList<>(); + + toppings.add(sauces); + toppings.add(cheeses); + toppings.add(vegetables); + + Assert.assertTrue(toppings.size() == 3); + Assert.assertTrue(toppings.contains(sauces)); + Assert.assertTrue(toppings.contains(cheeses)); + Assert.assertTrue(toppings.contains(vegetables)); + } + + @Test + public void givenOneArrayList_whenSplittingIntoTwoArrayLists_shouldSucceed() { + + ArrayList> removedToppings = new ArrayList<>(); + removedToppings.add(ingredients.remove(ingredients.indexOf(vegetables))); + + Assert.assertTrue(removedToppings.contains(vegetables)); + Assert.assertTrue(removedToppings.size() == 1); + Assert.assertTrue(ingredients.size() == 2); + Assert.assertTrue(ingredients.contains(sauces)); + Assert.assertTrue(ingredients.contains(cheeses)); + } +} diff --git a/core-java/src/test/java/org/baeldung/java/collections/JavaCollectionConversionUnitTest.java b/core-java/src/test/java/org/baeldung/java/collections/JavaCollectionConversionUnitTest.java index 95b79810cd..a5f684a141 100644 --- a/core-java/src/test/java/org/baeldung/java/collections/JavaCollectionConversionUnitTest.java +++ b/core-java/src/test/java/org/baeldung/java/collections/JavaCollectionConversionUnitTest.java @@ -31,7 +31,7 @@ public class JavaCollectionConversionUnitTest { @Test public final void givenUsingCoreJava_whenListConvertedToArray_thenCorrect() { - final List sourceList = Lists. newArrayList(0, 1, 2, 3, 4, 5); + final List sourceList = Arrays.asList(0, 1, 2, 3, 4, 5); final Integer[] targetArray = sourceList.toArray(new Integer[sourceList.size()]); } diff --git a/core-java/src/test/java/org/baeldung/java/enums/PizzaTest.java b/core-java/src/test/java/org/baeldung/java/enums/PizzaTest.java new file mode 100644 index 0000000000..a6814ee600 --- /dev/null +++ b/core-java/src/test/java/org/baeldung/java/enums/PizzaTest.java @@ -0,0 +1,80 @@ +package org.baeldung.java.enums; + + +import com.baeldung.enums.Pizza; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; + +import static junit.framework.TestCase.assertTrue; + + +public class PizzaTest { + @Test + public void givenPizaOrder_whenReady_thenDeliverable() { + Pizza testPz = new Pizza(); + testPz.setStatus(Pizza.PizzaStatus.READY); + assertTrue(testPz.isDeliverable()); + } + + @Test + public void givenPizaOrders_whenRetrievingUnDeliveredPzs_thenCorrectlyRetrieved() { + List pzList = new ArrayList<>(); + Pizza pz1 = new Pizza(); + pz1.setStatus(Pizza.PizzaStatus.DELIVERED); + + Pizza pz2 = new Pizza(); + pz2.setStatus(Pizza.PizzaStatus.ORDERED); + + Pizza pz3 = new Pizza(); + pz3.setStatus(Pizza.PizzaStatus.ORDERED); + + Pizza pz4 = new Pizza(); + pz4.setStatus(Pizza.PizzaStatus.READY); + + pzList.add(pz1); + pzList.add(pz2); + pzList.add(pz3); + pzList.add(pz4); + + List undeliveredPzs = Pizza.getAllUndeliveredPizzas(pzList); + assertTrue(undeliveredPzs.size() == 3); + } + + @Test + public void givenPizaOrders_whenGroupByStatusCalled_thenCorrectlyGrouped() { + + List pzList = new ArrayList<>(); + Pizza pz1 = new Pizza(); + pz1.setStatus(Pizza.PizzaStatus.DELIVERED); + + Pizza pz2 = new Pizza(); + pz2.setStatus(Pizza.PizzaStatus.ORDERED); + + Pizza pz3 = new Pizza(); + pz3.setStatus(Pizza.PizzaStatus.ORDERED); + + Pizza pz4 = new Pizza(); + pz4.setStatus(Pizza.PizzaStatus.READY); + + pzList.add(pz1); + pzList.add(pz2); + pzList.add(pz3); + pzList.add(pz4); + + EnumMap> map = Pizza.groupPizzaByStatus(pzList); + assertTrue(map.get(Pizza.PizzaStatus.DELIVERED).size() == 1); + assertTrue(map.get(Pizza.PizzaStatus.ORDERED).size() == 2); + assertTrue(map.get(Pizza.PizzaStatus.READY).size() == 1); + } + + @Test + public void givenPizaOrder_whenDelivered_thenPizzaGetsDeliveredAndStatusChanges() { + Pizza pz = new Pizza(); + pz.setStatus(Pizza.PizzaStatus.READY); + pz.deliver(); + assertTrue(pz.getStatus() == Pizza.PizzaStatus.DELIVERED); + } +} diff --git a/core-java/src/test/java/org/baeldung/java/io/JavaFileIntegrationTest.java b/core-java/src/test/java/org/baeldung/java/io/JavaFileIntegrationTest.java index c139e34afb..24213ba869 100644 --- a/core-java/src/test/java/org/baeldung/java/io/JavaFileIntegrationTest.java +++ b/core-java/src/test/java/org/baeldung/java/io/JavaFileIntegrationTest.java @@ -1,5 +1,6 @@ package org.baeldung.java.io; +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.junit.Assert.assertTrue; import java.io.File; @@ -57,9 +58,8 @@ public class JavaFileIntegrationTest { @Test public final void givenUsingJDK7Nio2_whenMovingFile_thenCorrect() throws IOException { - final Path fileToMovePath = Files.createFile(Paths.get("src/test/resources/fileToMove.txt")); - final Path dirPath = Paths.get("src/test/resources/"); - final Path targetPath = Files.createDirectory(dirPath); + final Path fileToMovePath = Files.createFile(Paths.get("src/test/resources/" + randomAlphabetic(5) + ".txt")); + final Path targetPath = Paths.get("src/main/resources/"); Files.move(fileToMovePath, targetPath.resolve(fileToMovePath.getFileName())); } diff --git a/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java b/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java index 55a0904499..1a6ac5f8ce 100644 --- a/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java +++ b/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java @@ -19,6 +19,7 @@ import java.io.Reader; import java.io.StringWriter; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.StandardCopyOption; import java.util.Scanner; import org.apache.commons.io.FileUtils; @@ -191,6 +192,16 @@ public class JavaInputStreamToXUnitTest { IOUtils.closeQuietly(outStream); } + @Test + public final void givenUsingPlainJava8_whenConvertingAnInProgressInputStreamToAFile_thenCorrect() throws IOException { + final InputStream initialStream = new FileInputStream(new File("src/main/resources/sample.txt")); + final File targetFile = new File("src/main/resources/targetFile.tmp"); + + java.nio.file.Files.copy(initialStream, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + + IOUtils.closeQuietly(initialStream); + } + @Test public final void givenUsingGuava_whenConvertingAnInputStreamToAFile_thenCorrect() throws IOException { final InputStream initialStream = new FileInputStream(new File("src/main/resources/sample.txt")); diff --git a/core-java/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java b/core-java/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java index 7a4c7366eb..3c574f1e5c 100644 --- a/core-java/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java +++ b/core-java/src/test/java/org/baeldung/java/io/JavaReaderToXUnitTest.java @@ -1,5 +1,8 @@ package org.baeldung.java.io; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileWriter; @@ -187,10 +190,24 @@ public class JavaReaderToXUnitTest { targetStream.close(); } + @Test + public void givenUsingCommonsIO_whenConvertingReaderIntoInputStream_thenCorrect() throws IOException { + String initialString = "With Commons IO"; + final Reader initialReader = new StringReader(initialString); + + final InputStream targetStream = IOUtils.toInputStream(IOUtils.toString(initialReader)); + + final String finalString = IOUtils.toString(targetStream); + assertThat(finalString, equalTo(initialString)); + + initialReader.close(); + targetStream.close(); + } + // tests - Reader to InputStream with encoding @Test - public void givenUsingPlainJava_whenConvertingReaderIntoInputStreamWithCharset_thenCorrect() throws IOException { + public void givenUsingPlainJava_whenConvertingReaderIntoInputStreamWithCharset() throws IOException { final Reader initialReader = new StringReader("With Java"); final char[] charBuffer = new char[8 * 1024]; @@ -225,4 +242,17 @@ public class JavaReaderToXUnitTest { targetStream.close(); } + @Test + public void givenUsingCommonsIO_whenConvertingReaderIntoInputStreamWithEncoding_thenCorrect() throws IOException { + String initialString = "With Commons IO"; + final Reader initialReader = new StringReader(initialString); + final InputStream targetStream = IOUtils.toInputStream(IOUtils.toString(initialReader), Charsets.UTF_8); + + String finalString = IOUtils.toString(targetStream, Charsets.UTF_8); + assertThat(finalString, equalTo(initialString)); + + initialReader.close(); + targetStream.close(); + } + } diff --git a/core-java/src/test/java/org/baeldung/java/io/JavaXToWriterUnitTest.java b/core-java/src/test/java/org/baeldung/java/io/JavaXToWriterUnitTest.java index 35ec15df16..eb393668bd 100644 --- a/core-java/src/test/java/org/baeldung/java/io/JavaXToWriterUnitTest.java +++ b/core-java/src/test/java/org/baeldung/java/io/JavaXToWriterUnitTest.java @@ -1,5 +1,7 @@ package org.baeldung.java.io; +import static org.junit.Assert.assertEquals; + import java.io.IOException; import java.io.StringWriter; import java.io.Writer; @@ -23,6 +25,8 @@ public class JavaXToWriterUnitTest { final Writer targetWriter = new StringWriter().append(new String(initialArray)); targetWriter.close(); + + assertEquals("With Java", targetWriter.toString()); } @Test @@ -40,6 +44,8 @@ public class JavaXToWriterUnitTest { charSink.write(buffer); stringWriter.close(); + + assertEquals("With Guava", stringWriter.toString()); } @Test @@ -48,6 +54,8 @@ public class JavaXToWriterUnitTest { final Writer targetWriter = new StringBuilderWriter(new StringBuilder(new String(initialArray))); targetWriter.close(); + + assertEquals("With Commons IO", targetWriter.toString()); } } diff --git a/core-java/src/test/java/org/baeldung/java/lists/ListAssertJTest.java b/core-java/src/test/java/org/baeldung/java/lists/ListAssertJTest.java new file mode 100644 index 0000000000..b8926946a9 --- /dev/null +++ b/core-java/src/test/java/org/baeldung/java/lists/ListAssertJTest.java @@ -0,0 +1,25 @@ +package org.baeldung.java.lists; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ListAssertJTest { + + private final List list1 = Arrays.asList("1", "2", "3", "4"); + private final List list2 = Arrays.asList("1", "2", "3", "4"); + private final List list3 = Arrays.asList("1", "2", "4", "3"); + + @Test + public void whenTestingForEquality_ShouldBeEqual() throws Exception { + assertThat(list1) + .isEqualTo(list2) + .isNotEqualTo(list3); + + assertThat(list1.equals(list2)).isTrue(); + assertThat(list1.equals(list3)).isFalse(); + } +} diff --git a/core-java/src/test/java/org/baeldung/java/lists/ListJUnitTest.java b/core-java/src/test/java/org/baeldung/java/lists/ListJUnitTest.java new file mode 100644 index 0000000000..7dddf6c2ce --- /dev/null +++ b/core-java/src/test/java/org/baeldung/java/lists/ListJUnitTest.java @@ -0,0 +1,21 @@ +package org.baeldung.java.lists; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +public class ListJUnitTest { + + private final List list1 = Arrays.asList("1", "2", "3", "4"); + private final List list2 = Arrays.asList("1", "2", "3", "4"); + private final List list3 = Arrays.asList("1", "2", "4", "3"); + + @Test + public void whenTestingForEquality_ShouldBeEqual() throws Exception { + Assert.assertEquals(list1, list2); + Assert.assertNotSame(list1, list2); + Assert.assertNotEquals(list1, list3); + } +} diff --git a/core-java/src/test/java/org/baeldung/java/lists/ListTestNGTest.java b/core-java/src/test/java/org/baeldung/java/lists/ListTestNGTest.java new file mode 100644 index 0000000000..fa80d0e224 --- /dev/null +++ b/core-java/src/test/java/org/baeldung/java/lists/ListTestNGTest.java @@ -0,0 +1,21 @@ +package org.baeldung.java.lists; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.List; + +public class ListTestNGTest { + + private final List list1 = Arrays.asList("1", "2", "3", "4"); + private final List list2 = Arrays.asList("1", "2", "3", "4"); + private final List list3 = Arrays.asList("1", "2", "4", "3"); + + @Test + public void whenTestingForEquality_ShouldBeEqual() throws Exception { + Assert.assertEquals(list1, list2); + Assert.assertNotSame(list1, list2); + Assert.assertNotEquals(list1, list3); + } +} diff --git a/core-java/src/test/java/org/baeldung/java/md5/JavaMD5Test.java b/core-java/src/test/java/org/baeldung/java/md5/JavaMD5Test.java new file mode 100644 index 0000000000..83f1fb33b6 --- /dev/null +++ b/core-java/src/test/java/org/baeldung/java/md5/JavaMD5Test.java @@ -0,0 +1,90 @@ +package org.baeldung.java.md5; + +import static org.junit.Assert.*; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.xml.bind.DatatypeConverter; + +import org.apache.commons.codec.digest.DigestUtils; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.hash.HashCode; +import com.google.common.hash.Hashing; + +import java.io.File; +import java.io.IOException; +import java.nio.*; +import static org.assertj.core.api.Assertions.assertThat; + + +public class JavaMD5Test { + + + String filename = "src/test/resources/test_md5.txt"; + String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3"; + + String hash = "35454B055CC325EA1AF2126E27707052"; + String password = "ILoveJava"; + + + + @Test + public void givenPassword_whenHashing_thenVerifying() throws NoSuchAlgorithmException { + String hash = "35454B055CC325EA1AF2126E27707052"; + String password = "ILoveJava"; + + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(password.getBytes()); + byte[] digest = md.digest(); + String myHash = DatatypeConverter.printHexBinary(digest).toUpperCase(); + + assertThat(myHash.equals(hash)).isTrue(); + } + + @Test + public void givenFile_generatingChecksum_thenVerifying() throws NoSuchAlgorithmException, IOException { + String filename = "src/test/resources/test_md5.txt"; + String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3"; + + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(Files.readAllBytes(Paths.get(filename))); + byte[] digest = md.digest(); + String myChecksum = DatatypeConverter + .printHexBinary(digest).toUpperCase(); + + assertThat(myChecksum.equals(checksum)).isTrue(); + } + + @Test + public void givenPassword_whenHashingUsingCommons_thenVerifying() { + String hash = "35454B055CC325EA1AF2126E27707052"; + String password = "ILoveJava"; + + String md5Hex = DigestUtils + .md5Hex(password).toUpperCase(); + + assertThat(md5Hex.equals(hash)).isTrue(); + } + + + @Test + public void givenFile_whenChecksumUsingGuava_thenVerifying() throws IOException { + String filename = "src/test/resources/test_md5.txt"; + String checksum = "5EB63BBBE01EEED093CB22BB8F5ACDC3"; + + HashCode hash = com.google.common.io.Files + .hash(new File(filename), Hashing.md5()); + String myChecksum = hash.toString() + .toUpperCase(); + + assertThat(myChecksum.equals(checksum)).isTrue(); + } + + +} diff --git a/core-java/src/test/java/org/baeldung/java/shell/JavaProcessUnitTest.java b/core-java/src/test/java/org/baeldung/java/shell/JavaProcessUnitTest.java new file mode 100644 index 0000000000..2c330c513d --- /dev/null +++ b/core-java/src/test/java/org/baeldung/java/shell/JavaProcessUnitTest.java @@ -0,0 +1,66 @@ +package org.baeldung.java.shell; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.*; +import java.util.concurrent.Executors; +import java.util.function.Consumer; + +public class JavaProcessUnitTest { + private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().startsWith("windows"); + + private static class StreamGobbler implements Runnable { + private InputStream inputStream; + private Consumer consumer; + + public StreamGobbler(InputStream inputStream, Consumer consumer) { + this.inputStream = inputStream; + this.consumer = consumer; + } + + @Override + public void run() { + new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumer); + } + } + + private Consumer consumer = new Consumer() { + @Override + public void accept(String s) { + Assert.assertNotNull(s); + } + }; + + private String homeDirectory = System.getProperty("user.home"); + + @Test + public void givenProcess_whenCreatingViaRuntime_shouldSucceed() throws Exception { + Process process; + if (IS_WINDOWS) { + process = Runtime.getRuntime().exec(String.format("cmd.exe /c dir %s", homeDirectory)); + } else { + process = Runtime.getRuntime().exec(String.format("sh -c ls %s", homeDirectory)); + } + StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), consumer); + Executors.newSingleThreadExecutor().submit(streamGobbler); + int exitCode = process.waitFor(); + Assert.assertEquals(0, exitCode); + } + + @Test + public void givenProcess_whenCreatingViaProcessBuilder_shouldSucceed() throws Exception { + ProcessBuilder builder = new ProcessBuilder(); + if (IS_WINDOWS) { + builder.command("cmd.exe", "/c", "dir"); + } else { + builder.command("sh", "-c", "ls"); + } + builder.directory(new File(homeDirectory)); + Process process = builder.start(); + StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), consumer); + Executors.newSingleThreadExecutor().submit(streamGobbler); + int exitCode = process.waitFor(); + Assert.assertEquals(0, exitCode); + } +} diff --git a/couchbase-sdk/README.md b/couchbase-sdk/README.md new file mode 100644 index 0000000000..9cdcdea012 --- /dev/null +++ b/couchbase-sdk/README.md @@ -0,0 +1,50 @@ +## Couchbase SDK Tutorial Project + +### Relevant Articles: +- [Introduction to Couchbase SDK for Java](http://www.baeldung.com/java-couchbase-sdk) +- [Using Couchbase in a Spring Application](http://www.baeldung.com/couchbase-sdk-spring) +- [Asynchronous Batch Opereations in Couchbase](http://www.baeldung.com/async-batch-operations-in-couchbase) + +### Overview +This Maven project contains the Java code for the Couchbase entities and Spring services +as described in the tutorials, as well as a unit/integration test +for each service implementation. + +### Working with the Code +The project was developed and tested using Java 7 and 8 in the Eclipse-based +Spring Source Toolkit (STS) and therefore should run fine in any +recent version of Eclipse or another IDE of your choice +that supports Java 7 or later. + +### Building the Project +You can also build the project using Maven outside of any IDE: +``` +mvn clean install +``` + +### Package Organization +Java classes for the intro tutorial are in the +org.baeldung.couchbase.intro package. + +Java classes for the Spring service tutorial are in the +org.baeldung.couchbase.spring package hierarchy. + +Java classes for the Asynchronous Couchbase tutorial are in the +org.baeldung.couchbase.async package hierarchy. + + +### Running the tests +The test classes for the Spring service tutorial are: +- org.baeldung.couchbase.spring.service.ClusterServiceTest +- org.baeldung.couchbase.spring.person.PersonCrudServiceTest + +The test classes for the Asynchronous Couchbase tutorial are in the +org.baeldung.couchbase.async package hierarchy: +- org.baeldung.couchbase.async.service.ClusterServiceTest +- org.baeldung.couchbase.async.person.PersonCrudServiceTest + +The test classes may be run as JUnit tests from your IDE +or using the Maven command line: +``` +mvn test +``` diff --git a/couchbase-sdk/mvnw b/couchbase-sdk/mvnw new file mode 100755 index 0000000000..a1ba1bf554 --- /dev/null +++ b/couchbase-sdk/mvnw @@ -0,0 +1,233 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # + # Look for the Apple JDKs first to preserve the existing behaviour, and then look + # for the new JDKs provided by Oracle. + # + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then + # + # Apple JDKs + # + export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then + # + # Oracle JDKs + # + export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home + fi + + if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then + # + # Apple JDKs + # + export JAVA_HOME=`/usr/libexec/java_home` + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + local basedir=$(pwd) + local wdir=$(pwd) + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + wdir=$(cd "$wdir/.."; pwd) + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} "$@" diff --git a/couchbase-sdk/mvnw.cmd b/couchbase-sdk/mvnw.cmd new file mode 100644 index 0000000000..2b934e89dd --- /dev/null +++ b/couchbase-sdk/mvnw.cmd @@ -0,0 +1,145 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +set MAVEN_CMD_LINE_ARGS=%* + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% \ No newline at end of file diff --git a/couchbase-sdk/pom.xml b/couchbase-sdk/pom.xml new file mode 100644 index 0000000000..4c277f4c85 --- /dev/null +++ b/couchbase-sdk/pom.xml @@ -0,0 +1,102 @@ + + + 4.0.0 + com.baeldung + couchbase-sdk + 0.1-SNAPSHOT + jar + couchbase-sdk + Couchbase SDK Tutorials + + + + + com.couchbase.client + java-client + ${couchbase.client.version} + + + + + org.springframework + spring-context + ${spring-framework.version} + + + org.springframework + spring-context-support + ${spring-framework.version} + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + compile + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + + + org.springframework + spring-test + ${spring-framework.version} + test + + + junit + junit + ${junit.version} + test + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + test + + + + + + + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + + 1.7 + UTF-8 + 2.2.6 + 4.2.4.RELEASE + 1.1.3 + 1.7.12 + 4.11 + 3.4 + + + diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/CouchbaseEntity.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/CouchbaseEntity.java new file mode 100644 index 0000000000..16e1876719 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/CouchbaseEntity.java @@ -0,0 +1,9 @@ +package com.baeldung.couchbase.async; + +public interface CouchbaseEntity { + + String getId(); + + void setId(String id); + +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/Person.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/Person.java new file mode 100644 index 0000000000..32ed2ebbe4 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/Person.java @@ -0,0 +1,89 @@ +package com.baeldung.couchbase.async.person; + +import com.baeldung.couchbase.async.CouchbaseEntity; + +public class Person implements CouchbaseEntity { + + private String id; + private String type; + private String name; + private String homeTown; + + Person() {} + + public Person(Builder b) { + this.id = b.id; + this.type = b.type; + this.name = b.name; + this.homeTown = b.homeTown; + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getHomeTown() { + return homeTown; + } + + public void setHomeTown(String homeTown) { + this.homeTown = homeTown; + } + + public static class Builder { + private String id; + private String type; + private String name; + private String homeTown; + + public static Builder newInstance() { + return new Builder(); + } + + public Person build() { + return new Person(this); + } + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder type(String type) { + this.type = type; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder homeTown(String homeTown) { + this.homeTown = homeTown; + return this; + } + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/PersonCrudService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/PersonCrudService.java new file mode 100644 index 0000000000..b2ef985725 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/PersonCrudService.java @@ -0,0 +1,26 @@ +package com.baeldung.couchbase.async.person; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +import com.baeldung.couchbase.async.service.AbstractCrudService; +import com.baeldung.couchbase.async.service.BucketService; + +@Service +public class PersonCrudService extends AbstractCrudService { + + @Autowired + public PersonCrudService( + @Qualifier("TutorialBucketService") BucketService bucketService, + PersonDocumentConverter converter) { + super(bucketService, converter); + } + + @PostConstruct + private void init() { + loadBucket(); + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/PersonDocumentConverter.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/PersonDocumentConverter.java new file mode 100644 index 0000000000..8646cf247a --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/PersonDocumentConverter.java @@ -0,0 +1,31 @@ +package com.baeldung.couchbase.async.person; + +import org.springframework.stereotype.Service; + +import com.baeldung.couchbase.async.service.JsonDocumentConverter; +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.document.json.JsonObject; + +@Service +public class PersonDocumentConverter implements JsonDocumentConverter { + + @Override + public JsonDocument toDocument(Person p) { + JsonObject content = JsonObject.empty() + .put("type", "Person") + .put("name", p.getName()) + .put("homeTown", p.getHomeTown()); + return JsonDocument.create(p.getId(), content); + } + + @Override + public Person fromDocument(JsonDocument doc) { + JsonObject content = doc.content(); + Person p = new Person(); + p.setId(doc.id()); + p.setType("Person"); + p.setName(content.getString("name")); + p.setHomeTown(content.getString("homeTown")); + return p; + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/RegistrationService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/RegistrationService.java new file mode 100644 index 0000000000..926cd7f4e8 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/person/RegistrationService.java @@ -0,0 +1,29 @@ +package com.baeldung.couchbase.async.person; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.couchbase.client.core.CouchbaseException; + +@Service +public class RegistrationService { + + @Autowired + private PersonCrudService crud; + + public void registerNewPerson(String name, String homeTown) { + Person person = new Person(); + person.setName(name); + person.setHomeTown(homeTown); + crud.create(person); + } + + public Person findRegistrant(String id) { + try{ + return crud.read(id); + } + catch(CouchbaseException e) { + return crud.readFromReplica(id); + } + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/AbstractBucketService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/AbstractBucketService.java new file mode 100644 index 0000000000..cbc03cbcda --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/AbstractBucketService.java @@ -0,0 +1,27 @@ +package com.baeldung.couchbase.async.service; + +import com.couchbase.client.java.Bucket; + +public abstract class AbstractBucketService implements BucketService { + + private ClusterService clusterService; + + private Bucket bucket; + + protected void openBucket() { + bucket = clusterService.openBucket(getBucketName(), getBucketPassword()); + } + + protected abstract String getBucketName(); + + protected abstract String getBucketPassword(); + + public AbstractBucketService(ClusterService clusterService) { + this.clusterService = clusterService; + } + + @Override + public Bucket getBucket() { + return bucket; + } + } diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/AbstractCrudService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/AbstractCrudService.java new file mode 100644 index 0000000000..861e2404e5 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/AbstractCrudService.java @@ -0,0 +1,175 @@ +package com.baeldung.couchbase.async.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.couchbase.async.CouchbaseEntity; +import com.couchbase.client.core.BackpressureException; +import com.couchbase.client.core.time.Delay; +import com.couchbase.client.java.AsyncBucket; +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.ReplicaMode; +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.util.retry.RetryBuilder; + +import rx.Observable; +import rx.functions.Action1; +import rx.functions.Func1; + +public abstract class AbstractCrudService implements CrudService { + + private static final Logger logger = LoggerFactory.getLogger(AbstractCrudService.class); + + private BucketService bucketService; + private Bucket bucket; + private JsonDocumentConverter converter; + + public AbstractCrudService(BucketService bucketService, JsonDocumentConverter converter) { + this.bucketService = bucketService; + this.converter = converter; + } + + protected void loadBucket() { + bucket = bucketService.getBucket(); + } + + @Override + public void create(T t) { + if(t.getId() == null) { + t.setId(UUID.randomUUID().toString()); + } + JsonDocument doc = converter.toDocument(t); + bucket.insert(doc); + } + + @Override + public T read(String id) { + JsonDocument doc = bucket.get(id); + return (doc == null ? null : converter.fromDocument(doc)); + } + + @Override + public T readFromReplica(String id) { + List docs = bucket.getFromReplica(id, ReplicaMode.FIRST); + return (docs.isEmpty() ? null : converter.fromDocument(docs.get(0))); + } + + @Override + public void update(T t) { + JsonDocument doc = converter.toDocument(t); + bucket.upsert(doc); + } + + @Override + public void delete(String id) { + bucket.remove(id); + } + + @Override + public List readBulk(Iterable ids) { + final AsyncBucket asyncBucket = bucket.async(); + Observable asyncOperation = Observable + .from(ids) + .flatMap(new Func1>() { + public Observable call(String key) { + return asyncBucket.get(key); + } + }); + + final List items = new ArrayList(); + try { + asyncOperation.toBlocking() + .forEach(new Action1() { + public void call(JsonDocument doc) { + T item = converter.fromDocument(doc); + items.add(item); + } + }); + } catch (Exception e) { + logger.error("Error during bulk get", e); + } + + return items; + } + + @Override + public void createBulk(Iterable items) { + final AsyncBucket asyncBucket = bucket.async(); + Observable + .from(items) + .flatMap(new Func1>() { + @SuppressWarnings("unchecked") + @Override + public Observable call(final T t) { + if(t.getId() == null) { + t.setId(UUID.randomUUID().toString()); + } + JsonDocument doc = converter.toDocument(t); + return asyncBucket.insert(doc) + .retryWhen(RetryBuilder + .anyOf(BackpressureException.class) + .delay(Delay.exponential(TimeUnit.MILLISECONDS, 100)) + .max(10) + .build()); + } + }) + .last() + .toBlocking() + .single(); + } + + @Override + public void updateBulk(Iterable items) { + final AsyncBucket asyncBucket = bucket.async(); + Observable + .from(items) + .flatMap(new Func1>() { + @SuppressWarnings("unchecked") + @Override + public Observable call(final T t) { + JsonDocument doc = converter.toDocument(t); + return asyncBucket.upsert(doc) + .retryWhen(RetryBuilder + .anyOf(BackpressureException.class) + .delay(Delay.exponential(TimeUnit.MILLISECONDS, 100)) + .max(10) + .build()); + } + }) + .last() + .toBlocking() + .single(); + } + + @Override + public void deleteBulk(Iterable ids) { + final AsyncBucket asyncBucket = bucket.async(); + Observable + .from(ids) + .flatMap(new Func1>() { + @SuppressWarnings("unchecked") + @Override + public Observable call(String key) { + return asyncBucket.remove(key) + .retryWhen(RetryBuilder + .anyOf(BackpressureException.class) + .delay(Delay.exponential(TimeUnit.MILLISECONDS, 100)) + .max(10) + .build()); + } + }) + .last() + .toBlocking() + .single(); + } + + @Override + public boolean exists(String id) { + return bucket.exists(id); + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/BucketService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/BucketService.java new file mode 100644 index 0000000000..28470be99f --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/BucketService.java @@ -0,0 +1,8 @@ +package com.baeldung.couchbase.async.service; + +import com.couchbase.client.java.Bucket; + +public interface BucketService { + + Bucket getBucket(); +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/ClusterService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/ClusterService.java new file mode 100644 index 0000000000..ee67405b12 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/ClusterService.java @@ -0,0 +1,8 @@ +package com.baeldung.couchbase.async.service; + +import com.couchbase.client.java.Bucket; + +public interface ClusterService { + + Bucket openBucket(String name, String password); +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/ClusterServiceImpl.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/ClusterServiceImpl.java new file mode 100644 index 0000000000..7ce75d21f5 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/ClusterServiceImpl.java @@ -0,0 +1,36 @@ +package com.baeldung.couchbase.async.service; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.annotation.PostConstruct; + +import org.springframework.stereotype.Service; + +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.CouchbaseCluster; +import com.couchbase.client.java.env.CouchbaseEnvironment; +import com.couchbase.client.java.env.DefaultCouchbaseEnvironment; + +@Service +public class ClusterServiceImpl implements ClusterService { + + private Cluster cluster; + private Map buckets = new ConcurrentHashMap<>(); + + @PostConstruct + private void init() { + CouchbaseEnvironment env = DefaultCouchbaseEnvironment.create(); + cluster = CouchbaseCluster.create(env, "localhost"); + } + + @Override + synchronized public Bucket openBucket(String name, String password) { + if(!buckets.containsKey(name)) { + Bucket bucket = cluster.openBucket(name, password); + buckets.put(name, bucket); + } + return buckets.get(name); + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/CrudService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/CrudService.java new file mode 100644 index 0000000000..5bd0e52214 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/CrudService.java @@ -0,0 +1,26 @@ +package com.baeldung.couchbase.async.service; + +import java.util.List; + +public interface CrudService { + + void create(T t); + + T read(String id); + + T readFromReplica(String id); + + void update(T t); + + void delete(String id); + + List readBulk(Iterable ids); + + void createBulk(Iterable items); + + void updateBulk(Iterable items); + + void deleteBulk(Iterable ids); + + boolean exists(String id); +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/JsonDocumentConverter.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/JsonDocumentConverter.java new file mode 100644 index 0000000000..85e14a87ce --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/JsonDocumentConverter.java @@ -0,0 +1,10 @@ +package com.baeldung.couchbase.async.service; + +import com.couchbase.client.java.document.JsonDocument; + +public interface JsonDocumentConverter { + + JsonDocument toDocument(T t); + + T fromDocument(JsonDocument doc); +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/TutorialBucketService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/TutorialBucketService.java new file mode 100644 index 0000000000..459585d995 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/async/service/TutorialBucketService.java @@ -0,0 +1,32 @@ +package com.baeldung.couchbase.async.service; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +@Qualifier("TutorialBucketService") +public class TutorialBucketService extends AbstractBucketService { + + @PostConstruct + void init() { + openBucket(); + } + + @Autowired + public TutorialBucketService(ClusterService clusterService) { + super(clusterService); + } + + @Override + protected String getBucketName() { + return "baeldung-tutorial"; + } + + @Override + protected String getBucketPassword() { + return ""; + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/intro/CodeSnippets.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/intro/CodeSnippets.java new file mode 100644 index 0000000000..2cb9e1f4f7 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/intro/CodeSnippets.java @@ -0,0 +1,96 @@ +package com.baeldung.couchbase.intro; + +import java.util.List; +import java.util.UUID; + +import com.couchbase.client.core.CouchbaseException; +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.CouchbaseCluster; +import com.couchbase.client.java.ReplicaMode; +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.document.json.JsonObject; +import com.couchbase.client.java.env.CouchbaseEnvironment; +import com.couchbase.client.java.env.DefaultCouchbaseEnvironment; + +public class CodeSnippets { + + static Cluster loadClusterWithDefaultEnvironment() { + return CouchbaseCluster.create("localhost"); + } + + static Cluster loadClusterWithCustomEnvironment() { + CouchbaseEnvironment env = DefaultCouchbaseEnvironment.builder() + .connectTimeout(10000) + .kvTimeout(3000) + .build(); + return CouchbaseCluster.create(env, "localhost"); + } + + static Bucket loadDefaultBucketWithBlankPassword(Cluster cluster) { + return cluster.openBucket(); + } + + static Bucket loadBaeldungBucket(Cluster cluster) { + return cluster.openBucket("baeldung", ""); + } + + static JsonDocument insertExample(Bucket bucket) { + JsonObject content = JsonObject.empty() + .put("name", "John Doe") + .put("type", "Person") + .put("email", "john.doe@mydomain.com") + .put("homeTown", "Chicago") + ; + String id = UUID.randomUUID().toString(); + JsonDocument document = JsonDocument.create(id, content); + JsonDocument inserted = bucket.insert(document); + return inserted; + } + + static JsonDocument retrieveAndUpsertExample(Bucket bucket, String id) { + JsonDocument document = bucket.get(id); + JsonObject content = document.content(); + content.put("homeTown", "Kansas City"); + JsonDocument upserted = bucket.upsert(document); + return upserted; + } + + static JsonDocument replaceExample(Bucket bucket, String id) { + JsonDocument document = bucket.get(id); + JsonObject content = document.content(); + content.put("homeTown", "Milwaukee"); + JsonDocument replaced = bucket.replace(document); + return replaced; + } + + static JsonDocument removeExample(Bucket bucket, String id) { + JsonDocument removed = bucket.remove(id); + return removed; + } + + static JsonDocument getFirstFromReplicaExample(Bucket bucket, String id) { + try{ + return bucket.get(id); + } + catch(CouchbaseException e) { + List list = bucket.getFromReplica(id, ReplicaMode.FIRST); + if(!list.isEmpty()) { + return list.get(0); + } + } + return null; + } + + static JsonDocument getLatestReplicaVersion(Bucket bucket, String id) { + long maxCasValue = -1; + JsonDocument latest = null; + for(JsonDocument replica : bucket.getFromReplica(id, ReplicaMode.ALL)) { + if(replica.cas() > maxCasValue) { + latest = replica; + maxCasValue = replica.cas(); + } + } + return latest; + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/Person.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/Person.java new file mode 100644 index 0000000000..0348ba1e5f --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/Person.java @@ -0,0 +1,85 @@ +package com.baeldung.couchbase.spring.person; + +public class Person { + + private String id; + private String type; + private String name; + private String homeTown; + + Person() {} + + public Person(Builder b) { + this.id = b.id; + this.type = b.type; + this.name = b.name; + this.homeTown = b.homeTown; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getHomeTown() { + return homeTown; + } + + public void setHomeTown(String homeTown) { + this.homeTown = homeTown; + } + + public static class Builder { + private String id; + private String type; + private String name; + private String homeTown; + + public static Builder newInstance() { + return new Builder(); + } + + public Person build() { + return new Person(this); + } + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder type(String type) { + this.type = type; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder homeTown(String homeTown) { + this.homeTown = homeTown; + return this; + } + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/PersonCrudService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/PersonCrudService.java new file mode 100644 index 0000000000..de035f1d2c --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/PersonCrudService.java @@ -0,0 +1,69 @@ +package com.baeldung.couchbase.spring.person; + +import java.util.List; +import java.util.UUID; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baeldung.couchbase.spring.service.CrudService; +import com.baeldung.couchbase.spring.service.TutorialBucketService; +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.ReplicaMode; +import com.couchbase.client.java.document.JsonDocument; + +@Service +public class PersonCrudService implements CrudService { + + @Autowired + private TutorialBucketService bucketService; + + @Autowired + private PersonDocumentConverter converter; + + private Bucket bucket; + + @PostConstruct + private void init() { + bucket = bucketService.getBucket(); + } + + @Override + public void create(Person person) { + if(person.getId() == null) { + person.setId(UUID.randomUUID().toString()); + } + JsonDocument document = converter.toDocument(person); + bucket.insert(document); + } + + @Override + public Person read(String id) { + JsonDocument doc = bucket.get(id); + return (doc != null ? converter.fromDocument(doc) : null); + } + + @Override + public Person readFromReplica(String id) { + List docs = bucket.getFromReplica(id, ReplicaMode.FIRST); + return (docs.isEmpty() ? null : converter.fromDocument(docs.get(0))); + } + + @Override + public void update(Person person) { + JsonDocument document = converter.toDocument(person); + bucket.upsert(document); + } + + @Override + public void delete(String id) { + bucket.remove(id); + } + + @Override + public boolean exists(String id) { + return bucket.exists(id); + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/PersonDocumentConverter.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/PersonDocumentConverter.java new file mode 100644 index 0000000000..030c9fde27 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/PersonDocumentConverter.java @@ -0,0 +1,31 @@ +package com.baeldung.couchbase.spring.person; + +import org.springframework.stereotype.Service; + +import com.baeldung.couchbase.spring.service.JsonDocumentConverter; +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.document.json.JsonObject; + +@Service +public class PersonDocumentConverter implements JsonDocumentConverter { + + @Override + public JsonDocument toDocument(Person p) { + JsonObject content = JsonObject.empty() + .put("type", "Person") + .put("name", p.getName()) + .put("homeTown", p.getHomeTown()); + return JsonDocument.create(p.getId(), content); + } + + @Override + public Person fromDocument(JsonDocument doc) { + JsonObject content = doc.content(); + Person p = new Person(); + p.setId(doc.id()); + p.setType("Person"); + p.setName(content.getString("name")); + p.setHomeTown(content.getString("homeTown")); + return p; + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/RegistrationService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/RegistrationService.java new file mode 100644 index 0000000000..5ffe7acf24 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/person/RegistrationService.java @@ -0,0 +1,29 @@ +package com.baeldung.couchbase.spring.person; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.couchbase.client.core.CouchbaseException; + +@Service +public class RegistrationService { + + @Autowired + private PersonCrudService crud; + + public void registerNewPerson(String name, String homeTown) { + Person person = new Person(); + person.setName(name); + person.setHomeTown(homeTown); + crud.create(person); + } + + public Person findRegistrant(String id) { + try{ + return crud.read(id); + } + catch(CouchbaseException e) { + return crud.readFromReplica(id); + } + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/BucketService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/BucketService.java new file mode 100644 index 0000000000..97ff1e4fd5 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/BucketService.java @@ -0,0 +1,9 @@ +package com.baeldung.couchbase.spring.service; + +import com.couchbase.client.java.Bucket; + +public interface BucketService { + + Bucket getBucket(); + +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/ClusterService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/ClusterService.java new file mode 100644 index 0000000000..a8543fbd91 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/ClusterService.java @@ -0,0 +1,17 @@ +package com.baeldung.couchbase.spring.service; + +import java.util.List; + +import com.couchbase.client.java.AsyncBucket; +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.document.JsonDocument; + +public interface ClusterService { + + Bucket openBucket(String name, String password); + + List getDocuments(Bucket bucket, Iterable keys); + + List getDocumentsAsync(AsyncBucket bucket, Iterable keys); + +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/ClusterServiceImpl.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/ClusterServiceImpl.java new file mode 100644 index 0000000000..3499fa956e --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/ClusterServiceImpl.java @@ -0,0 +1,84 @@ +package com.baeldung.couchbase.spring.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import com.couchbase.client.java.AsyncBucket; +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.CouchbaseCluster; +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.env.CouchbaseEnvironment; +import com.couchbase.client.java.env.DefaultCouchbaseEnvironment; + +import rx.Observable; +import rx.functions.Action1; +import rx.functions.Func1; + +@Service +public class ClusterServiceImpl implements ClusterService { + private static final Logger logger = LoggerFactory.getLogger(ClusterServiceImpl.class); + + private Cluster cluster; + private Map buckets = new ConcurrentHashMap<>(); + + @PostConstruct + private void init() { + CouchbaseEnvironment env = DefaultCouchbaseEnvironment.create(); + cluster = CouchbaseCluster.create(env, "localhost"); + } + + @Override + synchronized public Bucket openBucket(String name, String password) { + if(!buckets.containsKey(name)) { + Bucket bucket = cluster.openBucket(name, password); + buckets.put(name, bucket); + } + return buckets.get(name); + } + + @Override + public List getDocuments(Bucket bucket, Iterable keys) { + List docs = new ArrayList<>(); + for(String key : keys) { + JsonDocument doc = bucket.get(key); + if(doc != null) { + docs.add(doc); + } + } + return docs; + } + + @Override + public List getDocumentsAsync(final AsyncBucket asyncBucket, Iterable keys) { + Observable asyncBulkGet = Observable + .from(keys) + .flatMap(new Func1>() { + public Observable call(String key) { + return asyncBucket.get(key); + } + }); + + final List docs = new ArrayList<>(); + try { + asyncBulkGet.toBlocking() + .forEach(new Action1() { + public void call(JsonDocument doc) { + docs.add(doc); + } + }); + } catch (Exception e) { + logger.error("Error during bulk get", e); + } + + return docs; + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/CrudService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/CrudService.java new file mode 100644 index 0000000000..f683b9f562 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/CrudService.java @@ -0,0 +1,16 @@ +package com.baeldung.couchbase.spring.service; + +public interface CrudService { + + void create(T t); + + T read(String id); + + T readFromReplica(String id); + + void update(T t); + + void delete(String id); + + boolean exists(String id); +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/JsonDocumentConverter.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/JsonDocumentConverter.java new file mode 100644 index 0000000000..cf4861fbeb --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/JsonDocumentConverter.java @@ -0,0 +1,10 @@ +package com.baeldung.couchbase.spring.service; + +import com.couchbase.client.java.document.JsonDocument; + +public interface JsonDocumentConverter { + + JsonDocument toDocument(T t); + + T fromDocument(JsonDocument doc); +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/TutorialBucketService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/TutorialBucketService.java new file mode 100644 index 0000000000..8a28deb1d6 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/spring/service/TutorialBucketService.java @@ -0,0 +1,29 @@ +package com.baeldung.couchbase.spring.service; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +import com.couchbase.client.java.Bucket; + +@Service +@Qualifier("TutorialBucketService") +public class TutorialBucketService implements BucketService { + + @Autowired + private ClusterService couchbase; + + private Bucket bucket; + + @PostConstruct + private void init() { + bucket = couchbase.openBucket("baeldung-tutorial", ""); + } + + @Override + public Bucket getBucket() { + return bucket; + } +} diff --git a/mockito-mocks-spring-beans/src/main/resources/application.properties b/couchbase-sdk/src/main/resources/application.properties similarity index 100% rename from mockito-mocks-spring-beans/src/main/resources/application.properties rename to couchbase-sdk/src/main/resources/application.properties diff --git a/couchbase-sdk/src/main/resources/logback.xml b/couchbase-sdk/src/main/resources/logback.xml new file mode 100644 index 0000000000..efcc6fb4c7 --- /dev/null +++ b/couchbase-sdk/src/main/resources/logback.xml @@ -0,0 +1,17 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + \ No newline at end of file diff --git a/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/AsyncIntegrationTest.java b/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/AsyncIntegrationTest.java new file mode 100644 index 0000000000..3079fc928a --- /dev/null +++ b/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/AsyncIntegrationTest.java @@ -0,0 +1,13 @@ +package com.baeldung.couchbase.async; + +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { AsyncIntegrationTestConfig.class }) +@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class }) +public abstract class AsyncIntegrationTest { +} diff --git a/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/AsyncIntegrationTestConfig.java b/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/AsyncIntegrationTestConfig.java new file mode 100644 index 0000000000..6afdfe04bd --- /dev/null +++ b/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/AsyncIntegrationTestConfig.java @@ -0,0 +1,9 @@ +package com.baeldung.couchbase.async; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages={"com.baeldung.couchbase.async"}) +public class AsyncIntegrationTestConfig { +} diff --git a/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/person/PersonCrudServiceTest.java b/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/person/PersonCrudServiceTest.java new file mode 100644 index 0000000000..afc5bbd53b --- /dev/null +++ b/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/person/PersonCrudServiceTest.java @@ -0,0 +1,223 @@ +package com.baeldung.couchbase.async.person; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +import com.baeldung.couchbase.async.AsyncIntegrationTest; +import com.baeldung.couchbase.async.person.Person; +import com.baeldung.couchbase.async.person.PersonCrudService; +import com.baeldung.couchbase.async.person.PersonDocumentConverter; +import com.baeldung.couchbase.async.service.BucketService; +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.document.JsonDocument; + +public class PersonCrudServiceTest extends AsyncIntegrationTest { + + @Autowired + private PersonCrudService personService; + + @Autowired + @Qualifier("TutorialBucketService") + private BucketService bucketService; + + @Autowired + private PersonDocumentConverter converter; + + private Bucket bucket; + + @PostConstruct + private void init() { + bucket = bucketService.getBucket(); + } + + @Test + public final void givenRandomPerson_whenCreate_thenPersonPersisted() { + //create person + Person person = randomPerson(); + personService.create(person); + + //check results + assertNotNull(person.getId()); + assertNotNull(bucket.get(person.getId())); + + //cleanup + bucket.remove(person.getId()); + } + + @Test + public final void givenId_whenRead_thenReturnsPerson() { + //create and insert person document + String id = insertRandomPersonDocument().id(); + + //read person and check results + assertNotNull(personService.read(id)); + + //cleanup + bucket.remove(id); + } + + @Test + public final void givenNewHometown_whenUpdate_thenNewHometownPersisted() { + //create and insert person document + JsonDocument doc = insertRandomPersonDocument(); + + //update person + Person expected = converter.fromDocument(doc); + String updatedHomeTown = RandomStringUtils.randomAlphabetic(12); + expected.setHomeTown(updatedHomeTown); + personService.update(expected); + + //check results + JsonDocument actual = bucket.get(expected.getId()); + assertNotNull(actual); + assertNotNull(actual.content()); + assertEquals(expected.getHomeTown(), actual.content().getString("homeTown")); + + //cleanup + bucket.remove(expected.getId()); + } + + @Test + public final void givenRandomPerson_whenDelete_thenPersonNotInBucket() { + //create and insert person document + String id = insertRandomPersonDocument().id(); + + //delete person and check results + personService.delete(id); + assertNull(bucket.get(id)); + } + + @Test + public final void givenIds_whenReadBulk_thenReturnsOnlyPersonsWithMatchingIds() { + List ids = new ArrayList<>(); + + //add some person documents + for(int i=0; i<5; i++) { + ids.add(insertRandomPersonDocument().id()); + } + + //perform bulk read + List persons = personService.readBulk(ids); + + //check results + for(Person person : persons) { + assertTrue(ids.contains(person.getId())); + } + + //cleanup + for(String id : ids) { + bucket.remove(id); + } + } + + @Test + public final void givenPersons_whenInsertBulk_thenPersonsAreInserted() { + + //create some persons + List persons = new ArrayList<>(); + for(int i=0; i<5; i++) { + persons.add(randomPerson()); + } + + //perform bulk insert + personService.createBulk(persons); + + //check results + for(Person person : persons) { + assertNotNull(bucket.get(person.getId())); + } + + //cleanup + for(Person person : persons) { + bucket.remove(person.getId()); + } + } + + @Test + public final void givenPersons_whenUpdateBulk_thenPersonsAreUpdated() { + + List ids = new ArrayList<>(); + + //add some person documents + for(int i=0; i<5; i++) { + ids.add(insertRandomPersonDocument().id()); + } + + //load persons from Couchbase + List persons = new ArrayList<>(); + for(String id : ids) { + persons.add(converter.fromDocument(bucket.get(id))); + } + + //modify persons + for(Person person : persons) { + person.setHomeTown(RandomStringUtils.randomAlphabetic(10)); + } + + //perform bulk update + personService.updateBulk(persons); + + //check results + for(Person person : persons) { + JsonDocument doc = bucket.get(person.getId()); + assertEquals(person.getName(), doc.content().getString("name")); + assertEquals(person.getHomeTown(), doc.content().getString("homeTown")); + } + + //cleanup + for(String id : ids) { + bucket.remove(id); + } + } + + @Test + public void givenIds_whenDeleteBulk_thenPersonsAreDeleted() { + + List ids = new ArrayList<>(); + + //add some person documents + for(int i=0; i<5; i++) { + ids.add(insertRandomPersonDocument().id()); + } + + //perform bulk delete + personService.deleteBulk(ids); + + //check results + for(String id : ids) { + assertNull(bucket.get(id)); + } + + } + + private JsonDocument insertRandomPersonDocument() { + Person expected = randomPersonWithId(); + JsonDocument doc = converter.toDocument(expected); + return bucket.insert(doc); + } + + private Person randomPerson() { + return Person.Builder.newInstance() + .name(RandomStringUtils.randomAlphabetic(10)) + .homeTown(RandomStringUtils.randomAlphabetic(10)) + .build(); + } + + private Person randomPersonWithId() { + return Person.Builder.newInstance() + .id(UUID.randomUUID().toString()) + .name(RandomStringUtils.randomAlphabetic(10)) + .homeTown(RandomStringUtils.randomAlphabetic(10)) + .build(); + } +} diff --git a/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/service/ClusterServiceTest.java b/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/service/ClusterServiceTest.java new file mode 100644 index 0000000000..8ecb51a4b9 --- /dev/null +++ b/couchbase-sdk/src/test/java/com/baeldung/couchbase/async/service/ClusterServiceTest.java @@ -0,0 +1,35 @@ +package com.baeldung.couchbase.async.service; + +import static org.junit.Assert.*; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +import com.baeldung.couchbase.async.AsyncIntegrationTest; +import com.baeldung.couchbase.async.AsyncIntegrationTestConfig; +import com.baeldung.couchbase.async.service.ClusterService; +import com.couchbase.client.java.Bucket; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { AsyncIntegrationTestConfig.class }) +@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class }) +public class ClusterServiceTest extends AsyncIntegrationTest { + + @Autowired + private ClusterService couchbaseService; + + private Bucket defaultBucket; + + @Test + public void whenOpenBucket_thenBucketIsNotNull() throws Exception { + defaultBucket = couchbaseService.openBucket("default", ""); + assertNotNull(defaultBucket); + assertFalse(defaultBucket.isClosed()); + defaultBucket.close(); + } +} diff --git a/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/IntegrationTest.java b/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/IntegrationTest.java new file mode 100644 index 0000000000..9c0b0a50c1 --- /dev/null +++ b/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/IntegrationTest.java @@ -0,0 +1,13 @@ +package com.baeldung.couchbase.spring; + +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { IntegrationTestConfig.class }) +@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class }) +public abstract class IntegrationTest { +} diff --git a/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/IntegrationTestConfig.java b/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/IntegrationTestConfig.java new file mode 100644 index 0000000000..ac71911b9b --- /dev/null +++ b/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/IntegrationTestConfig.java @@ -0,0 +1,9 @@ +package com.baeldung.couchbase.spring; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages={"com.baeldung.couchbase.spring"}) +public class IntegrationTestConfig { +} diff --git a/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/person/PersonCrudServiceTest.java b/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/person/PersonCrudServiceTest.java new file mode 100644 index 0000000000..601b261f6e --- /dev/null +++ b/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/person/PersonCrudServiceTest.java @@ -0,0 +1,82 @@ +package com.baeldung.couchbase.spring.person; + +import static org.junit.Assert.*; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.baeldung.couchbase.spring.IntegrationTest; + +public class PersonCrudServiceTest extends IntegrationTest { + + private static final String CLARK_KENT = "Clark Kent"; + private static final String SMALLVILLE = "Smallville"; + private static final String CLARK_KENT_ID = "Person:ClarkKent"; + + private Person clarkKent; + + @Autowired + private PersonCrudService personService; + + @PostConstruct + private void init() { + clarkKent = personService.read(CLARK_KENT_ID); + if(clarkKent == null) { + clarkKent = buildClarkKent(); + personService.create(clarkKent); + } + } + + @Test + public final void givenRandomPerson_whenCreate_thenPersonPersisted() { + Person person = randomPerson(); + personService.create(person); + String id = person.getId(); + assertNotNull(personService.read(id)); + } + + @Test + public final void givenClarkKentId_whenRead_thenReturnsClarkKent() { + Person person = personService.read(CLARK_KENT_ID); + assertNotNull(person); + } + + @Test + public final void givenNewHometown_whenUpdate_thenNewHometownPersisted() { + Person expected = randomPerson(); + personService.create(expected); + String updatedHomeTown = RandomStringUtils.randomAlphabetic(12); + expected.setHomeTown(updatedHomeTown); + personService.update(expected); + Person actual = personService.read(expected.getId()); + assertNotNull(actual); + assertEquals(expected.getHomeTown(), actual.getHomeTown()); + } + + @Test + public final void givenRandomPerson_whenDelete_thenPersonNotInBucket() { + Person person = randomPerson(); + personService.create(person); + String id = person.getId(); + personService.delete(id); + assertNull(personService.read(id)); + } + + private Person buildClarkKent() { + return Person.Builder.newInstance() + .id(CLARK_KENT_ID) + .name(CLARK_KENT) + .homeTown(SMALLVILLE) + .build(); + } + + private Person randomPerson() { + return Person.Builder.newInstance() + .name(RandomStringUtils.randomAlphabetic(10)) + .homeTown(RandomStringUtils.randomAlphabetic(10)) + .build(); + } +} diff --git a/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/service/ClusterServiceTest.java b/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/service/ClusterServiceTest.java new file mode 100644 index 0000000000..d1968e1c04 --- /dev/null +++ b/couchbase-sdk/src/test/java/com/baeldung/couchbase/spring/service/ClusterServiceTest.java @@ -0,0 +1,34 @@ +package com.baeldung.couchbase.spring.service; + +import static org.junit.Assert.*; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +import com.baeldung.couchbase.spring.IntegrationTest; +import com.baeldung.couchbase.spring.IntegrationTestConfig; +import com.couchbase.client.java.Bucket; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { IntegrationTestConfig.class }) +@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class }) +public class ClusterServiceTest extends IntegrationTest { + + @Autowired + private ClusterService couchbaseService; + + private Bucket defaultBucket; + + @Test + public void whenOpenBucket_thenBucketIsNotNull() throws Exception { + defaultBucket = couchbaseService.openBucket("default", ""); + assertNotNull(defaultBucket); + assertFalse(defaultBucket.isClosed()); + defaultBucket.close(); + } +} diff --git a/deltaspike/.gitignore b/deltaspike/.gitignore new file mode 100644 index 0000000000..aa121e866e --- /dev/null +++ b/deltaspike/.gitignore @@ -0,0 +1,3 @@ +/.idea +baeldung-jee7-seed.iml +/target diff --git a/deltaspike/pom.xml b/deltaspike/pom.xml new file mode 100644 index 0000000000..22cf8f935c --- /dev/null +++ b/deltaspike/pom.xml @@ -0,0 +1,301 @@ + + + 4.0.0 + com.baeldung + deltaspike + 1.0 + war + deltaspike + A starter Java EE 7 webapp which uses DeltaSpike + + http://wildfly.org + + + Apache License, Version 2.0 + repo + http://www.apache.org/licenses/LICENSE-2.0.html + + + + + + + UTF-8 + + + 1.0.2.Final + + + 8.2.1.Final + + + 3.1 + 2.16 + 2.5 + + + 1.7 + 1.7 + + + + + + + + org.wildfly.bom + jboss-javaee-7.0-with-tools + ${version.jboss.bom} + pom + import + + + org.wildfly.bom + jboss-javaee-7.0-with-hibernate + ${version.jboss.bom} + pom + import + + + + + + + + + + + javax.enterprise + cdi-api + provided + + + + + org.jboss.spec.javax.annotation + jboss-annotations-api_1.2_spec + provided + + + + + org.jboss.resteasy + jaxrs-api + provided + + + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + provided + + + + + org.jboss.spec.javax.ejb + jboss-ejb-api_3.2_spec + provided + + + + + + + org.hibernate + hibernate-validator + provided + + + org.slf4j + slf4j-api + + + + + + + org.jboss.spec.javax.faces + jboss-jsf-api_2.2_spec + provided + + + + + + + org.hibernate + hibernate-jpamodelgen + provided + + + + + org.hibernate + hibernate-validator-annotation-processor + provided + + + + + junit + junit + test + + + + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet + test + + + + org.jboss.shrinkwrap.resolver + shrinkwrap-resolver-impl-maven + test + + + + org.apache.deltaspike.modules + deltaspike-data-module-api + 1.7.1 + compile + + + + org.apache.deltaspike.modules + deltaspike-data-module-impl + 1.7.1 + runtime + + + + + com.mysema.querydsl + querydsl-apt + 3.7.4 + provided + + + + com.mysema.querydsl + querydsl-jpa + 3.7.4 + + + + org.slf4j + slf4j-log4j12 + 1.6.1 + + + + + + ${project.artifactId} + + + maven-war-plugin + ${version.war.plugin} + + + false + + + + com.mysema.maven + apt-maven-plugin + 1.0.9 + + + + process + + + target/generated-sources/java + com.mysema.query.apt.jpa.JPAAnnotationProcessor + + + + + + + + org.wildfly.plugins + wildfly-maven-plugin + ${version.wildfly.maven.plugin} + + + + + + + + + default + + true + + + + + maven-surefire-plugin + ${version.surefire.plugin} + + true + + + + + + + + + + + + arq-wildfly-managed + + + org.wildfly + wildfly-arquillian-container-managed + test + + + + + diff --git a/deltaspike/src/main/java/baeldung/controller/MemberController.java b/deltaspike/src/main/java/baeldung/controller/MemberController.java new file mode 100644 index 0000000000..7a9e9800f4 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/controller/MemberController.java @@ -0,0 +1,84 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package baeldung.controller; + +import javax.annotation.PostConstruct; +import javax.enterprise.inject.Model; +import javax.enterprise.inject.Produces; +import javax.faces.application.FacesMessage; +import javax.faces.context.FacesContext; +import javax.inject.Inject; +import javax.inject.Named; + +import baeldung.model.Member; +import baeldung.service.MemberRegistration; + +// The @Model stereotype is a convenience mechanism to make this a request-scoped bean that has an +// EL name +// Read more about the @Model stereotype in this FAQ: +// http://www.cdi-spec.org/faq/#accordion6 +@Model +public class MemberController { + + @Inject + private FacesContext facesContext; + + @Inject + private MemberRegistration memberRegistration; + + @Produces + @Named + private Member newMember; + + @PostConstruct + public void initNewMember() { + newMember = new Member(); + } + + public void register() throws Exception { + try { + memberRegistration.register(newMember); + FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_INFO, "Registered!", "Registration successful"); + facesContext.addMessage(null, m); + initNewMember(); + } catch (Exception e) { + String errorMessage = getRootErrorMessage(e); + FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, "Registration unsuccessful"); + facesContext.addMessage(null, m); + } + } + + private String getRootErrorMessage(Exception e) { + // Default to general error message that registration failed. + String errorMessage = "Registration failed. See server log for more information"; + if (e == null) { + // This shouldn't happen, but return the default messages + return errorMessage; + } + + // Start with the exception and recurse to find the root cause + Throwable t = e; + while (t != null) { + // Get the message from the Throwable class instance + errorMessage = t.getLocalizedMessage(); + t = t.getCause(); + } + // This is the root cause message + return errorMessage; + } + +} diff --git a/deltaspike/src/main/java/baeldung/data/EntityManagerProducer.java b/deltaspike/src/main/java/baeldung/data/EntityManagerProducer.java new file mode 100644 index 0000000000..9189dbba74 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/data/EntityManagerProducer.java @@ -0,0 +1,29 @@ +package baeldung.data; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Default; +import javax.enterprise.inject.Disposes; +import javax.enterprise.inject.Produces; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceUnit; + +@ApplicationScoped +public class EntityManagerProducer { + @PersistenceUnit(unitName = "primary") + private EntityManagerFactory entityManagerFactory; + + @Produces + @Default + @RequestScoped + public EntityManager create() { + return this.entityManagerFactory.createEntityManager(); + } + + public void dispose(@Disposes @Default EntityManager entityManager) { + if (entityManager.isOpen()) { + entityManager.close(); + } + } +} \ No newline at end of file diff --git a/deltaspike/src/main/java/baeldung/data/MemberListProducer.java b/deltaspike/src/main/java/baeldung/data/MemberListProducer.java new file mode 100644 index 0000000000..c1f5fda31d --- /dev/null +++ b/deltaspike/src/main/java/baeldung/data/MemberListProducer.java @@ -0,0 +1,54 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package baeldung.data; + +import javax.annotation.PostConstruct; +import javax.enterprise.context.RequestScoped; +import javax.enterprise.event.Observes; +import javax.enterprise.event.Reception; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import javax.inject.Named; +import java.util.List; + +import baeldung.model.Member; + +@RequestScoped +public class MemberListProducer { + + @Inject + private MemberRepository memberRepository; + + private List members; + + // @Named provides access the return value via the EL variable name "members" in the UI (e.g. + // Facelets or JSP view) + @Produces + @Named + public List getMembers() { + return members; + } + + public void onMemberListChanged(@Observes(notifyObserver = Reception.IF_EXISTS) final Member member) { + retrieveAllMembersOrderedByName(); + } + + @PostConstruct + public void retrieveAllMembersOrderedByName() { + members = memberRepository.findAllOrderedByNameWithQueryDSL(); + } +} diff --git a/deltaspike/src/main/java/baeldung/data/MemberRepository.java b/deltaspike/src/main/java/baeldung/data/MemberRepository.java new file mode 100644 index 0000000000..56a4a4e634 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/data/MemberRepository.java @@ -0,0 +1,43 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package baeldung.data; + +import baeldung.model.Member; +import baeldung.model.QMember; +import org.apache.deltaspike.data.api.*; + +import java.util.List; + +@Repository +@EntityManagerConfig(entityManagerResolver = SecondaryEntityManagerResolver.class) +public abstract class MemberRepository extends AbstractEntityRepository implements QueryDslSupport { + + public abstract Member findById(Long id); + + public abstract Member findByEmail(String email); + + @Query("from Member m order by m.name") + public abstract List findAllOrderedByName(); + + public List findAllOrderedByNameWithQueryDSL() { + final QMember member = QMember.member; + return jpaQuery() + .from(member) + .orderBy(member.email.asc()) + .list(member); + } +} diff --git a/deltaspike/src/main/java/baeldung/data/QueryDslRepositoryExtension.java b/deltaspike/src/main/java/baeldung/data/QueryDslRepositoryExtension.java new file mode 100644 index 0000000000..8cb00958ab --- /dev/null +++ b/deltaspike/src/main/java/baeldung/data/QueryDslRepositoryExtension.java @@ -0,0 +1,18 @@ +package baeldung.data; + +import com.mysema.query.jpa.impl.JPAQuery; +import org.apache.deltaspike.data.spi.DelegateQueryHandler; +import org.apache.deltaspike.data.spi.QueryInvocationContext; + +import javax.inject.Inject; + +public class QueryDslRepositoryExtension implements QueryDslSupport, DelegateQueryHandler { + + @Inject + private QueryInvocationContext context; + + @Override + public JPAQuery jpaQuery() { + return new JPAQuery(context.getEntityManager()); + } +} diff --git a/deltaspike/src/main/java/baeldung/data/QueryDslSupport.java b/deltaspike/src/main/java/baeldung/data/QueryDslSupport.java new file mode 100644 index 0000000000..72c33cf1b6 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/data/QueryDslSupport.java @@ -0,0 +1,7 @@ +package baeldung.data; + +import com.mysema.query.jpa.impl.JPAQuery; + +public interface QueryDslSupport { + JPAQuery jpaQuery(); +} diff --git a/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerProducer.java b/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerProducer.java new file mode 100644 index 0000000000..41d30d9018 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerProducer.java @@ -0,0 +1,30 @@ +package baeldung.data; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Default; +import javax.enterprise.inject.Disposes; +import javax.enterprise.inject.Produces; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceUnit; + +@ApplicationScoped +public class SecondaryEntityManagerProducer { + @PersistenceUnit(unitName = "secondary") + private EntityManagerFactory entityManagerFactory; + + @Produces + @Default + @RequestScoped + @SecondaryPersistenceUnit + public EntityManager create() { + return this.entityManagerFactory.createEntityManager(); + } + + public void dispose(@Disposes @Default EntityManager entityManager) { + if (entityManager.isOpen()) { + entityManager.close(); + } + } +} \ No newline at end of file diff --git a/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerResolver.java b/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerResolver.java new file mode 100644 index 0000000000..7faaa1ac49 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/data/SecondaryEntityManagerResolver.java @@ -0,0 +1,18 @@ +package baeldung.data; + +import org.apache.deltaspike.data.api.EntityManagerResolver; + +import javax.inject.Inject; +import javax.persistence.EntityManager; + +public class SecondaryEntityManagerResolver implements EntityManagerResolver { + + @Inject + @SecondaryPersistenceUnit + private EntityManager entityManager; + + @Override + public EntityManager resolveEntityManager() { + return entityManager; + } +} diff --git a/deltaspike/src/main/java/baeldung/data/SecondaryPersistenceUnit.java b/deltaspike/src/main/java/baeldung/data/SecondaryPersistenceUnit.java new file mode 100644 index 0000000000..e60d0aff05 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/data/SecondaryPersistenceUnit.java @@ -0,0 +1,12 @@ +package baeldung.data; + +import javax.inject.Qualifier; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface SecondaryPersistenceUnit { +} diff --git a/deltaspike/src/main/java/baeldung/model/Member.java b/deltaspike/src/main/java/baeldung/model/Member.java new file mode 100644 index 0000000000..e178dcf63a --- /dev/null +++ b/deltaspike/src/main/java/baeldung/model/Member.java @@ -0,0 +1,93 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package baeldung.model; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; +import javax.validation.constraints.Digits; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlRootElement; + +import org.hibernate.validator.constraints.Email; +import org.hibernate.validator.constraints.NotEmpty; + +@SuppressWarnings("serial") +@Entity +@XmlRootElement +@Table(uniqueConstraints = @UniqueConstraint(columnNames = "email")) +public class Member implements Serializable { + + @Id + @GeneratedValue + private Long id; + + @NotNull + @Size(min = 1, max = 25) + @Pattern(regexp = "[^0-9]*", message = "Must not contain numbers") + private String name; + + @NotNull + @NotEmpty + @Email + private String email; + + @NotNull + @Size(min = 10, max = 12) + @Digits(fraction = 0, integer = 12) + @Column(name = "phone_number") + private String phoneNumber; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } +} diff --git a/deltaspike/src/main/java/baeldung/rest/JaxRsActivator.java b/deltaspike/src/main/java/baeldung/rest/JaxRsActivator.java new file mode 100644 index 0000000000..9357ae0ea6 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/rest/JaxRsActivator.java @@ -0,0 +1,33 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package baeldung.rest; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +/** + * A class extending {@link Application} and annotated with @ApplicationPath is the Java EE 7 "no XML" approach to activating + * JAX-RS. + *

+ *

+ * Resources are served relative to the servlet path specified in the {@link ApplicationPath} annotation. + *

+ */ +@ApplicationPath("/rest") +public class JaxRsActivator extends Application { + /* class body intentionally left blank */ +} diff --git a/deltaspike/src/main/java/baeldung/rest/MemberResourceRESTService.java b/deltaspike/src/main/java/baeldung/rest/MemberResourceRESTService.java new file mode 100644 index 0000000000..5a09e45591 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/rest/MemberResourceRESTService.java @@ -0,0 +1,185 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package baeldung.rest; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.persistence.NoResultException; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.ValidationException; +import javax.validation.Validator; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import baeldung.data.MemberRepository; +import baeldung.model.Member; +import baeldung.service.MemberRegistration; + +/** + * JAX-RS Example + *

+ * This class produces a RESTful service to read/write the contents of the members table. + */ +@Path("/members") +@RequestScoped +public class MemberResourceRESTService { + + @Inject + private Logger log; + + @Inject + private Validator validator; + + @Inject + private MemberRepository repository; + + @Inject + MemberRegistration registration; + + @GET + @Produces(MediaType.APPLICATION_JSON) + public List listAllMembers() { + return repository.findAllOrderedByName(); + } + + @GET + @Path("/{id:[0-9][0-9]*}") + @Produces(MediaType.APPLICATION_JSON) + public Member lookupMemberById(@PathParam("id") long id) { + Member member = repository.findById(id); + if (member == null) { + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + return member; + } + + /** + * Creates a new member from the values provided. Performs validation, and will return a JAX-RS response with either 200 ok, + * or with a map of fields, and related errors. + */ + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createMember(Member member) { + + Response.ResponseBuilder builder = null; + + try { + // Validates member using bean validation + validateMember(member); + + registration.register(member); + + // Create an "ok" response + builder = Response.ok(); + } catch (ConstraintViolationException ce) { + // Handle bean validation issues + builder = createViolationResponse(ce.getConstraintViolations()); + } catch (ValidationException e) { + // Handle the unique constrain violation + Map responseObj = new HashMap<>(); + responseObj.put("email", "Email taken"); + builder = Response.status(Response.Status.CONFLICT).entity(responseObj); + } catch (Exception e) { + // Handle generic exceptions + Map responseObj = new HashMap<>(); + responseObj.put("error", e.getMessage()); + builder = Response.status(Response.Status.BAD_REQUEST).entity(responseObj); + } + + return builder.build(); + } + + /** + *

+ * Validates the given Member variable and throws validation exceptions based on the type of error. If the error is standard + * bean validation errors then it will throw a ConstraintValidationException with the set of the constraints violated. + *

+ *

+ * If the error is caused because an existing member with the same email is registered it throws a regular validation + * exception so that it can be interpreted separately. + *

+ * + * @param member Member to be validated + * @throws ConstraintViolationException If Bean Validation errors exist + * @throws ValidationException If member with the same email already exists + */ + private void validateMember(Member member) throws ConstraintViolationException, ValidationException { + // Create a bean validator and check for issues. + Set> violations = validator.validate(member); + + if (!violations.isEmpty()) { + throw new ConstraintViolationException(new HashSet>(violations)); + } + + // Check the uniqueness of the email address + if (emailAlreadyExists(member.getEmail())) { + throw new ValidationException("Unique Email Violation"); + } + } + + /** + * Creates a JAX-RS "Bad Request" response including a map of all violation fields, and their message. This can then be used + * by clients to show violations. + * + * @param violations A set of violations that needs to be reported + * @return JAX-RS response containing all violations + */ + private Response.ResponseBuilder createViolationResponse(Set> violations) { + log.fine("Validation completed. violations found: " + violations.size()); + + Map responseObj = new HashMap<>(); + + for (ConstraintViolation violation : violations) { + responseObj.put(violation.getPropertyPath().toString(), violation.getMessage()); + } + + return Response.status(Response.Status.BAD_REQUEST).entity(responseObj); + } + + /** + * Checks if a member with the same email address is already registered. This is the only way to easily capture the + * "@UniqueConstraint(columnNames = "email")" constraint from the Member class. + * + * @param email The email to check + * @return True if the email already exists, and false otherwise + */ + public boolean emailAlreadyExists(String email) { + Member member = null; + try { + member = repository.findByEmail(email); + } catch (NoResultException e) { + // ignore + } + return member != null; + } +} diff --git a/deltaspike/src/main/java/baeldung/service/MemberRegistration.java b/deltaspike/src/main/java/baeldung/service/MemberRegistration.java new file mode 100644 index 0000000000..ec65471622 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/service/MemberRegistration.java @@ -0,0 +1,85 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package baeldung.service; + +import baeldung.data.MemberRepository; +import baeldung.data.SecondaryPersistenceUnit; +import baeldung.model.Member; +import baeldung.model.QMember; + +import javax.ejb.Stateless; +import javax.enterprise.event.Event; +import javax.enterprise.inject.Default; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.NoResultException; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.ValidationException; +import javax.validation.Validator; +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Logger; + +@Stateless +public class MemberRegistration { + + @Inject + private Logger log; + + @Inject + private MemberRepository repository; + + @Inject + private Event memberEventSrc; + + @Inject + private Validator validator; + + private void validateMember(Member member) throws ConstraintViolationException, ValidationException { + // Create a bean validator and check for issues. + Set> violations = validator.validate(member); + + if (!violations.isEmpty()) { + throw new ConstraintViolationException(new HashSet>(violations)); + } + + // Check the uniqueness of the email address + if (emailAlreadyExists(member.getEmail())) { + throw new ValidationException("Unique Email Violation"); + } + } + + + public void register(Member member) throws Exception { + log.info("Registering " + member.getName()); + validateMember(member); + repository.save(member); + memberEventSrc.fire(member); + } + + public boolean emailAlreadyExists(String email) { + Member member = null; + try { + member = repository.findByEmail(email); + } catch (NoResultException e) { + // ignore + } + return member != null; + } + +} diff --git a/deltaspike/src/main/java/baeldung/util/Resources.java b/deltaspike/src/main/java/baeldung/util/Resources.java new file mode 100644 index 0000000000..2cc1f235d7 --- /dev/null +++ b/deltaspike/src/main/java/baeldung/util/Resources.java @@ -0,0 +1,53 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package baeldung.util; + +import java.util.logging.Logger; + +import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.faces.context.FacesContext; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +/** + * This class uses CDI to alias Java EE resources, such as the persistence context, to CDI beans + *

+ *

+ * Example injection on a managed bean field: + *

+ *

+ *

+ * @Inject
+ * private EntityManager em;
+ * 
+ */ +public class Resources { + + @Produces + public Logger produceLog(InjectionPoint injectionPoint) { + return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName()); + } + + @Produces + @RequestScoped + public FacesContext produceFacesContext() { + return FacesContext.getCurrentInstance(); + } + +} diff --git a/deltaspike/src/main/resources/META-INF/apache-deltaspike.properties b/deltaspike/src/main/resources/META-INF/apache-deltaspike.properties new file mode 100644 index 0000000000..a861ad729a --- /dev/null +++ b/deltaspike/src/main/resources/META-INF/apache-deltaspike.properties @@ -0,0 +1 @@ +globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy=org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy diff --git a/deltaspike/src/main/resources/META-INF/persistence.xml b/deltaspike/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000000..b68c2c1bb1 --- /dev/null +++ b/deltaspike/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,21 @@ + + + + java:jboss/datasources/baeldung-jee7-seedDS + + + + + + + java:jboss/datasources/baeldung-jee7-seed-secondaryDS + + + + + + diff --git a/deltaspike/src/main/resources/import.sql b/deltaspike/src/main/resources/import.sql new file mode 100644 index 0000000000..154f4e9923 --- /dev/null +++ b/deltaspike/src/main/resources/import.sql @@ -0,0 +1,19 @@ +-- +-- JBoss, Home of Professional Open Source +-- Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual +-- contributors by the @authors tag. See the copyright.txt in the +-- distribution for a full listing of individual contributors. +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- http://www.apache.org/licenses/LICENSE-2.0 +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +-- You can use this file to load seed data into the database using SQL statements +insert into Member (id, name, email, phone_number) values (0, 'John Smith', 'john.smith@mailinator.com', '2125551212') diff --git a/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-ds.xml b/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-ds.xml new file mode 100644 index 0000000000..1a8e350667 --- /dev/null +++ b/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-ds.xml @@ -0,0 +1,37 @@ + + + + + + + jdbc:h2:mem:baeldung-jee7-seed;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1 + h2 + + sa + sa + + + + diff --git a/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-secondary-ds.xml b/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-secondary-ds.xml new file mode 100644 index 0000000000..c4c9afb2e0 --- /dev/null +++ b/deltaspike/src/main/webapp/WEB-INF/baeldung-jee7-seed-secondary-ds.xml @@ -0,0 +1,19 @@ + + + + + + jdbc:h2:mem:baeldung-jee7-seed;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1 + h2 + + sa + sa + + + + diff --git a/deltaspike/src/main/webapp/WEB-INF/beans.xml b/deltaspike/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000000..0090177eb7 --- /dev/null +++ b/deltaspike/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,23 @@ + + + + + diff --git a/deltaspike/src/main/webapp/WEB-INF/faces-config.xml b/deltaspike/src/main/webapp/WEB-INF/faces-config.xml new file mode 100644 index 0000000000..26cf98b669 --- /dev/null +++ b/deltaspike/src/main/webapp/WEB-INF/faces-config.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/deltaspike/src/main/webapp/WEB-INF/templates/default.xhtml b/deltaspike/src/main/webapp/WEB-INF/templates/default.xhtml new file mode 100644 index 0000000000..2f001f8626 --- /dev/null +++ b/deltaspike/src/main/webapp/WEB-INF/templates/default.xhtml @@ -0,0 +1,55 @@ + + + + + baeldung-jee7-seed + + + + +
+
+ +
+
+ + [Template content will be inserted here] + +
+ + +
+
+ diff --git a/deltaspike/src/main/webapp/index.html b/deltaspike/src/main/webapp/index.html new file mode 100644 index 0000000000..dd6c4fb886 --- /dev/null +++ b/deltaspike/src/main/webapp/index.html @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/deltaspike/src/main/webapp/index.xhtml b/deltaspike/src/main/webapp/index.xhtml new file mode 100644 index 0000000000..0f515601be --- /dev/null +++ b/deltaspike/src/main/webapp/index.xhtml @@ -0,0 +1,97 @@ + + + + +

Welcome to WildFly!

+ +
+

You have successfully deployed a Java EE 7 Enterprise + Application.

+

Your application can run on:

+ +
+ + +

Member Registration

+

Enforces annotation-based constraints defined on the + model class.

+ + + + + + + + + + + + + + +

+ + + + +

+
+

Members

+ + No registered members. + + + + Id + #{_member.id} + + + Name + #{_member.name} + + + Email + #{_member.email} + + + Phone # + #{_member.phoneNumber} + + + REST URL + /rest/members/#{_member.id} + + + REST URL for all members: /rest/members + + +
+
diff --git a/deltaspike/src/main/webapp/resources/css/screen.css b/deltaspike/src/main/webapp/resources/css/screen.css new file mode 100644 index 0000000000..0e81d5a9d2 --- /dev/null +++ b/deltaspike/src/main/webapp/resources/css/screen.css @@ -0,0 +1,202 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* Core styles for the page */ +body { + margin: 0; + padding: 0; + background-color: #F1F1F1; + font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; + font-size: 0.8em; + color:#363636; +} + +#container { + margin: 0 auto; + padding: 0 20px 10px 20px; + border-top: 5px solid #000000; + border-left: 5px solid #8c8f91; + border-right: 5px solid #8c8f91; + border-bottom: 25px solid #8c8f91; + width: 865px; /* subtract 40px from banner width for padding */ + background: #FFFFFF; + background-image: url(#{request.contextPath}/resources/gfx/headerbkg.png); + background-repeat: repeat-x; + padding-top: 30px; + box-shadow: 3px 3px 15px #d5d5d5; +} +#content { + float: left; + width: 500px; + margin: 20px; +} +#aside { + font-size: 0.9em; + width: 275px; + float: left; + margin: 20px 0px; + border: 1px solid #D5D5D5; + background: #F1F1F1; + background-image: url(#{request.contextPath}/resources/gfx/asidebkg.png); + background-repeat: repeat-x; + padding: 20px; +} + +#aside ul { + padding-left: 30px; +} +.dualbrand { + float: right; + padding-right: 10px; +} +#footer { + clear: both; + text-align: center; + color: #666666; + font-size: 0.85em; +} +code { + font-size: 1.1em; +} +a { + color: #4a5d75; + text-decoration: none; +} +a:hover { + color: #369; + text-decoration: underline; +} +h1 { + color:#243446; + font-size: 2.25em; +} +h2 { + font-size: 1em; +} +h3 { + color:#243446; +} +h4 { +} +h5 { +} +h6 { +} +/* Member registration styles */ +span.invalid { + padding-left: 3px; + color: red; +} +form { + padding: 1em; + font: 80%/1 sans-serif; + width: 375px; + border: 1px solid #D5D5D5; +} +label { + float: left; + width: 15%; + margin-left: 20px; + margin-right: 0.5em; + padding-top: 0.2em; + text-align: right; + font-weight: bold; + color:#363636; +} +input { + margin-bottom: 8px; +} +.register { + float: left; + margin-left: 85px; +} + +/* ----- table style ------- */ + + +/* = Simple Table style (black header, grey/white stripes */ + +.simpletablestyle { + background-color:#E6E7E8; + clear:both; + width: 550px; +} + +.simpletablestyle img { + border:0px; +} + +.simpletablestyle td { + height:2em; + padding-left: 6px; + font-size:11px; + padding:5px 5px; +} + +.simpletablestyle th { + background: url(#{request.contextPath}/resources/gfx/bkg-blkheader.png) black repeat-x top left; + font-size:12px; + font-weight:normal; + padding:0 10px 0 5px; + border-bottom:#999999 dotted 1px; +} + +.simpletablestyle thead { + background: url(#{request.contextPath}/resources/gfx/bkg-blkheader.png) black repeat-x top left; + height:31px; + font-size:10px; + font-weight:bold; + color:#FFFFFF; + text-align:left; +} + +.simpletablestyle .header a { + color:#94aebd; +} + +.simpletablestype tfoot { + height: 20px; + font-size: 10px; + font-weight: bold; + background-color: #EAECEE; + text-align: center; +} + +.simpletablestyle tr.header td { + padding: 0px 10px 0px 5px; +} + + +.simpletablestyle .subheader { + background-color: #e6e7e8; + font-size:10px; + font-weight:bold; + color:#000000; + text-align:left; +} + +/* Using new CSS3 selectors for styling*/ +.simpletablestyle tr:nth-child(odd) { + background: #f4f3f3; +} +.simpletablestyle tr:nth-child(even) { + background: #ffffff; +} + +.simpletablestyle td a:hover { + color:#3883ce; + text-decoration:none; +} diff --git a/deltaspike/src/main/webapp/resources/gfx/asidebkg.png b/deltaspike/src/main/webapp/resources/gfx/asidebkg.png new file mode 100644 index 0000000000..543d66ad37 Binary files /dev/null and b/deltaspike/src/main/webapp/resources/gfx/asidebkg.png differ diff --git a/deltaspike/src/main/webapp/resources/gfx/bkg-blkheader.png b/deltaspike/src/main/webapp/resources/gfx/bkg-blkheader.png new file mode 100644 index 0000000000..54b95f349f Binary files /dev/null and b/deltaspike/src/main/webapp/resources/gfx/bkg-blkheader.png differ diff --git a/deltaspike/src/main/webapp/resources/gfx/dualbrand_logo.png b/deltaspike/src/main/webapp/resources/gfx/dualbrand_logo.png new file mode 100644 index 0000000000..68853292cb Binary files /dev/null and b/deltaspike/src/main/webapp/resources/gfx/dualbrand_logo.png differ diff --git a/deltaspike/src/main/webapp/resources/gfx/headerbkg.png b/deltaspike/src/main/webapp/resources/gfx/headerbkg.png new file mode 100644 index 0000000000..2669028ba2 Binary files /dev/null and b/deltaspike/src/main/webapp/resources/gfx/headerbkg.png differ diff --git a/deltaspike/src/main/webapp/resources/gfx/wildfly_400x130.jpg b/deltaspike/src/main/webapp/resources/gfx/wildfly_400x130.jpg new file mode 100644 index 0000000000..667c5a66a3 Binary files /dev/null and b/deltaspike/src/main/webapp/resources/gfx/wildfly_400x130.jpg differ diff --git a/deltaspike/src/test/java/baeldung/test/MemberRegistrationTest.java b/deltaspike/src/test/java/baeldung/test/MemberRegistrationTest.java new file mode 100644 index 0000000000..0270d2d164 --- /dev/null +++ b/deltaspike/src/test/java/baeldung/test/MemberRegistrationTest.java @@ -0,0 +1,84 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package baeldung.test; + +import static org.junit.Assert.assertNotNull; + +import java.io.File; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import baeldung.data.*; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import baeldung.model.Member; +import baeldung.service.MemberRegistration; +import baeldung.util.Resources; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.resolver.api.maven.Maven; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(Arquillian.class) +public class MemberRegistrationTest { + @Deployment + public static Archive createTestArchive() { + File[] files = Maven.resolver().loadPomFromFile("pom.xml") + .importRuntimeDependencies().resolve().withTransitivity().asFile(); + + return ShrinkWrap.create(WebArchive.class, "test.war") + .addClasses( + EntityManagerProducer.class, + Member.class, + MemberRegistration.class, + MemberRepository.class, + Resources.class, + QueryDslRepositoryExtension.class, + QueryDslSupport.class, + SecondaryPersistenceUnit.class, + SecondaryEntityManagerProducer.class, + SecondaryEntityManagerResolver.class) + .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml") + .addAsResource("META-INF/apache-deltaspike.properties") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") + .addAsWebInfResource("test-ds.xml") + .addAsWebInfResource("test-secondary-ds.xml") + .addAsLibraries(files); + } + + @Inject + MemberRegistration memberRegistration; + + @Inject + Logger log; + + @Test + public void testRegister() throws Exception { + Member newMember = new Member(); + newMember.setName("Jane Doe"); + newMember.setEmail("jane@mailinator.com"); + newMember.setPhoneNumber("2125551234"); + memberRegistration.register(newMember); + assertNotNull(newMember.getId()); + log.info(newMember.getName() + " was persisted with id " + newMember.getId()); + } + +} diff --git a/deltaspike/src/test/resources/META-INF/apache-deltaspike.properties b/deltaspike/src/test/resources/META-INF/apache-deltaspike.properties new file mode 100644 index 0000000000..a861ad729a --- /dev/null +++ b/deltaspike/src/test/resources/META-INF/apache-deltaspike.properties @@ -0,0 +1 @@ +globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy=org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy diff --git a/deltaspike/src/test/resources/META-INF/test-persistence.xml b/deltaspike/src/test/resources/META-INF/test-persistence.xml new file mode 100644 index 0000000000..bc9fbcbeef --- /dev/null +++ b/deltaspike/src/test/resources/META-INF/test-persistence.xml @@ -0,0 +1,21 @@ + + + + java:jboss/datasources/baeldung-jee7-seedTestDS + + + + + + + java:jboss/datasources/baeldung-jee7-seedTestSecondaryDS + + + + + + diff --git a/deltaspike/src/test/resources/arquillian.xml b/deltaspike/src/test/resources/arquillian.xml new file mode 100644 index 0000000000..14f9e53bbd --- /dev/null +++ b/deltaspike/src/test/resources/arquillian.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + target\wildfly-run\wildfly-10.0.0.Final + + + + diff --git a/deltaspike/src/test/resources/test-ds.xml b/deltaspike/src/test/resources/test-ds.xml new file mode 100644 index 0000000000..8c5d022690 --- /dev/null +++ b/deltaspike/src/test/resources/test-ds.xml @@ -0,0 +1,16 @@ + + + + jdbc:h2:mem:baeldung-jee7-seed-test;DB_CLOSE_DELAY=-1 + h2 + + sa + sa + + + + diff --git a/deltaspike/src/test/resources/test-secondary-ds.xml b/deltaspike/src/test/resources/test-secondary-ds.xml new file mode 100644 index 0000000000..f545adc6d6 --- /dev/null +++ b/deltaspike/src/test/resources/test-secondary-ds.xml @@ -0,0 +1,16 @@ + + + + jdbc:h2:mem:baeldung-jee7-seed-test;DB_CLOSE_DELAY=-1 + h2 + + sa + sa + + + + diff --git a/dependency-injection/.gitignore b/dependency-injection/.gitignore new file mode 100644 index 0000000000..6531dfc93f --- /dev/null +++ b/dependency-injection/.gitignore @@ -0,0 +1,12 @@ +RemoteSystemsTempFiles/ +.classpath +.project +.settings/ +bin/ +.metadata/ +docs/*.autosave +docs/*.autosave +.recommenders/ +build/ +.gradle/ +.DS_Store diff --git a/dependency-injection/pom.xml b/dependency-injection/pom.xml new file mode 100644 index 0000000000..9e78a66ad6 --- /dev/null +++ b/dependency-injection/pom.xml @@ -0,0 +1,99 @@ + + + 4.0.0 + + com.baeldung + dependency-injection + 0.0.1-SNAPSHOT + war + + dependency-injection + Accompanying the demonstration of the use of the annotations related to injection mechanisms, namely + Resource, Inject, and Autowired + + + + + junit + junit + 4.11 + test + + + org.mockito + mockito-all + 1.10.19 + + + org.springframework + spring-test + 4.2.6.RELEASE + + + org.springframework + spring-core + 4.2.6.RELEASE + + + org.springframework + spring-beans + 4.2.6.RELEASE + + + org.springframework + spring-context + 4.2.6.RELEASE + + + javax.inject + javax.inject + 1 + + + + + + + + maven-compiler-plugin + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*Test.java + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + false + + + + + + + + + 2.6 + + + + + java.net + https://maven.java.net/content/repositories/releases/ + + + + diff --git a/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestAutowiredName.java b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestAutowiredName.java new file mode 100644 index 0000000000..48c4495465 --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestAutowiredName.java @@ -0,0 +1,9 @@ +package com.baeldung.configuration; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages = {"com.baeldung.dependency"}) +public class ApplicationContextTestAutowiredName { +} diff --git a/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestAutowiredQualifier.java b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestAutowiredQualifier.java new file mode 100644 index 0000000000..ef6690ab4b --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestAutowiredQualifier.java @@ -0,0 +1,24 @@ +package com.baeldung.configuration; + +import com.baeldung.dependency.AnotherArbitraryDependency; +import com.baeldung.dependency.ArbitraryDependency; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ApplicationContextTestAutowiredQualifier { + + @Bean + public ArbitraryDependency autowiredFieldDependency() { + ArbitraryDependency autowiredFieldDependency = new ArbitraryDependency(); + + return autowiredFieldDependency; + } + + @Bean + public ArbitraryDependency anotherAutowiredFieldDependency() { + ArbitraryDependency anotherAutowiredFieldDependency = new AnotherArbitraryDependency(); + + return anotherAutowiredFieldDependency; + } +} diff --git a/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestAutowiredType.java b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestAutowiredType.java new file mode 100644 index 0000000000..240bc466b7 --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestAutowiredType.java @@ -0,0 +1,15 @@ +package com.baeldung.configuration; + +import com.baeldung.dependency.ArbitraryDependency; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ApplicationContextTestAutowiredType { + + @Bean + public ArbitraryDependency autowiredFieldDependency() { + ArbitraryDependency autowiredFieldDependency = new ArbitraryDependency(); + return autowiredFieldDependency; + } +} diff --git a/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestInjectName.java b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestInjectName.java new file mode 100644 index 0000000000..851aa0b8ee --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestInjectName.java @@ -0,0 +1,16 @@ +package com.baeldung.configuration; + +import com.baeldung.dependency.ArbitraryDependency; +import com.baeldung.dependency.YetAnotherArbitraryDependency; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ApplicationContextTestInjectName { + + @Bean + public ArbitraryDependency yetAnotherFieldInjectDependency() { + ArbitraryDependency yetAnotherFieldInjectDependency = new YetAnotherArbitraryDependency(); + return yetAnotherFieldInjectDependency; + } +} diff --git a/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestInjectQualifier.java b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestInjectQualifier.java new file mode 100644 index 0000000000..59af5a91bb --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestInjectQualifier.java @@ -0,0 +1,22 @@ +package com.baeldung.configuration; + +import com.baeldung.dependency.AnotherArbitraryDependency; +import com.baeldung.dependency.ArbitraryDependency; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ApplicationContextTestInjectQualifier { + + @Bean + public ArbitraryDependency defaultFile() { + ArbitraryDependency defaultFile = new ArbitraryDependency(); + return defaultFile; + } + + @Bean + public ArbitraryDependency namedFile() { + ArbitraryDependency namedFile = new AnotherArbitraryDependency(); + return namedFile; + } +} diff --git a/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestInjectType.java b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestInjectType.java new file mode 100644 index 0000000000..1e1f01f269 --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestInjectType.java @@ -0,0 +1,15 @@ +package com.baeldung.configuration; + +import com.baeldung.dependency.ArbitraryDependency; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ApplicationContextTestInjectType { + + @Bean + public ArbitraryDependency injectDependency() { + ArbitraryDependency injectDependency = new ArbitraryDependency(); + return injectDependency; + } +} diff --git a/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestResourceNameType.java b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestResourceNameType.java new file mode 100644 index 0000000000..cb1b5981e8 --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestResourceNameType.java @@ -0,0 +1,16 @@ +package com.baeldung.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.io.File; + +@Configuration +public class ApplicationContextTestResourceNameType { + + @Bean(name = "namedFile") + public File namedFile() { + File namedFile = new File("namedFile.txt"); + return namedFile; + } +} diff --git a/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestResourceQualifier.java b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestResourceQualifier.java new file mode 100644 index 0000000000..c9aa2f4a7d --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/configuration/ApplicationContextTestResourceQualifier.java @@ -0,0 +1,22 @@ +package com.baeldung.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.io.File; + +@Configuration +public class ApplicationContextTestResourceQualifier { + + @Bean(name = "defaultFile") + public File defaultFile() { + File defaultFile = new File("defaultFile.txt"); + return defaultFile; + } + + @Bean(name = "namedFile") + public File namedFile() { + File namedFile = new File("namedFile.txt"); + return namedFile; + } +} diff --git a/dependency-injection/src/main/java/com/baeldung/dependency/AnotherArbitraryDependency.java b/dependency-injection/src/main/java/com/baeldung/dependency/AnotherArbitraryDependency.java new file mode 100644 index 0000000000..0e19523b7e --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/dependency/AnotherArbitraryDependency.java @@ -0,0 +1,13 @@ +package com.baeldung.dependency; + +import org.springframework.stereotype.Component; + +@Component +public class AnotherArbitraryDependency extends ArbitraryDependency { + + private final String label = "Another Arbitrary Dependency"; + + public String toString() { + return label; + } +} diff --git a/dependency-injection/src/main/java/com/baeldung/dependency/ArbitraryDependency.java b/dependency-injection/src/main/java/com/baeldung/dependency/ArbitraryDependency.java new file mode 100644 index 0000000000..3c90492d2c --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/dependency/ArbitraryDependency.java @@ -0,0 +1,13 @@ +package com.baeldung.dependency; + +import org.springframework.stereotype.Component; + +@Component(value = "autowiredFieldDependency") +public class ArbitraryDependency { + + private final String label = "Arbitrary Dependency"; + + public String toString() { + return label; + } +} diff --git a/dependency-injection/src/main/java/com/baeldung/dependency/YetAnotherArbitraryDependency.java b/dependency-injection/src/main/java/com/baeldung/dependency/YetAnotherArbitraryDependency.java new file mode 100644 index 0000000000..a88abd0924 --- /dev/null +++ b/dependency-injection/src/main/java/com/baeldung/dependency/YetAnotherArbitraryDependency.java @@ -0,0 +1,13 @@ +package com.baeldung.dependency; + +import org.springframework.stereotype.Component; + +@Component +public class YetAnotherArbitraryDependency extends ArbitraryDependency { + + private final String label = "Yet Another Arbitrary Dependency"; + + public String toString() { + return label; + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/autowired/FieldAutowiredNameTest.java b/dependency-injection/src/test/java/com/baeldung/autowired/FieldAutowiredNameTest.java new file mode 100644 index 0000000000..cbdac68543 --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/autowired/FieldAutowiredNameTest.java @@ -0,0 +1,29 @@ +package com.baeldung.autowired; + +import com.baeldung.configuration.ApplicationContextTestAutowiredName; +import com.baeldung.dependency.ArbitraryDependency; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestAutowiredName.class) +public class FieldAutowiredNameTest { + + @Autowired + private ArbitraryDependency autowiredFieldDependency; + + @Test + public void givenAutowiredAnnotation_WhenOnField_ThenDependencyValid() { + assertNotNull(autowiredFieldDependency); + assertEquals("Arbitrary Dependency", autowiredFieldDependency.toString()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/autowired/FieldAutowiredTest.java b/dependency-injection/src/test/java/com/baeldung/autowired/FieldAutowiredTest.java new file mode 100644 index 0000000000..b736871f85 --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/autowired/FieldAutowiredTest.java @@ -0,0 +1,29 @@ +package com.baeldung.autowired; + +import com.baeldung.configuration.ApplicationContextTestAutowiredType; +import com.baeldung.dependency.ArbitraryDependency; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestAutowiredType.class) +public class FieldAutowiredTest { + + @Autowired + private ArbitraryDependency fieldDependency; + + @Test + public void givenAutowired_WhenSetOnField_ThenDependencyResolved() { + assertNotNull(fieldDependency); + assertEquals("Arbitrary Dependency", fieldDependency.toString()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/autowired/FieldQualifierAutowiredTest.java b/dependency-injection/src/test/java/com/baeldung/autowired/FieldQualifierAutowiredTest.java new file mode 100644 index 0000000000..cbc3d56f67 --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/autowired/FieldQualifierAutowiredTest.java @@ -0,0 +1,41 @@ +package com.baeldung.autowired; + +import com.baeldung.configuration.ApplicationContextTestAutowiredQualifier; +import com.baeldung.dependency.ArbitraryDependency; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestAutowiredQualifier.class) +public class FieldQualifierAutowiredTest { + + @Autowired + @Qualifier("autowiredFieldDependency") + private ArbitraryDependency fieldDependency1; + + @Autowired + @Qualifier("anotherAutowiredFieldDependency") + private ArbitraryDependency fieldDependency2; + + @Test + public void givenAutowiredQualifier_WhenOnField_ThenDep1Valid() { + assertNotNull(fieldDependency1); + assertEquals("Arbitrary Dependency", fieldDependency1.toString()); + } + + @Test + public void givenAutowiredQualifier_WhenOnField_ThenDep2Valid() { + assertNotNull(fieldDependency2); + assertEquals("Another Arbitrary Dependency", fieldDependency2.toString()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/inject/FieldByNameInjectTest.java b/dependency-injection/src/test/java/com/baeldung/inject/FieldByNameInjectTest.java new file mode 100644 index 0000000000..665c9f1ddc --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/inject/FieldByNameInjectTest.java @@ -0,0 +1,32 @@ +package com.baeldung.inject; + +import com.baeldung.configuration.ApplicationContextTestInjectName; +import com.baeldung.dependency.ArbitraryDependency; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.inject.Inject; +import javax.inject.Named; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestInjectName.class) +public class FieldByNameInjectTest { + + @Inject + @Named("yetAnotherFieldInjectDependency") + private ArbitraryDependency yetAnotherFieldInjectDependency; + + @Test + public void givenInjectQualifier_WhenSetOnField_ThenDependencyValid() { + assertNotNull(yetAnotherFieldInjectDependency); + assertEquals("Yet Another Arbitrary Dependency", yetAnotherFieldInjectDependency.toString()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/inject/FieldInjectTest.java b/dependency-injection/src/test/java/com/baeldung/inject/FieldInjectTest.java new file mode 100644 index 0000000000..7561c39e76 --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/inject/FieldInjectTest.java @@ -0,0 +1,30 @@ +package com.baeldung.inject; + +import com.baeldung.configuration.ApplicationContextTestInjectType; +import com.baeldung.dependency.ArbitraryDependency; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.inject.Inject; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestInjectType.class) +public class FieldInjectTest { + + @Inject + private ArbitraryDependency fieldInjectDependency; + + @Test + public void givenInjectAnnotation_WhenOnField_ThenValidDependency() { + assertNotNull(fieldInjectDependency); + assertEquals("Arbitrary Dependency", fieldInjectDependency.toString()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/inject/FieldQualifierInjectTest.java b/dependency-injection/src/test/java/com/baeldung/inject/FieldQualifierInjectTest.java new file mode 100644 index 0000000000..7e5f7e7453 --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/inject/FieldQualifierInjectTest.java @@ -0,0 +1,41 @@ +package com.baeldung.inject; + +import com.baeldung.configuration.ApplicationContextTestInjectQualifier; +import com.baeldung.dependency.ArbitraryDependency; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.inject.Inject; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestInjectQualifier.class) +public class FieldQualifierInjectTest { + + @Inject + @Qualifier("defaultFile") + private ArbitraryDependency defaultDependency; + + @Inject + @Qualifier("namedFile") + private ArbitraryDependency namedDependency; + + @Test + public void givenInjectQualifier_WhenOnField_ThenDefaultFileValid() { + assertNotNull(defaultDependency); + assertEquals("Arbitrary Dependency", defaultDependency.toString()); + } + + @Test + public void givenInjectQualifier_WhenOnField_ThenNamedFileValid() { + assertNotNull(defaultDependency); + assertEquals("Another Arbitrary Dependency", namedDependency.toString()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/resource/FieldResourceInjectionTest.java b/dependency-injection/src/test/java/com/baeldung/resource/FieldResourceInjectionTest.java new file mode 100644 index 0000000000..ef7e7b0aeb --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/resource/FieldResourceInjectionTest.java @@ -0,0 +1,30 @@ +package com.baeldung.resource; + +import com.baeldung.configuration.ApplicationContextTestResourceNameType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.annotation.Resource; +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestResourceNameType.class) +public class FieldResourceInjectionTest { + + @Resource(name = "namedFile") + private File defaultFile; + + @Test + public void givenResourceAnnotation_WhenOnField_ThenDependencyValid() { + assertNotNull(defaultFile); + assertEquals("namedFile.txt", defaultFile.getName()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/resource/MethodByQualifierResourceTest.java b/dependency-injection/src/test/java/com/baeldung/resource/MethodByQualifierResourceTest.java new file mode 100644 index 0000000000..95e9fc0bd5 --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/resource/MethodByQualifierResourceTest.java @@ -0,0 +1,45 @@ +package com.baeldung.resource; + +import com.baeldung.configuration.ApplicationContextTestResourceQualifier; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.annotation.Resource; +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestResourceQualifier.class) +public class MethodByQualifierResourceTest { + + private File arbDependency; + private File anotherArbDependency; + + @Test + public void givenResourceQualifier_WhenSetter_ThenValidDependencies() { + assertNotNull(arbDependency); + assertEquals("namedFile.txt", arbDependency.getName()); + assertNotNull(anotherArbDependency); + assertEquals("defaultFile.txt", anotherArbDependency.getName()); + } + + @Resource + @Qualifier("namedFile") + public void setArbDependency(File arbDependency) { + this.arbDependency = arbDependency; + } + + @Resource + @Qualifier("defaultFile") + public void setAnotherArbDependency(File anotherArbDependency) { + this.anotherArbDependency = anotherArbDependency; + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/resource/MethodByTypeResourceTest.java b/dependency-injection/src/test/java/com/baeldung/resource/MethodByTypeResourceTest.java new file mode 100644 index 0000000000..ad9a9a4fb6 --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/resource/MethodByTypeResourceTest.java @@ -0,0 +1,34 @@ +package com.baeldung.resource; + +import com.baeldung.configuration.ApplicationContextTestResourceNameType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.annotation.Resource; +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestResourceNameType.class) +public class MethodByTypeResourceTest { + + private File defaultFile; + + @Resource + protected void setDefaultFile(File defaultFile) { + this.defaultFile = defaultFile; + } + + @Test + public void givenResourceAnnotation_WhenSetter_ThenValidDependency() { + assertNotNull(defaultFile); + assertEquals("namedFile.txt", defaultFile.getName()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/resource/MethodResourceInjectionTest.java b/dependency-injection/src/test/java/com/baeldung/resource/MethodResourceInjectionTest.java new file mode 100644 index 0000000000..1622d8896c --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/resource/MethodResourceInjectionTest.java @@ -0,0 +1,34 @@ +package com.baeldung.resource; + +import com.baeldung.configuration.ApplicationContextTestResourceNameType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.annotation.Resource; +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestResourceNameType.class) +public class MethodResourceInjectionTest { + + private File defaultFile; + + @Resource(name = "namedFile") + protected void setDefaultFile(File defaultFile) { + this.defaultFile = defaultFile; + } + + @Test + public void givenResourceAnnotation_WhenSetter_ThenDependencyValid() { + assertNotNull(defaultFile); + assertEquals("namedFile.txt", defaultFile.getName()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/resource/NamedResourceTest.java b/dependency-injection/src/test/java/com/baeldung/resource/NamedResourceTest.java new file mode 100644 index 0000000000..da104ecaae --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/resource/NamedResourceTest.java @@ -0,0 +1,29 @@ +package com.baeldung.resource; + +import com.baeldung.configuration.ApplicationContextTestResourceNameType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.annotation.Resource; +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestResourceNameType.class) +public class NamedResourceTest { + + @Resource(name = "namedFile") + private File testFile; + + @Test + public void givenResourceAnnotation_WhenOnField_THEN_DEPENDENCY_Found() { + assertNotNull(testFile); + assertEquals("namedFile.txt", testFile.getName()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/resource/QualifierResourceInjectionTest.java b/dependency-injection/src/test/java/com/baeldung/resource/QualifierResourceInjectionTest.java new file mode 100644 index 0000000000..024c8e2bbe --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/resource/QualifierResourceInjectionTest.java @@ -0,0 +1,42 @@ +package com.baeldung.resource; + +import com.baeldung.configuration.ApplicationContextTestResourceQualifier; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.annotation.Resource; +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestResourceQualifier.class) +public class QualifierResourceInjectionTest { + + @Resource + @Qualifier("defaultFile") + private File dependency1; + + @Resource + @Qualifier("namedFile") + private File dependency2; + + @Test + public void givenResourceAnnotation_WhenField_ThenDependency1Valid() { + assertNotNull(dependency1); + assertEquals("defaultFile.txt", dependency1.getName()); + } + + @Test + public void givenResourceQualifier_WhenField_ThenDependency2Valid() { + assertNotNull(dependency2); + assertEquals("namedFile.txt", dependency2.getName()); + } +} diff --git a/dependency-injection/src/test/java/com/baeldung/resource/SetterResourceInjectionTest.java b/dependency-injection/src/test/java/com/baeldung/resource/SetterResourceInjectionTest.java new file mode 100644 index 0000000000..aa7cfda975 --- /dev/null +++ b/dependency-injection/src/test/java/com/baeldung/resource/SetterResourceInjectionTest.java @@ -0,0 +1,33 @@ +package com.baeldung.resource; + +import com.baeldung.configuration.ApplicationContextTestResourceNameType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.annotation.Resource; +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class, + classes = ApplicationContextTestResourceNameType.class) +public class SetterResourceInjectionTest { + + private File defaultFile; + + @Resource + protected void setDefaultFile(File defaultFile) { + this.defaultFile = defaultFile; + } + + @Test + public void givenResourceAnnotation_WhenOnSetter_THEN_MUST_INJECT_Dependency() { + assertNotNull(defaultFile); + assertEquals("namedFile.txt", defaultFile.getName()); + } +} diff --git a/dozer/pom.xml b/dozer/pom.xml new file mode 100644 index 0000000000..35ac2394a6 --- /dev/null +++ b/dozer/pom.xml @@ -0,0 +1,58 @@ + + 4.0.0 + + com.baeldung + dozer + 1.0 + + dozer + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 7 + 7 + + + + + + + + org.slf4j + slf4j-api + 1.7.5 + + + + org.slf4j + jcl-over-slf4j + 1.7.5 + + + + org.apache.commons + commons-lang3 + 3.2.1 + + + + net.sf.dozer + dozer + 5.5.1 + + + junit + junit + 4.3 + test + + + + + diff --git a/dozer/src/main/java/com/baeldung/dozer/Dest.java b/dozer/src/main/java/com/baeldung/dozer/Dest.java new file mode 100644 index 0000000000..ddffcc29a1 --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/Dest.java @@ -0,0 +1,33 @@ +package com.baeldung.dozer; + +public class Dest { + private String name; + private int age; + + public Dest() { + + } + + public Dest(String name, int age) { + super(); + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/dozer/src/main/java/com/baeldung/dozer/Dest2.java b/dozer/src/main/java/com/baeldung/dozer/Dest2.java new file mode 100644 index 0000000000..bd89af6b2e --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/Dest2.java @@ -0,0 +1,38 @@ +package com.baeldung.dozer; + +public class Dest2 { + private int id; + private int points; + + public Dest2() { + + } + + public Dest2(int id, int points) { + super(); + this.id = id; + this.points = points; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getPoints() { + return points; + } + + public void setPoints(int points) { + this.points = points; + } + + @Override + public String toString() { + return "Dest2 [id=" + id + ", points=" + points + "]"; + } + +} diff --git a/dozer/src/main/java/com/baeldung/dozer/MyCustomConvertor.java b/dozer/src/main/java/com/baeldung/dozer/MyCustomConvertor.java new file mode 100644 index 0000000000..3ae095dc51 --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/MyCustomConvertor.java @@ -0,0 +1,44 @@ +package com.baeldung.dozer; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.dozer.CustomConverter; +import org.dozer.MappingException; + +public class MyCustomConvertor implements CustomConverter { + + @Override + public Object convert(Object dest, Object source, Class arg2, Class arg3) { + if (source == null) { + return null; + } + if (source instanceof Personne3) { + Personne3 person = (Personne3) source; + Date date = new Date(person.getDtob()); + DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + String isoDate = format.format(date); + return new Person3(person.getName(), isoDate); + + } else if (source instanceof Person3) { + Person3 person = (Person3) source; + DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + Date date = null; + try { + date = format.parse(person.getDtob()); + + } catch (ParseException e) { + throw new MappingException("Converter MyCustomConvertor " + "used incorrectly:" + e.getMessage()); + } + long timestamp = date.getTime(); + return new Personne3(person.getName(), timestamp); + + } else { + throw new MappingException("Converter MyCustomConvertor " + "used incorrectly. Arguments passed in were:" + dest + " and " + source); + + } + } + +} diff --git a/dozer/src/main/java/com/baeldung/dozer/Person.java b/dozer/src/main/java/com/baeldung/dozer/Person.java new file mode 100644 index 0000000000..030c6e9de7 --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/Person.java @@ -0,0 +1,43 @@ +package com.baeldung.dozer; + +public class Person { + private String name; + private String nickname; + private int age; + + public Person() { + + } + + public Person(String name, String nickname, int age) { + super(); + this.name = name; + this.nickname = nickname; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/dozer/src/main/java/com/baeldung/dozer/Person2.java b/dozer/src/main/java/com/baeldung/dozer/Person2.java new file mode 100644 index 0000000000..741dfd2fd1 --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/Person2.java @@ -0,0 +1,43 @@ +package com.baeldung.dozer; + +public class Person2 { + private String name; + private String nickname; + private int age; + + public Person2() { + + } + + public Person2(String name, String nickname, int age) { + super(); + this.name = name; + this.nickname = nickname; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/dozer/src/main/java/com/baeldung/dozer/Person3.java b/dozer/src/main/java/com/baeldung/dozer/Person3.java new file mode 100644 index 0000000000..a2a37bed53 --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/Person3.java @@ -0,0 +1,38 @@ +package com.baeldung.dozer; + +public class Person3 { + private String name; + private String dtob; + + public Person3() { + + } + + public Person3(String name, String dtob) { + super(); + this.name = name; + this.dtob = dtob; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDtob() { + return dtob; + } + + public void setDtob(String dtob) { + this.dtob = dtob; + } + + @Override + public String toString() { + return "Person3 [name=" + name + ", dtob=" + dtob + "]"; + } + +} diff --git a/dozer/src/main/java/com/baeldung/dozer/Personne.java b/dozer/src/main/java/com/baeldung/dozer/Personne.java new file mode 100644 index 0000000000..ff301db416 --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/Personne.java @@ -0,0 +1,43 @@ +package com.baeldung.dozer; + +public class Personne { + private String nom; + private String surnom; + private int age; + + public Personne() { + + } + + public Personne(String nom, String surnom, int age) { + super(); + this.nom = nom; + this.surnom = surnom; + this.age = age; + } + + public String getNom() { + return nom; + } + + public void setNom(String nom) { + this.nom = nom; + } + + public String getSurnom() { + return surnom; + } + + public void setSurnom(String surnom) { + this.surnom = surnom; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/dozer/src/main/java/com/baeldung/dozer/Personne2.java b/dozer/src/main/java/com/baeldung/dozer/Personne2.java new file mode 100644 index 0000000000..825c45fb81 --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/Personne2.java @@ -0,0 +1,47 @@ +package com.baeldung.dozer; + +import org.dozer.Mapping; + +public class Personne2 { + private String nom; + private String surnom; + private int age; + + public Personne2() { + + } + + public Personne2(String nom, String surnom, int age) { + super(); + this.nom = nom; + this.surnom = surnom; + this.age = age; + } + + @Mapping("name") + public String getNom() { + return nom; + } + + @Mapping("nickname") + public String getSurnom() { + return surnom; + } + + public void setNom(String nom) { + this.nom = nom; + } + + public void setSurnom(String surnom) { + this.surnom = surnom; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/dozer/src/main/java/com/baeldung/dozer/Personne3.java b/dozer/src/main/java/com/baeldung/dozer/Personne3.java new file mode 100644 index 0000000000..c55f8da20d --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/Personne3.java @@ -0,0 +1,38 @@ +package com.baeldung.dozer; + +public class Personne3 { + private String name; + private long dtob; + + public Personne3() { + + } + + public Personne3(String name, long dtob) { + super(); + this.name = name; + this.dtob = dtob; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getDtob() { + return dtob; + } + + public void setDtob(long dtob) { + this.dtob = dtob; + } + + @Override + public String toString() { + return "Personne3 [name=" + name + ", dtob=" + dtob + "]"; + } + +} diff --git a/dozer/src/main/java/com/baeldung/dozer/Source.java b/dozer/src/main/java/com/baeldung/dozer/Source.java new file mode 100644 index 0000000000..d715a5cc16 --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/Source.java @@ -0,0 +1,32 @@ +package com.baeldung.dozer; + +public class Source { + private String name; + private int age; + + public Source() { + } + + public Source(String name, int age) { + super(); + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/dozer/src/main/java/com/baeldung/dozer/Source2.java b/dozer/src/main/java/com/baeldung/dozer/Source2.java new file mode 100644 index 0000000000..e722f206ca --- /dev/null +++ b/dozer/src/main/java/com/baeldung/dozer/Source2.java @@ -0,0 +1,38 @@ +package com.baeldung.dozer; + +public class Source2 { + private String id; + private double points; + + public Source2() { + + } + + public Source2(String id, double points) { + super(); + this.id = id; + this.points = points; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public double getPoints() { + return points; + } + + public void setPoints(double points) { + this.points = points; + } + + @Override + public String toString() { + return "Source2 [id=" + id + ", points=" + points + "]"; + } + +} diff --git a/dozer/src/test/java/com/baeldung/dozer/DozerTest.java b/dozer/src/test/java/com/baeldung/dozer/DozerTest.java new file mode 100644 index 0000000000..107aab078d --- /dev/null +++ b/dozer/src/test/java/com/baeldung/dozer/DozerTest.java @@ -0,0 +1,199 @@ +package com.baeldung.dozer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.dozer.DozerBeanMapper; +import org.dozer.loader.api.BeanMappingBuilder; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +public class DozerTest { + private final long GMT_DIFFERENCE = 46800000; + + DozerBeanMapper mapper; + + @Before + public void before() throws Exception { + mapper = new DozerBeanMapper(); + } + + BeanMappingBuilder builder = new BeanMappingBuilder() { + + @Override + protected void configure() { + mapping(Person.class, Personne.class).fields("name", "nom").fields("nickname", "surnom"); + + } + }; + BeanMappingBuilder builderMinusAge = new BeanMappingBuilder() { + + @Override + protected void configure() { + mapping(Person.class, Personne.class).fields("name", "nom").fields("nickname", "surnom").exclude("age"); + + } + }; + + @Test + public void givenApiMapper_whenMaps_thenCorrect() { + mapper.addMapping(builder); + + Personne frenchAppPerson = new Personne("Sylvester Stallone", "Rambo", 70); + Person englishAppPerson = mapper.map(frenchAppPerson, Person.class); + + assertEquals(englishAppPerson.getName(), frenchAppPerson.getNom()); + assertEquals(englishAppPerson.getNickname(), frenchAppPerson.getSurnom()); + assertEquals(englishAppPerson.getAge(), frenchAppPerson.getAge()); + } + + @Test + public void givenApiMapper_whenMapsOnlySpecifiedFields_thenCorrect() { + mapper.addMapping(builderMinusAge); + + Person englishAppPerson = new Person("Sylvester Stallone", "Rambo", 70); + Personne frenchAppPerson = mapper.map(englishAppPerson, Personne.class); + + assertEquals(frenchAppPerson.getNom(), englishAppPerson.getName()); + assertEquals(frenchAppPerson.getSurnom(), englishAppPerson.getNickname()); + assertEquals(frenchAppPerson.getAge(), 0); + } + + @Test + public void givenApiMapper_whenMapsBidirectionally_thenCorrect() { + mapper.addMapping(builder); + + Person englishAppPerson = new Person("Sylvester Stallone", "Rambo", 70); + Personne frenchAppPerson = mapper.map(englishAppPerson, Personne.class); + + assertEquals(frenchAppPerson.getNom(), englishAppPerson.getName()); + assertEquals(frenchAppPerson.getSurnom(), englishAppPerson.getNickname()); + assertEquals(frenchAppPerson.getAge(), englishAppPerson.getAge()); + } + + @Test + public void givenSourceObjectAndDestClass_whenMapsSameNameFieldsCorrectly_thenCorrect() { + Source source = new Source("Baeldung", 10); + Dest dest = mapper.map(source, Dest.class); + assertEquals(dest.getName(), "Baeldung"); + assertEquals(dest.getAge(), 10); + } + + @Test + public void givenSourceObjectAndDestObject_whenMapsSameNameFieldsCorrectly_thenCorrect() { + Source source = new Source("Baeldung", 10); + Dest dest = new Dest(); + mapper.map(source, dest); + assertEquals(dest.getName(), "Baeldung"); + assertEquals(dest.getAge(), 10); + } + + @Test + public void givenSourceAndDestWithDifferentFieldTypes_whenMapsAndAutoConverts_thenCorrect() { + Source2 source = new Source2("320", 15.2); + Dest2 dest = mapper.map(source, Dest2.class); + assertEquals(dest.getId(), 320); + assertEquals(dest.getPoints(), 15); + } + + @Test + public void givenSrcAndDestWithDifferentFieldNamesWithCustomMapper_whenMaps_thenCorrect() { + configureMapper("dozer_mapping.xml"); + + Personne frenchAppPerson = new Personne("Sylvester Stallone", "Rambo", 70); + Person englishAppPerson = mapper.map(frenchAppPerson, Person.class); + + assertEquals(englishAppPerson.getName(), frenchAppPerson.getNom()); + assertEquals(englishAppPerson.getNickname(), frenchAppPerson.getSurnom()); + assertEquals(englishAppPerson.getAge(), frenchAppPerson.getAge()); + } + + @Test + public void givenSrcAndDestWithDifferentFieldNamesWithCustomMapper_whenMapsBidirectionally_thenCorrect() { + configureMapper("dozer_mapping.xml"); + + Person englishAppPerson = new Person("Dwayne Johnson", "The Rock", 44); + Personne frenchAppPerson = mapper.map(englishAppPerson, Personne.class); + + assertEquals(frenchAppPerson.getNom(), englishAppPerson.getName()); + assertEquals(frenchAppPerson.getSurnom(), englishAppPerson.getNickname()); + assertEquals(frenchAppPerson.getAge(), englishAppPerson.getAge()); + } + + @Ignore("place dozer_mapping.xml at a location of your choice and copy/paste the path after file: in configureMapper method") + @Test + public void givenMappingFileOutsideClasspath_whenMaps_thenCorrect() { + configureMapper("file:e:/dozer_mapping.xml"); + + Person englishAppPerson = new Person("Marshall Bruce Mathers III", "Eminem", 43); + Personne frenchAppPerson = mapper.map(englishAppPerson, Personne.class); + + assertEquals(frenchAppPerson.getNom(), englishAppPerson.getName()); + assertEquals(frenchAppPerson.getSurnom(), englishAppPerson.getNickname()); + assertEquals(frenchAppPerson.getAge(), englishAppPerson.getAge()); + } + + @Test + public void givenSrcAndDest_whenMapsOnlySpecifiedFields_thenCorrect() { + configureMapper("dozer_mapping2.xml"); + + Person englishAppPerson = new Person("Shawn Corey Carter", "Jay Z", 46); + Personne frenchAppPerson = mapper.map(englishAppPerson, Personne.class); + + assertEquals(frenchAppPerson.getNom(), englishAppPerson.getName()); + assertEquals(frenchAppPerson.getSurnom(), englishAppPerson.getNickname()); + assertEquals(frenchAppPerson.getAge(), 0); + } + + @Test + public void givenAnnotatedSrcFields_whenMapsToRightDestField_thenCorrect() { + Person2 englishAppPerson = new Person2("Jean-Claude Van Damme", "JCVD", 55); + Personne2 frenchAppPerson = mapper.map(englishAppPerson, Personne2.class); + assertEquals(frenchAppPerson.getNom(), englishAppPerson.getName()); + assertEquals(frenchAppPerson.getSurnom(), englishAppPerson.getNickname()); + assertEquals(frenchAppPerson.getAge(), englishAppPerson.getAge()); + } + + @Test + public void givenAnnotatedSrcFields_whenMapsToRightDestFieldBidirectionally_thenCorrect() { + Personne2 frenchAppPerson = new Personne2("Jason Statham", "transporter", 49); + Person2 englishAppPerson = mapper.map(frenchAppPerson, Person2.class); + assertEquals(englishAppPerson.getName(), frenchAppPerson.getNom()); + assertEquals(englishAppPerson.getNickname(), frenchAppPerson.getSurnom()); + assertEquals(englishAppPerson.getAge(), frenchAppPerson.getAge()); + } + + @Test + public void givenSrcAndDestWithDifferentFieldTypes_whenAbleToCustomConvert_thenCorrect() { + configureMapper("dozer_custom_convertor.xml"); + + String dateTime = "2007-06-26T21:22:39Z"; + long timestamp = new Long("1182882159000"); + + Person3 person = new Person3("Rich", dateTime); + Personne3 person0 = mapper.map(person, Personne3.class); + + long timestampToTest = person0.getDtob(); + assertTrue(timestampToTest == timestamp || timestampToTest >= timestamp - GMT_DIFFERENCE || timestampToTest <= timestamp + GMT_DIFFERENCE); + } + + @Test + public void givenSrcAndDestWithDifferentFieldTypes_whenAbleToCustomConvertBidirectionally_thenCorrect() { + long timestamp = new Long("1182882159000"); + Personne3 person = new Personne3("Rich", timestamp); + configureMapper("dozer_custom_convertor.xml"); + + Person3 person0 = mapper.map(person, Person3.class); + String timestampTest = person0.getDtob(); + + assertTrue(timestampTest.charAt(10) == 'T' && timestampTest.charAt(19) == 'Z'); + } + + public void configureMapper(String... mappingFileUrls) { + mapper.setMappingFiles(Arrays.asList(mappingFileUrls)); + } + +} diff --git a/dozer/src/test/resources/dozer_custom_convertor.xml b/dozer/src/test/resources/dozer_custom_convertor.xml new file mode 100644 index 0000000000..0cbe5a7918 --- /dev/null +++ b/dozer/src/test/resources/dozer_custom_convertor.xml @@ -0,0 +1,14 @@ + + + + + + com.baeldung.dozer.Personne3 + com.baeldung.dozer.Person3 + + + + + \ No newline at end of file diff --git a/dozer/src/test/resources/dozer_mapping.xml b/dozer/src/test/resources/dozer_mapping.xml new file mode 100644 index 0000000000..13f31db11a --- /dev/null +++ b/dozer/src/test/resources/dozer_mapping.xml @@ -0,0 +1,17 @@ + + + + com.baeldung.dozer.Personne + com.baeldung.dozer.Person + + nom + name + + + surnom + nickname + + + \ No newline at end of file diff --git a/dozer/src/test/resources/dozer_mapping2.xml b/dozer/src/test/resources/dozer_mapping2.xml new file mode 100644 index 0000000000..63411568b6 --- /dev/null +++ b/dozer/src/test/resources/dozer_mapping2.xml @@ -0,0 +1,17 @@ + + + + com.baeldung.dozer.Personne + com.baeldung.dozer.Person + + nom + name + + + surnom + nickname + + + \ No newline at end of file diff --git a/feign-client/README.md b/feign-client/README.md new file mode 100644 index 0000000000..e6ade4d161 --- /dev/null +++ b/feign-client/README.md @@ -0,0 +1,5 @@ +## Feign Hypermedia Client ## + +This is the implementation of a [spring-hypermedia-api][1] client using Feign. + +[1]: https://github.com/eugenp/spring-hypermedia-api diff --git a/feign-client/pom.xml b/feign-client/pom.xml new file mode 100644 index 0000000000..af61883f1b --- /dev/null +++ b/feign-client/pom.xml @@ -0,0 +1,99 @@ + + + 4.0.0 + + com.baeldung.feign + feign-client + 1.0.0-SNAPSHOT + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + UTF-8 + + + + + io.github.openfeign + feign-core + 9.3.1 + + + io.github.openfeign + feign-okhttp + 9.3.1 + + + io.github.openfeign + feign-gson + 9.3.1 + + + io.github.openfeign + feign-slf4j + 9.3.1 + + + org.slf4j + slf4j-api + 1.7.21 + + + org.apache.logging.log4j + log4j-core + 2.6.2 + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.6.2 + + + org.projectlombok + lombok + 1.16.10 + provided + + + junit + junit + 4.12 + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + true + + + + org.springframework.boot + spring-boot-maven-plugin + 1.4.0.RELEASE + + + + + diff --git a/feign-client/src/main/java/com/baeldung/feign/BookControllerFeignClientBuilder.java b/feign-client/src/main/java/com/baeldung/feign/BookControllerFeignClientBuilder.java new file mode 100644 index 0000000000..9c0c359d88 --- /dev/null +++ b/feign-client/src/main/java/com/baeldung/feign/BookControllerFeignClientBuilder.java @@ -0,0 +1,26 @@ +package com.baeldung.feign; + +import com.baeldung.feign.clients.BookClient; +import feign.Feign; +import feign.Logger; +import feign.gson.GsonDecoder; +import feign.gson.GsonEncoder; +import feign.okhttp.OkHttpClient; +import feign.slf4j.Slf4jLogger; +import lombok.Getter; + +@Getter +public class BookControllerFeignClientBuilder { + private BookClient bookClient = createClient(BookClient.class, + "http://localhost:8081/api/books"); + + private static T createClient(Class type, String uri) { + return Feign.builder() + .client(new OkHttpClient()) + .encoder(new GsonEncoder()) + .decoder(new GsonDecoder()) + .logger(new Slf4jLogger(type)) + .logLevel(Logger.Level.FULL) + .target(type, uri); + } +} diff --git a/feign-client/src/main/java/com/baeldung/feign/clients/BookClient.java b/feign-client/src/main/java/com/baeldung/feign/clients/BookClient.java new file mode 100644 index 0000000000..df20ef8f93 --- /dev/null +++ b/feign-client/src/main/java/com/baeldung/feign/clients/BookClient.java @@ -0,0 +1,21 @@ +package com.baeldung.feign.clients; + +import com.baeldung.feign.models.Book; +import com.baeldung.feign.models.BookResource; +import feign.Headers; +import feign.Param; +import feign.RequestLine; + +import java.util.List; + +public interface BookClient { + @RequestLine("GET /{isbn}") + BookResource findByIsbn(@Param("isbn") String isbn); + + @RequestLine("GET") + List findAll(); + + @RequestLine("POST") + @Headers("Content-Type: application/json") + void create(Book book); +} diff --git a/feign-client/src/main/java/com/baeldung/feign/models/Book.java b/feign-client/src/main/java/com/baeldung/feign/models/Book.java new file mode 100644 index 0000000000..cda4412e27 --- /dev/null +++ b/feign-client/src/main/java/com/baeldung/feign/models/Book.java @@ -0,0 +1,18 @@ +package com.baeldung.feign.models; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class Book { + private String isbn; + private String author; + private String title; + private String synopsis; + private String language; +} diff --git a/feign-client/src/main/java/com/baeldung/feign/models/BookResource.java b/feign-client/src/main/java/com/baeldung/feign/models/BookResource.java new file mode 100644 index 0000000000..7902db9fe8 --- /dev/null +++ b/feign-client/src/main/java/com/baeldung/feign/models/BookResource.java @@ -0,0 +1,14 @@ +package com.baeldung.feign.models; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@Data +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class BookResource { + private Book book; +} diff --git a/feign-client/src/main/resources/log4j2.xml b/feign-client/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..659c5fda0e --- /dev/null +++ b/feign-client/src/main/resources/log4j2.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/feign-client/src/test/java/com/baeldung/feign/clients/BookClientTest.java b/feign-client/src/test/java/com/baeldung/feign/clients/BookClientTest.java new file mode 100644 index 0000000000..e7e058a336 --- /dev/null +++ b/feign-client/src/test/java/com/baeldung/feign/clients/BookClientTest.java @@ -0,0 +1,58 @@ +package com.baeldung.feign.clients; + +import com.baeldung.feign.BookControllerFeignClientBuilder; +import com.baeldung.feign.models.Book; +import com.baeldung.feign.models.BookResource; +import lombok.extern.slf4j.Slf4j; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +@Slf4j +@RunWith(JUnit4.class) +public class BookClientTest { + private BookClient bookClient; + + @Before + public void setup() { + BookControllerFeignClientBuilder feignClientBuilder = new BookControllerFeignClientBuilder(); + bookClient = feignClientBuilder.getBookClient(); + } + + @Test + public void givenBookClient_shouldRunSuccessfully() throws Exception { + List books = bookClient.findAll().stream() + .map(BookResource::getBook) + .collect(Collectors.toList()); + assertTrue(books.size() > 2); + log.info("{}", books); + } + + @Test + public void givenBookClient_shouldFindOneBook() throws Exception { + Book book = bookClient.findByIsbn("0151072558").getBook(); + assertThat(book.getAuthor(), containsString("Orwell")); + log.info("{}", book); + } + + @Test + public void givenBookClient_shouldPostBook() throws Exception { + String isbn = UUID.randomUUID().toString(); + Book book = new Book(isbn, "Me", "It's me!", null, null); + bookClient.create(book); + + book = bookClient.findByIsbn(isbn).getBook(); + assertThat(book.getAuthor(), is("Me")); + log.info("{}", book); + } +} diff --git a/flyway-migration/.gitignore b/flyway-migration/.gitignore new file mode 100644 index 0000000000..abffe04ed2 --- /dev/null +++ b/flyway-migration/.gitignore @@ -0,0 +1,4 @@ +.classpath +.project +.settings +target/ \ No newline at end of file diff --git a/flyway-migration/README.MD b/flyway-migration/README.MD new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/flyway-migration/README.MD @@ -0,0 +1 @@ + diff --git a/flyway-migration/db/migration/V1_0__create_employee_schema.sql b/flyway-migration/db/migration/V1_0__create_employee_schema.sql new file mode 100644 index 0000000000..09408faecb --- /dev/null +++ b/flyway-migration/db/migration/V1_0__create_employee_schema.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `employee` ( + +`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, +`name` varchar(20), +`email` varchar(50), +`date_of_birth` timestamp + +)ENGINE=InnoDB DEFAULT CHARSET=UTF8; \ No newline at end of file diff --git a/flyway-migration/db/migration/V2_0__create_department_schema.sql b/flyway-migration/db/migration/V2_0__create_department_schema.sql new file mode 100644 index 0000000000..2b9d3364a5 --- /dev/null +++ b/flyway-migration/db/migration/V2_0__create_department_schema.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `department` ( + +`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, +`name` varchar(20) + +)ENGINE=InnoDB DEFAULT CHARSET=UTF8; + +ALTER TABLE `employee` ADD `dept_id` int AFTER `email`; \ No newline at end of file diff --git a/flyway-migration/myFlywayConfig.properties b/flyway-migration/myFlywayConfig.properties new file mode 100644 index 0000000000..22f3afefd3 --- /dev/null +++ b/flyway-migration/myFlywayConfig.properties @@ -0,0 +1,5 @@ +flyway.user=root +flyway.password=mysql +flyway.schemas=app-db +flyway.url=jdbc:mysql://localhost:3306/ +flyway.locations=filesystem:db/migration \ No newline at end of file diff --git a/flyway-migration/pom.xml b/flyway-migration/pom.xml new file mode 100644 index 0000000000..6e9d683a0e --- /dev/null +++ b/flyway-migration/pom.xml @@ -0,0 +1,34 @@ + + 4.0.0 + com.baeldung + flyway-migration + 1.0 + flyway-migration + A sample project to demonstrate Flyway migrations + + + mysql + mysql-connector-java + 6.0.3 + + + + + + org.flywaydb + flyway-maven-plugin + 4.0.3 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/gson-jackson-performance/README.md b/gson-jackson-performance/README.md new file mode 100644 index 0000000000..5b08f6cdec --- /dev/null +++ b/gson-jackson-performance/README.md @@ -0,0 +1,3 @@ +## Performance of Gson and Jackson + +Standalone java programs to measure the performance of both JSON APIs based on file size and object graph complexity. diff --git a/gson-jackson-performance/pom.xml b/gson-jackson-performance/pom.xml new file mode 100644 index 0000000000..1ea43bd7fa --- /dev/null +++ b/gson-jackson-performance/pom.xml @@ -0,0 +1,72 @@ + + 4.0.0 + + com.baeldung + gson-jackson-performance + 0.0.1-SNAPSHOT + jar + + gson-jackson-performance + http://maven.apache.org + + + UTF-8 + + + + gson-jackson-performance + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + + + + com.google.code.gson + gson + 2.5 + + + + com.fasterxml.jackson.core + jackson-databind + 2.7.1-1 + + + + junit + junit + 3.8.1 + test + + + + log4j + log4j + 1.2.17 + + + + + + + diff --git a/gson-jackson-performance/src/main/java/com/baeldung/data/complex/ComplexDataGeneration.java b/gson-jackson-performance/src/main/java/com/baeldung/data/complex/ComplexDataGeneration.java new file mode 100644 index 0000000000..b69d306edf --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/data/complex/ComplexDataGeneration.java @@ -0,0 +1,63 @@ +package com.baeldung.data.complex; + +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.data.utility.Utility; +import com.baeldung.pojo.complex.AddressDetails; +import com.baeldung.pojo.complex.ContactDetails; +import com.baeldung.pojo.complex.CustomerAddressDetails; +import com.baeldung.pojo.complex.CustomerPortfolioComplex; + +/** + * + * This class is responsible for generating data for complex type object + */ + +public class ComplexDataGeneration { + + public static CustomerPortfolioComplex generateData() { + List customerAddressDetailsList = new ArrayList(); + for (int i = 0; i < 600000; i++) { + CustomerAddressDetails customerAddressDetails = new CustomerAddressDetails(); + customerAddressDetails.setAge(20); + customerAddressDetails.setFirstName(Utility.generateRandomName()); + customerAddressDetails.setLastName(Utility.generateRandomName()); + + List addressDetailsList = new ArrayList(); + customerAddressDetails.setAddressDetails(addressDetailsList); + + for (int j = 0; j < 2; j++) { + AddressDetails addressDetails = new AddressDetails(); + addressDetails.setZipcode(Utility.generateRandomZip()); + addressDetails.setAddress(Utility.generateRandomAddress()); + + List contactDetailsList = new ArrayList(); + addressDetails.setContactDetails(contactDetailsList); + + for (int k = 0; k < 2; k++) { + ContactDetails contactDetails = new ContactDetails(); + contactDetails.setLandline(Utility.generateRandomPhone()); + contactDetails.setMobile(Utility.generateRandomPhone()); + contactDetailsList.add(contactDetails); + contactDetails = null; + } + + addressDetailsList.add(addressDetails); + addressDetails = null; + contactDetailsList = null; + } + customerAddressDetailsList.add(customerAddressDetails); + customerAddressDetails = null; + + if (i % 6000 == 0) { + Runtime.getRuntime().gc(); + } + } + + CustomerPortfolioComplex customerPortfolioComplex = new CustomerPortfolioComplex(); + customerPortfolioComplex.setCustomerAddressDetailsList(customerAddressDetailsList); + customerAddressDetailsList = null; + return customerPortfolioComplex; + } +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/data/complex/ComplexDataGson.java b/gson-jackson-performance/src/main/java/com/baeldung/data/complex/ComplexDataGson.java new file mode 100644 index 0000000000..b97893e8f1 --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/data/complex/ComplexDataGson.java @@ -0,0 +1,91 @@ +package com.baeldung.data.complex; + +import java.util.Map; + +import org.apache.log4j.Logger; +import com.baeldung.data.utility.Utility; +import com.baeldung.pojo.complex.CustomerPortfolioComplex; + +import com.google.gson.Gson; + +/** + * + * This class is responsible for performing functions for Complex type + * GSON like + * Java to Json + * Json to Map + * Json to Java Object + */ + +public class ComplexDataGson { + + private static final Logger logger = Logger.getLogger(ComplexDataGson.class); + + static Gson gson = new Gson(); + + static long generateJsonAvgTime = 0L; + + static long parseJsonToMapAvgTime = 0L; + + static long parseJsonToActualObjectAvgTime = 0L; + + public static void main(String[] args) { + CustomerPortfolioComplex customerPortfolioComplex = ComplexDataGeneration.generateData(); + int j = 50; + for (int i = 0; i < j; i++) { + logger.info("-------Round " + (i + 1)); + String jsonStr = generateJson(customerPortfolioComplex); + logger.info("Size of Complex content Jackson :: " + Utility.bytesIntoMB(jsonStr.getBytes().length)); + logger.info("--------------------------------------------------------------------------"); + parseJsonToMap(jsonStr); + parseJsonToActualObject(jsonStr); + jsonStr = null; + } + + generateJsonAvgTime = generateJsonAvgTime / j; + parseJsonToMapAvgTime = parseJsonToMapAvgTime / j; + parseJsonToActualObjectAvgTime = parseJsonToActualObjectAvgTime / j; + + logger.info("--------------------------------------------------------------------------"); + logger.info("Average Time to Generate JSON : " + generateJsonAvgTime); + logger.info("Average Time to Parse JSON To Map : " + parseJsonToMapAvgTime); + logger.info("Average Time to Parse JSON To Actual Object : " + parseJsonToActualObjectAvgTime); + logger.info("--------------------------------------------------------------------------"); + } + + private static String generateJson(CustomerPortfolioComplex customerPortfolioComplex) { + Runtime.getRuntime().gc(); + long startParsTime = System.nanoTime(); + String json = gson.toJson(customerPortfolioComplex); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + generateJsonAvgTime = generateJsonAvgTime + elapsedTime; + logger.info("Json Generation Time(ms):: " + elapsedTime); + return json; + } + + private static void parseJsonToMap(String jsonStr) { + long startParsTime = System.nanoTime(); + Map parsedMap = gson.fromJson(jsonStr , Map.class); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + parseJsonToMapAvgTime = parseJsonToMapAvgTime + elapsedTime; + logger.info("Generating Map from json Time(ms):: " + elapsedTime); + logger.info("--------------------------------------------------------------------------"); + parsedMap = null; + Runtime.getRuntime().gc(); + } + + private static void parseJsonToActualObject(String jsonStr) { + long startParsTime = System.nanoTime(); + CustomerPortfolioComplex customerPortfolioComplex = gson.fromJson(jsonStr , CustomerPortfolioComplex.class); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + parseJsonToActualObjectAvgTime = parseJsonToActualObjectAvgTime + elapsedTime; + logger.info("Generating Actual Object from json Time(ms):: " + elapsedTime); + logger.info("--------------------------------------------------------------------------"); + customerPortfolioComplex = null; + Runtime.getRuntime().gc(); + + } +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/data/complex/ComplexDataJackson.java b/gson-jackson-performance/src/main/java/com/baeldung/data/complex/ComplexDataJackson.java new file mode 100644 index 0000000000..07a210fb37 --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/data/complex/ComplexDataJackson.java @@ -0,0 +1,95 @@ +package com.baeldung.data.complex; + +import java.io.IOException; +import java.util.Map; + +import com.baeldung.data.utility.Utility; +import org.apache.log4j.Logger; +import com.baeldung.pojo.complex.CustomerPortfolioComplex; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * + * This class is responsible for performing functions for Complex type + * Jackson like + * Java to Json + * Json to Map + * Json to Java Object + */ + +public class ComplexDataJackson { + + private static final Logger logger = Logger.getLogger(ComplexDataJackson.class); + + static ObjectMapper mapper = new ObjectMapper(); + + static long generateJsonAvgTime = 0L; + + static long parseJsonToMapAvgTime = 0L; + + static long parseJsonToActualObjectAvgTime = 0L; + + public static void main(String[] args) throws IOException { + CustomerPortfolioComplex customerPortfolioComplex = ComplexDataGeneration.generateData(); + int j = 50; + for (int i = 0; i < j; i++) { + logger.info("-------Round " + (i + 1)); + String jsonStr = generateJson(customerPortfolioComplex); + logger.info("Size of Complex content Jackson :: " + Utility.bytesIntoMB(jsonStr.getBytes().length)); + logger.info("--------------------------------------------------------------------------"); + parseJsonToMap(jsonStr); + parseJsonToActualObject(jsonStr); + jsonStr = null; + } + + generateJsonAvgTime = generateJsonAvgTime / j; + parseJsonToMapAvgTime = parseJsonToMapAvgTime / j; + parseJsonToActualObjectAvgTime = parseJsonToActualObjectAvgTime / j; + + logger.info("--------------------------------------------------------------------------"); + logger.info("Average Time to Generate JSON : " + generateJsonAvgTime); + logger.info("Average Time to Parse JSON To Map : " + parseJsonToMapAvgTime); + logger.info("Average Time to Parse JSON To Actual Object : " + parseJsonToActualObjectAvgTime); + logger.info("--------------------------------------------------------------------------"); + } + + private static String generateJson(CustomerPortfolioComplex customerPortfolioComplex) + throws JsonProcessingException { + Runtime.getRuntime().gc(); + long startParsTime = System.nanoTime(); + String json = mapper.writeValueAsString(customerPortfolioComplex); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + generateJsonAvgTime = generateJsonAvgTime + elapsedTime; + logger.info("Json Generation Time(ms):: " + elapsedTime); + return json; + } + + private static void parseJsonToMap(String jsonStr) throws JsonParseException , JsonMappingException , IOException { + long startParsTime = System.nanoTime(); + Map parsedMap = mapper.readValue(jsonStr , Map.class); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + parseJsonToMapAvgTime = parseJsonToMapAvgTime + elapsedTime; + logger.info("Generating Map from json Time(ms):: " + elapsedTime); + parsedMap = null; + Runtime.getRuntime().gc(); + + } + + private static void parseJsonToActualObject(String jsonStr) throws JsonParseException , JsonMappingException , + IOException { + long startParsTime = System.nanoTime(); + CustomerPortfolioComplex customerPortfolioComplex = mapper.readValue(jsonStr , CustomerPortfolioComplex.class); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + parseJsonToActualObjectAvgTime = parseJsonToActualObjectAvgTime + elapsedTime; + logger.info("Generating Actual Object from json Time(ms):: " + elapsedTime); + customerPortfolioComplex = null; + Runtime.getRuntime().gc(); + } +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/data/simple/SimpleDataGeneration.java b/gson-jackson-performance/src/main/java/com/baeldung/data/simple/SimpleDataGeneration.java new file mode 100644 index 0000000000..1e186adc72 --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/data/simple/SimpleDataGeneration.java @@ -0,0 +1,35 @@ +package com.baeldung.data.simple; + +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.data.utility.Utility; +import com.baeldung.pojo.simple.Customer; +import com.baeldung.pojo.simple.CustomerPortfolioSimple; + +/** + * + * This class is responsible for generating data for simple type object + */ + +public class SimpleDataGeneration { + + public static CustomerPortfolioSimple generateData() { + List customerList = new ArrayList(); + for (int i = 0; i < 1; i++) { + Customer customer = new Customer(); + customer.setAge(20); + customer.setFirstName(Utility.generateRandomName()); + customer.setLastName(Utility.generateRandomName()); + + customerList.add(customer); + customer = null; + + } + + CustomerPortfolioSimple customerPortfolioSimple = new CustomerPortfolioSimple(); + customerPortfolioSimple.setCustomerLists(customerList); + customerList = null; + return customerPortfolioSimple; + } +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/data/simple/SimpleDataGson.java b/gson-jackson-performance/src/main/java/com/baeldung/data/simple/SimpleDataGson.java new file mode 100644 index 0000000000..b190313462 --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/data/simple/SimpleDataGson.java @@ -0,0 +1,91 @@ +package com.baeldung.data.simple; + +import java.util.Map; + +import org.apache.log4j.Logger; +import com.baeldung.data.utility.Utility; +import com.baeldung.pojo.simple.CustomerPortfolioSimple; + +import com.google.gson.Gson; + +/** + * + * This class is responsible for performing functions for Simple type + * GSON like + * Java to Json + * Json to Map + * Json to Java Object + */ + +public class SimpleDataGson { + + private static final Logger logger = Logger.getLogger(SimpleDataGson.class); + + static Gson gson = new Gson(); + + static long generateJsonAvgTime = 0L; + + static long parseJsonToMapAvgTime = 0L; + + static long parseJsonToActualObjectAvgTime = 0L; + + public static void main(String[] args) { + CustomerPortfolioSimple customerPortfolioSimple = SimpleDataGeneration.generateData(); + String jsonStr = null; + int j = 5; + for (int i = 0; i < j; i++) { + logger.info("-------Round " + (i + 1)); + jsonStr = generateJson(customerPortfolioSimple); + logger.info("Size of Simple content Gson :: " + Utility.bytesIntoMB(jsonStr.getBytes().length)); + logger.info("--------------------------------------------------------------------------"); + parseJsonToMap(jsonStr); + parseJsonToActualObject(jsonStr); + jsonStr = null; + } + generateJsonAvgTime = generateJsonAvgTime / j; + parseJsonToMapAvgTime = parseJsonToMapAvgTime / j; + parseJsonToActualObjectAvgTime = parseJsonToActualObjectAvgTime / j; + + logger.info("--------------------------------------------------------------------------"); + logger.info("Average Time to Generate JSON : " + generateJsonAvgTime); + logger.info("Average Time to Parse JSON To Map : " + parseJsonToMapAvgTime); + logger.info("Average Time to Parse JSON To Actual Object : " + parseJsonToActualObjectAvgTime); + logger.info("--------------------------------------------------------------------------"); + } + + private static String generateJson(CustomerPortfolioSimple customerPortfolioSimple) { + Runtime.getRuntime().gc(); + long startParsTime = System.nanoTime(); + String json = gson.toJson(customerPortfolioSimple); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + generateJsonAvgTime = generateJsonAvgTime + elapsedTime; + logger.info("Json Generation Time(ms):: " + elapsedTime); + return json; + } + + private static void parseJsonToMap(String jsonStr) { + long startParsTime = System.nanoTime(); + Map parsedMap = gson.fromJson(jsonStr , Map.class); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + parseJsonToMapAvgTime = parseJsonToMapAvgTime + elapsedTime; + logger.info("Generating Map from json Time(ms):: " + elapsedTime); + logger.info("--------------------------------------------------------------------------"); + parsedMap = null; + Runtime.getRuntime().gc(); + + } + + private static void parseJsonToActualObject(String jsonStr) { + long startParsTime = System.nanoTime(); + CustomerPortfolioSimple customerPortfolioSimple = gson.fromJson(jsonStr , CustomerPortfolioSimple.class); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + parseJsonToActualObjectAvgTime = parseJsonToActualObjectAvgTime + elapsedTime; + logger.info("Generating Actual Object from json Time(ms):: " + elapsedTime); + logger.info("--------------------------------------------------------------------------"); + customerPortfolioSimple = null; + Runtime.getRuntime().gc(); + } +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/data/simple/SimpleDataJackson.java b/gson-jackson-performance/src/main/java/com/baeldung/data/simple/SimpleDataJackson.java new file mode 100644 index 0000000000..9330333604 --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/data/simple/SimpleDataJackson.java @@ -0,0 +1,95 @@ +package com.baeldung.data.simple; + +import java.io.IOException; +import java.util.Map; + +import com.baeldung.data.utility.Utility; +import org.apache.log4j.Logger; +import com.baeldung.pojo.simple.CustomerPortfolioSimple; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * + * This class is responsible for performing functions for Simple type + * Jackson like + * Java to Json + * Json to Map + * Json to Java Object + */ + +public class SimpleDataJackson { + + private static final Logger logger = Logger.getLogger(SimpleDataJackson.class); + + static ObjectMapper mapper = new ObjectMapper(); + + static long generateJsonAvgTime = 0L; + + static long parseJsonToMapAvgTime = 0L; + + static long parseJsonToActualObjectAvgTime = 0L; + + public static void main(String[] args) throws IOException { + CustomerPortfolioSimple customerPortfolioSimple = SimpleDataGeneration.generateData(); + int j = 50; + for (int i = 0; i < j; i++) { + logger.info("-------Round " + (i + 1)); + String jsonStr = generateJson(customerPortfolioSimple); + logger.info("Size of Simple content Jackson :: " + Utility.bytesIntoMB(jsonStr.getBytes().length)); + logger.info("--------------------------------------------------------------------------"); + + parseJsonToMap(jsonStr); + parseJsonToActualObject(jsonStr); + jsonStr = null; + } + + generateJsonAvgTime = generateJsonAvgTime / j; + parseJsonToMapAvgTime = parseJsonToMapAvgTime / j; + parseJsonToActualObjectAvgTime = parseJsonToActualObjectAvgTime / j; + + logger.info("--------------------------------------------------------------------------"); + logger.info("Average Time to Generate JSON : " + generateJsonAvgTime); + logger.info("Average Time to Parse JSON To Map : " + parseJsonToMapAvgTime); + logger.info("Average Time to Parse JSON To Actual Object : " + parseJsonToActualObjectAvgTime); + logger.info("--------------------------------------------------------------------------"); + } + + private static String generateJson(CustomerPortfolioSimple customerPortfolioSimple) throws JsonProcessingException { + Runtime.getRuntime().gc(); + long startParsTime = System.nanoTime(); + String json = mapper.writeValueAsString(customerPortfolioSimple); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + generateJsonAvgTime = generateJsonAvgTime + elapsedTime; + logger.info("Json Generation Time(ms):: " + elapsedTime); + return json; + } + + private static void parseJsonToMap(String jsonStr) throws JsonParseException , JsonMappingException , IOException { + long startParsTime = System.nanoTime(); + Map parsedMap = mapper.readValue(jsonStr , Map.class); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + parseJsonToMapAvgTime = parseJsonToMapAvgTime + elapsedTime; + logger.info("Generating Map from json Time(ms):: " + elapsedTime); + logger.info("--------------------------------------------------------------------------"); + parsedMap = null; + Runtime.getRuntime().gc(); + } + + private static void parseJsonToActualObject(String jsonStr) throws JsonParseException , JsonMappingException , + IOException { + long startParsTime = System.nanoTime(); + CustomerPortfolioSimple customerPortfolioSimple = mapper.readValue(jsonStr , CustomerPortfolioSimple.class); + long endParsTime = System.nanoTime(); + long elapsedTime = endParsTime - startParsTime; + parseJsonToActualObjectAvgTime = parseJsonToActualObjectAvgTime + elapsedTime; + logger.info("Generating Actual Object from json Time(ms):: " + elapsedTime); + customerPortfolioSimple = null; + Runtime.getRuntime().gc(); + } +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/data/utility/Utility.java b/gson-jackson-performance/src/main/java/com/baeldung/data/utility/Utility.java new file mode 100644 index 0000000000..8b0c402e47 --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/data/utility/Utility.java @@ -0,0 +1,90 @@ +package com.baeldung.data.utility; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.Random; + +public class Utility { + + public static String generateRandomName() { + char[] chars = "abcdefghijklmnopqrstuvwxyz ".toCharArray(); + StringBuilder sb = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < 8; i++) { + char c = chars[random.nextInt(chars.length)]; + sb.append(c); + } + return sb.toString(); + } + + public static String generateRandomAddress() { + char[] chars = "abcdefghijklmnopqrstuvwxyz ".toCharArray(); + StringBuilder sb = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < 30; i++) { + char c = chars[random.nextInt(chars.length)]; + sb.append(c); + } + return sb.toString(); + } + + public static String generateRandomZip() { + char[] chars = "1234567890".toCharArray(); + StringBuilder sb = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < 8; i++) { + char c = chars[random.nextInt(chars.length)]; + sb.append(c); + } + return sb.toString(); + } + + public static String generateRandomPhone() { + char[] chars = "1234567890".toCharArray(); + StringBuilder sb = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < 10; i++) { + char c = chars[random.nextInt(chars.length)]; + sb.append(c); + } + return sb.toString(); + } + + public static String readFile(String fileName , Class clazz) throws IOException { + String dir = clazz.getResource("/").getFile(); + dir = dir + "/" + fileName; + + BufferedReader br = new BufferedReader(new FileReader(dir)); + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + + while (line != null) { + sb.append(line); + sb.append(System.lineSeparator()); + line = br.readLine(); + } + return sb.toString(); + } finally { + br.close(); + } + } + + public static String bytesIntoMB(long bytes) { + long kilobyte = 1024; + long megabyte = kilobyte * 1024; + + if ((bytes >= 0) && (bytes < kilobyte)) { + return bytes + " B"; + + } else if ((bytes >= kilobyte) && (bytes < megabyte)) { + return (bytes / kilobyte) + " KB"; + + } else if ((bytes >= megabyte)) { + return (bytes / megabyte) + " MB"; + } + + return null; + } +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/AddressDetails.java b/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/AddressDetails.java new file mode 100644 index 0000000000..79725a97bd --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/AddressDetails.java @@ -0,0 +1,37 @@ +package com.baeldung.pojo.complex; + +import java.util.List; + +public class AddressDetails { + + private String address; + + private String zipcode; + + private List contactDetails; + + public String getZipcode() { + return zipcode; + } + + public void setZipcode(String zipcode) { + this.zipcode = zipcode; + } + + public List getContactDetails() { + return contactDetails; + } + + public void setContactDetails(List contactDetails) { + this.contactDetails = contactDetails; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/ContactDetails.java b/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/ContactDetails.java new file mode 100644 index 0000000000..164fe3f470 --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/ContactDetails.java @@ -0,0 +1,25 @@ +package com.baeldung.pojo.complex; + +public class ContactDetails { + + private String mobile; + + private String landline; + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getLandline() { + return landline; + } + + public void setLandline(String landline) { + this.landline = landline; + } + +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/CustomerAddressDetails.java b/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/CustomerAddressDetails.java new file mode 100644 index 0000000000..9bc5951716 --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/CustomerAddressDetails.java @@ -0,0 +1,18 @@ +package com.baeldung.pojo.complex; + +import java.util.List; + +import com.baeldung.pojo.simple.Customer; + +public class CustomerAddressDetails extends Customer { + + private List addressDetails; + + public List getAddressDetails() { + return addressDetails; + } + + public void setAddressDetails(List addressDetails) { + this.addressDetails = addressDetails; + } +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/CustomerPortfolioComplex.java b/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/CustomerPortfolioComplex.java new file mode 100644 index 0000000000..13f9d240b8 --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/pojo/complex/CustomerPortfolioComplex.java @@ -0,0 +1,17 @@ +package com.baeldung.pojo.complex; + +import java.util.List; + +public class CustomerPortfolioComplex { + + private List customerAddressDetailsList; + + public List getCustomerAddressDetailsList() { + return customerAddressDetailsList; + } + + public void setCustomerAddressDetailsList(List customerAddressDetailsList) { + this.customerAddressDetailsList = customerAddressDetailsList; + } + +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/pojo/simple/Customer.java b/gson-jackson-performance/src/main/java/com/baeldung/pojo/simple/Customer.java new file mode 100644 index 0000000000..3d5668f85a --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/pojo/simple/Customer.java @@ -0,0 +1,36 @@ +package com.baeldung.pojo.simple; + + +public class Customer { + + private String firstName; + + private String lastName; + + private int age; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/gson-jackson-performance/src/main/java/com/baeldung/pojo/simple/CustomerPortfolioSimple.java b/gson-jackson-performance/src/main/java/com/baeldung/pojo/simple/CustomerPortfolioSimple.java new file mode 100644 index 0000000000..7cb684813c --- /dev/null +++ b/gson-jackson-performance/src/main/java/com/baeldung/pojo/simple/CustomerPortfolioSimple.java @@ -0,0 +1,16 @@ +package com.baeldung.pojo.simple; + +import java.util.List; + +public class CustomerPortfolioSimple { + + private List customerLists; + + public List getCustomerLists() { + return customerLists; + } + + public void setCustomerLists(List customerLists) { + this.customerLists = customerLists; + } +} diff --git a/gson-jackson-performance/src/main/resources/log4j.properties b/gson-jackson-performance/src/main/resources/log4j.properties new file mode 100644 index 0000000000..371cbc9048 --- /dev/null +++ b/gson-jackson-performance/src/main/resources/log4j.properties @@ -0,0 +1,16 @@ +# Root logger option +log4j.rootLogger=DEBUG, file + +# Redirect log messages to console +# log4j.appender.stdout=org.apache.log4j.ConsoleAppender +# log4j.appender.stdout.Target=System.out +# log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +# log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n + +# Redirect log messages to a log file, support file rolling. +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.File=log4j-application.log +log4j.appender.file.MaxFileSize=5MB +log4j.appender.file.MaxBackupIndex=10 +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/gson/.classpath b/gson/.classpath deleted file mode 100644 index 5efa587d72..0000000000 --- a/gson/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gson/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/gson/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/gson/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/gson/.project b/gson/.project deleted file mode 100644 index 010b65738c..0000000000 --- a/gson/.project +++ /dev/null @@ -1,36 +0,0 @@ - - - gson - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/gson/.springBeans b/gson/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/gson/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/gson/README.md b/gson/README.md index 559e536d81..67651b732e 100644 --- a/gson/README.md +++ b/gson/README.md @@ -2,5 +2,6 @@ ## GSON Cookbooks and Examples -### Relevant Articles: +### Relevant Articles: +- [Gson Deserialization Cookbook](http://www.baeldung.com/gson-deserialization-guide) diff --git a/gson/pom.xml b/gson/pom.xml index c0640abcbf..4f331f6fd9 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung gson 0.1-SNAPSHOT @@ -112,13 +112,9 @@ - - 4.1.5.RELEASE - 3.2.5.RELEASE - - 4.3.10.Final - 5.1.35 + 4.3.11.Final + 5.1.38 2.3 @@ -142,14 +138,14 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.14 + 1.4.18 diff --git a/gson/src/main/java/org/baeldung/gson/entities/ActorGson.java b/gson/src/main/java/org/baeldung/gson/entities/ActorGson.java new file mode 100644 index 0000000000..5bbf776705 --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/entities/ActorGson.java @@ -0,0 +1,49 @@ +package org.baeldung.gson.entities; + +import java.util.Date; +import java.util.List; + +public class ActorGson { + + private String imdbId; + private Date dateOfBirth; + private List filmography; + + public ActorGson(String imdbId, Date dateOfBirth, List filmography) { + super(); + this.imdbId = imdbId; + this.dateOfBirth = dateOfBirth; + this.filmography = filmography; + } + + @Override + public String toString() { + return "ActorGson [imdbId=" + imdbId + ", dateOfBirth=" + dateOfBirth + ", filmography=" + filmography + "]"; + } + + public String getImdbId() { + return imdbId; + } + + public void setImdbId(String imdbId) { + this.imdbId = imdbId; + } + + public Date getDateOfBirth() { + return dateOfBirth; + } + + public void setDateOfBirth(Date dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } + + public List getFilmography() { + return filmography; + } + + public void setFilmography(List filmography) { + this.filmography = filmography; + } + + +} \ No newline at end of file diff --git a/gson/src/main/java/org/baeldung/gson/entities/Movie.java b/gson/src/main/java/org/baeldung/gson/entities/Movie.java new file mode 100644 index 0000000000..ee688f228d --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/entities/Movie.java @@ -0,0 +1,48 @@ +package org.baeldung.gson.entities; + +import java.util.List; + +public class Movie { + + private String imdbId; + private String director; + private List actors; + + public Movie(String imdbID, String director, List actors) { + super(); + this.imdbId = imdbID; + this.director = director; + this.actors = actors; + } + + @Override + public String toString() { + return "Movie [imdbId=" + imdbId + ", director=" + director + ", actors=" + actors + "]"; + } + + public String getImdbID() { + return imdbId; + } + + public void setImdbID(String imdbID) { + this.imdbId = imdbID; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public List getActors() { + return actors; + } + + public void setActors(List actors) { + this.actors = actors; + } + + +} \ No newline at end of file diff --git a/gson/src/main/java/org/baeldung/gson/entities/MovieWithNullValue.java b/gson/src/main/java/org/baeldung/gson/entities/MovieWithNullValue.java new file mode 100644 index 0000000000..fe62d51ffb --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/entities/MovieWithNullValue.java @@ -0,0 +1,46 @@ +package org.baeldung.gson.entities; + +import com.google.gson.annotations.Expose; + +import java.util.List; + +public class MovieWithNullValue { + + @Expose + private String imdbId; + private String director; + + @Expose + private List actors; + + public MovieWithNullValue(String imdbID, String director, List actors) { + super(); + this.imdbId = imdbID; + this.director = director; + this.actors = actors; + } + + public String getImdbID() { + return imdbId; + } + + public void setImdbID(String imdbID) { + this.imdbId = imdbID; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public List getActors() { + return actors; + } + + public void setActors(List actors) { + this.actors = actors; + } +} \ No newline at end of file diff --git a/gson/src/main/java/org/baeldung/gson/serialization/ActorGsonDeserializer.java b/gson/src/main/java/org/baeldung/gson/serialization/ActorGsonDeserializer.java new file mode 100644 index 0000000000..70a03500d5 --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/serialization/ActorGsonDeserializer.java @@ -0,0 +1,40 @@ +package org.baeldung.gson.serialization; + +import com.google.gson.*; +import org.baeldung.gson.entities.ActorGson; + +import java.lang.reflect.Type; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; + +public class ActorGsonDeserializer implements JsonDeserializer { + + private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + + @Override + public ActorGson deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + + JsonObject jsonObject = json.getAsJsonObject(); + + JsonElement jsonImdbId = jsonObject.get("imdbId"); + JsonElement jsonDateOfBirth = jsonObject.get("dateOfBirth"); + JsonArray jsonFilmography = jsonObject.getAsJsonArray("filmography"); + + ArrayList filmList = new ArrayList(); + if (jsonFilmography != null) { + for (int i = 0; i < jsonFilmography.size(); i++) { + filmList.add(jsonFilmography.get(i).getAsString()); + } + } + + ActorGson actorGson = null; + try { + actorGson = new ActorGson(jsonImdbId.getAsString(), sdf.parse(jsonDateOfBirth.getAsString()), filmList); + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return actorGson; + } +} \ No newline at end of file diff --git a/gson/src/main/java/org/baeldung/gson/serialization/ActorGsonSerializer.java b/gson/src/main/java/org/baeldung/gson/serialization/ActorGsonSerializer.java new file mode 100644 index 0000000000..8f2cd10f5a --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/serialization/ActorGsonSerializer.java @@ -0,0 +1,33 @@ +package org.baeldung.gson.serialization; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import org.baeldung.gson.entities.ActorGson; + +import java.lang.reflect.Type; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.stream.Collectors; + +public class ActorGsonSerializer implements JsonSerializer { + + private SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); + + @Override + public JsonElement serialize(ActorGson actor, Type type, JsonSerializationContext jsonSerializationContext) { + + JsonObject actorJsonObj = new JsonObject(); + actorJsonObj.addProperty("IMDB Code", actor.getImdbId()); + actorJsonObj.addProperty("Date Of Birth", actor.getDateOfBirth() != null ? sdf.format(actor.getDateOfBirth()) : null); + actorJsonObj.addProperty("N° Film: ", actor.getFilmography() != null ? actor.getFilmography().size() : null); + actorJsonObj.addProperty("filmography", actor.getFilmography() != null ? convertFilmography(actor.getFilmography()) : null); + + return actorJsonObj; + } + + private String convertFilmography(List filmography) { + return filmography.stream().collect(Collectors.joining("-")); + } +} \ No newline at end of file diff --git a/gson/src/main/webapp/WEB-INF/api-servlet.xml b/gson/src/main/webapp/WEB-INF/api-servlet.xml deleted file mode 100644 index 4c74be8912..0000000000 --- a/gson/src/main/webapp/WEB-INF/api-servlet.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/gson/src/main/webapp/WEB-INF/web.xml b/gson/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 935beae648..0000000000 --- a/gson/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - Spring MVC Application - - - - contextClass - - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - contextConfigLocation - org.baeldung.config - - - - org.springframework.web.context.ContextLoaderListener - - - - - api - org.springframework.web.servlet.DispatcherServlet - 1 - - - api - / - - - - - - - \ No newline at end of file diff --git a/gson/src/test/java/org/baeldung/gson/deserialization/GsonDeserializeTest.java b/gson/src/test/java/org/baeldung/gson/deserialization/GsonDeserializeTest.java new file mode 100644 index 0000000000..d87f0f4bd9 --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/deserialization/GsonDeserializeTest.java @@ -0,0 +1,38 @@ +package org.baeldung.gson.deserialization; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.baeldung.gson.entities.ActorGson; +import org.baeldung.gson.entities.Movie; +import org.baeldung.gson.serialization.ActorGsonDeserializer; +import org.junit.Assert; +import org.junit.Test; + +import java.text.ParseException; + +public class GsonDeserializeTest { + + @Test + public void whenSimpleDeserialize_thenCorrect() throws ParseException { + + String jsonInput = "{\"imdbId\":\"tt0472043\",\"actors\":" + "[{\"imdbId\":\"nm2199632\",\"dateOfBirth\":\"1982-09-21T12:00:00+01:00\",\"filmography\":" + "[\"Apocalypto\",\"Beatdown\",\"Wind Walkers\"]}]}"; + + Movie outputMovie = new Gson().fromJson(jsonInput, Movie.class); + + String expectedOutput = "Movie [imdbId=tt0472043, director=null, actors=[ActorGson [imdbId=nm2199632, dateOfBirth=Tue Sep 21 04:00:00 PDT 1982, filmography=[Apocalypto, Beatdown, Wind Walkers]]]]"; + Assert.assertEquals(outputMovie.toString(), expectedOutput); + } + + @Test + public void whenCustomDeserialize_thenCorrect() throws ParseException { + + String jsonInput = "{\"imdbId\":\"tt0472043\",\"actors\":" + "[{\"imdbId\":\"nm2199632\",\"dateOfBirth\":\"1982-09-21T12:00:00+01:00\",\"filmography\":" + "[\"Apocalypto\",\"Beatdown\",\"Wind Walkers\"]}]}"; + + Gson gson = new GsonBuilder().registerTypeAdapter(ActorGson.class, new ActorGsonDeserializer()).create(); + + Movie outputMovie = gson.fromJson(jsonInput, Movie.class); + + String expectedOutput = "Movie [imdbId=tt0472043, director=null, actors=[ActorGson [imdbId=nm2199632, dateOfBirth=Tue Sep 21 12:00:00 PDT 1982, filmography=[Apocalypto, Beatdown, Wind Walkers]]]]"; + Assert.assertEquals(outputMovie.toString(), expectedOutput); + } +} diff --git a/gson/src/test/java/org/baeldung/gson/serialization/GsonSerializeTest.java b/gson/src/test/java/org/baeldung/gson/serialization/GsonSerializeTest.java new file mode 100644 index 0000000000..7d5502b72f --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/serialization/GsonSerializeTest.java @@ -0,0 +1,48 @@ +package org.baeldung.gson.serialization; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParser; +import org.baeldung.gson.entities.ActorGson; +import org.baeldung.gson.entities.Movie; +import org.baeldung.gson.entities.MovieWithNullValue; +import org.junit.Assert; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; + +public class GsonSerializeTest { + + @Test + public void whenSimpleSerialize_thenCorrect() throws ParseException { + + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); + + ActorGson rudyYoungblood = new ActorGson("nm2199632", sdf.parse("21-09-1982"), Arrays.asList("Apocalypto", "Beatdown", "Wind Walkers")); + Movie movie = new Movie("tt0472043", "Mel Gibson", Arrays.asList(rudyYoungblood)); + + String expectedOutput = "{\"imdbId\":\"tt0472043\",\"director\":\"Mel Gibson\",\"actors\":[{\"imdbId\":\"nm2199632\",\"dateOfBirth\":\"Sep 21, 1982 12:00:00 AM\",\"filmography\":[\"Apocalypto\",\"Beatdown\",\"Wind Walkers\"]}]}"; + Assert.assertEquals(new Gson().toJson(movie), expectedOutput); + } + + @Test + public void whenCustomSerialize_thenCorrect() throws ParseException { + Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().serializeNulls().disableHtmlEscaping().registerTypeAdapter(ActorGson.class, new ActorGsonSerializer()).create(); + + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); + + ActorGson rudyYoungblood = new ActorGson("nm2199632", sdf.parse("21-09-1982"), Arrays.asList("Apocalypto", "Beatdown", "Wind Walkers")); + MovieWithNullValue movieWithNullValue = new MovieWithNullValue(null, "Mel Gibson", Arrays.asList(rudyYoungblood)); + + String expectedOutput = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .disableHtmlEscaping() + .create() + .toJson(new JsonParser() + .parse("{\"imdbId\":null,\"actors\":[{\"IMDB Code\":\"nm2199632\",\"Date Of Birth\":\"21-09-1982\",\"N° Film: \":3,\"filmography\":\"Apocalypto-Beatdown-Wind Walkers\"}]}")); + Assert.assertEquals(gson.toJson(movieWithNullValue), expectedOutput); + } +} diff --git a/guava/.classpath b/guava/.classpath deleted file mode 100644 index 8ebf6d9c31..0000000000 --- a/guava/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/guava/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/guava/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/guava/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/guava/.project b/guava/.project deleted file mode 100644 index 829dc83809..0000000000 --- a/guava/.project +++ /dev/null @@ -1,36 +0,0 @@ - - - guava - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/guava/.settings/.jsdtscope b/guava/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/guava/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/guava/.settings/org.eclipse.jdt.core.prefs b/guava/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/guava/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/guava/.settings/org.eclipse.jdt.ui.prefs b/guava/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/guava/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/guava/.settings/org.eclipse.m2e.core.prefs b/guava/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/guava/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/guava/.settings/org.eclipse.m2e.wtp.prefs b/guava/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/guava/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/guava/.settings/org.eclipse.wst.common.component b/guava/.settings/org.eclipse.wst.common.component deleted file mode 100644 index e98377cb0f..0000000000 --- a/guava/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/guava/.settings/org.eclipse.wst.common.project.facet.core.xml b/guava/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f4ef8aa0a5..0000000000 --- a/guava/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/guava/.settings/org.eclipse.wst.jsdt.ui.superType.container b/guava/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/guava/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/guava/.settings/org.eclipse.wst.jsdt.ui.superType.name b/guava/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/guava/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/guava/.settings/org.eclipse.wst.validation.prefs b/guava/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index cacf5451ae..0000000000 --- a/guava/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,14 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.303.v201202090300 -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/guava/.settings/org.eclipse.wst.ws.service.policy.prefs b/guava/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/guava/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/guava/.springBeans b/guava/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/guava/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/guava/README.md b/guava/README.md index 8960b4676e..28bcfeb912 100644 --- a/guava/README.md +++ b/guava/README.md @@ -7,7 +7,11 @@ - [Guava Collections Cookbook](http://www.baeldung.com/guava-collections) - [Guava Ordering Cookbook](http://www.baeldung.com/guava-order) - [Guava Functional Cookbook](http://www.baeldung.com/guava-functions-predicates) - - [Hamcrest Collections Cookbook](http://www.baeldung.com/hamcrest-collections-arrays) - - [Partition a List in Java](http://www.baeldung.com/java-list-split) +- [Filtering and Transforming Collections in Guava](http://www.baeldung.com/guava-filter-and-transform-a-collection) +- [Guava – Join and Split Collections](http://www.baeldung.com/guava-joiner-and-splitter-tutorial) +- [Guava – Write to File, Read from File](http://www.baeldung.com/guava-write-to-file-read-from-file) +- [Guava – Lists](http://www.baeldung.com/guava-lists) +- [Guava – Sets](http://www.baeldung.com/guava-sets) +- [Guava – Maps](http://www.baeldung.com/guava-maps) diff --git a/guava/pom.xml b/guava/pom.xml index 2b07be71bf..59ca3aa1bb 100644 --- a/guava/pom.xml +++ b/guava/pom.xml @@ -1,8 +1,8 @@ 4.0.0 - org.baeldung + com.baeldung guava - 0.1-SNAPSHOT + 0.1.0-SNAPSHOT guava @@ -93,13 +93,9 @@ - - 4.1.5.RELEASE - 3.2.5.RELEASE - - 4.3.10.Final - 5.1.35 + 4.3.11.Final + 5.1.38 1.7.13 @@ -120,14 +116,14 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.14 + 1.4.18 diff --git a/guava/src/main/webapp/WEB-INF/api-servlet.xml b/guava/src/main/webapp/WEB-INF/api-servlet.xml deleted file mode 100644 index 4c74be8912..0000000000 --- a/guava/src/main/webapp/WEB-INF/api-servlet.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/guava/src/main/webapp/WEB-INF/web.xml b/guava/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 935beae648..0000000000 --- a/guava/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - Spring MVC Application - - - - contextClass - - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - contextConfigLocation - org.baeldung.config - - - - org.springframework.web.context.ContextLoaderListener - - - - - api - org.springframework.web.servlet.DispatcherServlet - 1 - - - api - / - - - - - - - \ No newline at end of file diff --git a/guava/src/test/java/org/baeldung/guava/GuavaMapFromSet.java b/guava/src/test/java/org/baeldung/guava/GuavaMapFromSet.java new file mode 100644 index 0000000000..1d19423f7e --- /dev/null +++ b/guava/src/test/java/org/baeldung/guava/GuavaMapFromSet.java @@ -0,0 +1,101 @@ +package org.baeldung.guava; + +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; + +import com.google.common.base.Function; + +public class GuavaMapFromSet extends AbstractMap { + + private class SingleEntry implements Entry { + private K key; + + public SingleEntry(K key) { + this.key = key; + } + + @Override + public K getKey() { + return this.key; + } + + @Override + public V getValue() { + V value = GuavaMapFromSet.this.cache.get(this.key); + if (value == null) { + value = GuavaMapFromSet.this.function.apply(this.key); + GuavaMapFromSet.this.cache.put(this.key, value); + } + return value; + } + + @Override + public V setValue(V value) { + throw new UnsupportedOperationException(); + } + } + + private class MyEntrySet extends AbstractSet> { + + public class EntryIterator implements Iterator> { + private Iterator inner; + + public EntryIterator() { + this.inner = MyEntrySet.this.keys.iterator(); + } + + @Override + public boolean hasNext() { + return this.inner.hasNext(); + } + + @Override + public Map.Entry next() { + K key = this.inner.next(); + return new SingleEntry(key); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + private Set keys; + + public MyEntrySet(Set keys) { + this.keys = keys; + } + + @Override + public Iterator> iterator() { + return new EntryIterator(); + } + + @Override + public int size() { + return this.keys.size(); + } + + } + + private WeakHashMap cache; + private Set> entries; + private Function function; + + public GuavaMapFromSet(Set keys, Function function) { + this.function = function; + this.cache = new WeakHashMap(); + this.entries = new MyEntrySet(keys); + } + + @Override + public Set> entrySet() { + return this.entries; + } + +} diff --git a/guava/src/test/java/org/baeldung/guava/GuavaMapFromSetTests.java b/guava/src/test/java/org/baeldung/guava/GuavaMapFromSetTests.java new file mode 100644 index 0000000000..7dc4550c09 --- /dev/null +++ b/guava/src/test/java/org/baeldung/guava/GuavaMapFromSetTests.java @@ -0,0 +1,64 @@ +package org.baeldung.guava; + +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.junit.Test; + +import com.google.common.base.Function; + +public class GuavaMapFromSetTests { + + @Test + public void givenStringSet_whenMapsToElementLength_thenCorrect() { + Function function = new Function() { + @Override + public String apply(Integer from) { + return Integer.toBinaryString(from); + } + }; + Set set = new TreeSet<>(Arrays.asList(32, 64, 128)); + Map map = new GuavaMapFromSet(set, function); + assertTrue(map.get(32).equals("100000") + && map.get(64).equals("1000000") + && map.get(128).equals("10000000")); + } + + @Test + public void givenIntSet_whenMapsToElementBinaryValue_thenCorrect() { + Function function = new Function() { + + @Override + public Integer apply(String from) { + return from.length(); + } + }; + Set set = new TreeSet<>(Arrays.asList( + "four", "three", "twelve")); + Map map = new GuavaMapFromSet(set, + function); + assertTrue(map.get("four") == 4 && map.get("three") == 5 + && map.get("twelve") == 6); + } + + @Test + public void givenSet_whenNewSetElementAddedAndMappedLive_thenCorrect() { + Function function = new Function() { + + @Override + public Integer apply(String from) { + return from.length(); + } + }; + Set set = new TreeSet<>(Arrays.asList( + "four", "three", "twelve")); + Map map = new GuavaMapFromSet(set, + function); + set.add("one"); + assertTrue(map.get("one") == 3 && map.size() == 4); + } +} diff --git a/guava/src/test/java/org/baeldung/hamcrest/Animal.java b/guava/src/test/java/org/baeldung/hamcrest/Animal.java new file mode 100644 index 0000000000..1a0266f5a3 --- /dev/null +++ b/guava/src/test/java/org/baeldung/hamcrest/Animal.java @@ -0,0 +1,33 @@ +package org.baeldung.hamcrest; + +public class Animal { + String name; + boolean wild; + String sound; + + public Animal(String name, boolean wild, String sound) { + super(); + this.name = name; + this.wild = wild; + this.sound = sound; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public boolean isWild() { + return wild; + } + public void setWild(boolean wild) { + this.wild = wild; + } + public String getSound() { + return sound; + } + public void setSound(String sound) { + this.sound = sound; + } + +} diff --git a/guava/src/test/java/org/baeldung/hamcrest/Cat.java b/guava/src/test/java/org/baeldung/hamcrest/Cat.java new file mode 100644 index 0000000000..892e5b6e30 --- /dev/null +++ b/guava/src/test/java/org/baeldung/hamcrest/Cat.java @@ -0,0 +1,13 @@ +package org.baeldung.hamcrest; + +public class Cat extends Animal { + + public Cat() { + super("cat", false, "meow"); + } + + public String makeSound() { + return getSound(); + } + +} diff --git a/guava/src/test/java/org/baeldung/hamcrest/HamcrestMatcherTest.java b/guava/src/test/java/org/baeldung/hamcrest/HamcrestMatcherTest.java new file mode 100644 index 0000000000..b3756d609f --- /dev/null +++ b/guava/src/test/java/org/baeldung/hamcrest/HamcrestMatcherTest.java @@ -0,0 +1,331 @@ +package org.baeldung.hamcrest; + +import org.junit.Test; + +import java.util.*; + +import static org.baeldung.hamcrest.IsPositiveInteger.isAPositiveInteger; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.hamcrest.beans.HasProperty.hasProperty; +import static org.hamcrest.beans.HasPropertyWithValue.hasProperty; +import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs; +import static org.hamcrest.collection.IsArrayContaining.hasItemInArray; +import static org.hamcrest.collection.IsArrayContainingInAnyOrder.arrayContainingInAnyOrder; +import static org.hamcrest.collection.IsArrayContainingInOrder.arrayContaining; +import static org.hamcrest.collection.IsArrayWithSize.arrayWithSize; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.hamcrest.collection.IsEmptyCollection.empty; +import static org.hamcrest.collection.IsIn.isIn; +import static org.hamcrest.collection.IsIn.isOneOf; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; +import static org.hamcrest.collection.IsMapContaining.hasEntry; +import static org.hamcrest.collection.IsMapContaining.hasKey; +import static org.hamcrest.collection.IsMapContaining.hasValue; +import static org.hamcrest.core.AllOf.allOf; +import static org.hamcrest.core.AnyOf.anyOf; +import static org.hamcrest.core.Every.everyItem; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.hamcrest.core.StringContains.containsString; +import static org.hamcrest.core.StringEndsWith.endsWith; +import static org.hamcrest.core.StringStartsWith.startsWith; +import static org.hamcrest.object.HasToString.hasToString; +import static org.hamcrest.object.IsCompatibleType.typeCompatibleWith; +import static org.hamcrest.text.IsEmptyString.isEmptyOrNullString; +import static org.hamcrest.text.IsEmptyString.isEmptyString; +import static org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase; +import static org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace; +import static org.hamcrest.text.StringContainsInOrder.stringContainsInOrder; + +public class HamcrestMatcherTest { + @Test + public void given2Strings_whenEqual_thenCorrect() { + String a = "foo"; + String b = "FOO"; + assertThat(a, equalToIgnoringCase(b)); + } + + @Test + public void givenBean_whenHasValue_thenCorrect() { + Person person = new Person("Baeldung", "New York"); + assertThat(person, hasProperty("name")); + } + + @Test + public void givenBean_whenHasCorrectValue_thenCorrect() { + Person person = new Person("Baeldung", "New York"); + assertThat(person, hasProperty("address", equalTo("New York"))); + } + + @Test + public void given2Beans_whenHavingSameValues_thenCorrect() { + Person person1 = new Person("Baeldung", "New York"); + Person person2 = new Person("Baeldung", "New York"); + assertThat(person1, samePropertyValuesAs(person2)); + } + + @Test + public void givenAList_whenChecksSize_thenCorrect() { + List hamcrestMatchers = Arrays.asList("collections", "beans", + "text", "number"); + assertThat(hamcrestMatchers, hasSize(4)); + } + + @Test + public void givenArray_whenChecksSize_thenCorrect() { + String[] hamcrestMatchers = { "collections", "beans", "text", "number" }; + assertThat(hamcrestMatchers, arrayWithSize(4)); + } + + @Test + public void givenAListAndValues_whenChecksListForGivenValues_thenCorrect() { + List hamcrestMatchers = Arrays.asList("collections", "beans", + "text", "number"); + assertThat(hamcrestMatchers, + containsInAnyOrder("beans", "text", "collections", "number")); + } + + @Test + public void givenAListAndValues_whenChecksListForGivenValuesWithOrder_thenCorrect() { + List hamcrestMatchers = Arrays.asList("collections", "beans", + "text", "number"); + assertThat(hamcrestMatchers, + contains("collections", "beans", "text", "number")); + } + + @Test + public void givenArrayAndValue_whenValueFoundInArray_thenCorrect() { + String[] hamcrestMatchers = { "collections", "beans", "text", "number" }; + assertThat(hamcrestMatchers, hasItemInArray("text")); + + } + + @Test + public void givenValueAndArray_whenValueIsOneOfArrayElements_thenCorrect() { + String[] hamcrestMatchers = { "collections", "beans", "text", "number" }; + assertThat("text", isOneOf(hamcrestMatchers)); + + } + + @Test + public void givenArrayAndValues_whenValuesFoundInArray_thenCorrect() { + String[] hamcrestMatchers = { "collections", "beans", "text", "number" }; + assertThat( + hamcrestMatchers, + arrayContainingInAnyOrder("beans", "collections", "number", + "text")); + + } + + @Test + public void givenArrayAndValues_whenValuesFoundInArrayInOrder_thenCorrect() { + String[] hamcrestMatchers = { "collections", "beans", "text", "number" }; + assertThat(hamcrestMatchers, + arrayContaining("collections", "beans", "text", "number")); + + } + + @Test + public void givenCollection_whenEmpty_thenCorrect() { + List emptyList = new ArrayList<>(); + assertThat(emptyList, empty()); + + } + + @Test + public void givenValueAndArray_whenValueFoundInArray_thenCorrect() { + String[] array = new String[] { "collections", "beans", "text", + "number" }; + assertThat("beans", isIn(array)); + + } + + @Test + public void givenMapAndKey_whenKeyFoundInMap_thenCorrect() { + Map map = new HashMap<>(); + map.put("blogname", "baeldung"); + assertThat(map, hasKey("blogname")); + } + + @Test + public void givenMapAndEntry_whenEntryFoundInMap_thenCorrect() { + Map map = new HashMap<>(); + map.put("blogname", "baeldung"); + assertThat(map, hasEntry("blogname", "baeldung")); + } + + @Test + public void givenMapAndValue_whenValueFoundInMap_thenCorrect() { + Map map = new HashMap<>(); + map.put("blogname", "baeldung"); + assertThat(map, hasValue("baeldung")); + } + + @Test + public void givenString_whenEmpty_thenCorrect() { + String str = ""; + assertThat(str, isEmptyString()); + } + + @Test + public void givenString_whenEmptyOrNull_thenCorrect() { + String str = null; + assertThat(str, isEmptyOrNullString()); + } + + @Test + public void given2Strings_whenEqualRegardlessWhiteSpace_thenCorrect() { + String str1 = "text"; + String str2 = " text "; + assertThat(str1, equalToIgnoringWhiteSpace(str2)); + } + + @Test + public void givenString_whenContainsGivenSubstring_thenCorrect() { + String str = "calligraphy"; + assertThat(str, stringContainsInOrder(Arrays.asList("call", "graph"))); + } + + @Test + public void givenBean_whenToStringReturnsRequiredString_thenCorrect() { + Person person = new Person("Barrack", "Washington"); + String str = person.toString(); + assertThat(person, hasToString(str)); + } + + @Test + public void given2Classes_whenOneInheritsFromOther_thenCorrect() { + assertThat(Cat.class, typeCompatibleWith(Animal.class)); + } + + + @Test + public void given2Strings_whenIsEqualRegardlessWhiteSpace_thenCorrect() { + String str1 = "text"; + String str2 = " text "; + assertThat(str1, is(equalToIgnoringWhiteSpace(str2))); + } + + @Test + public void given2Strings_whenIsNotEqualRegardlessWhiteSpace_thenCorrect() { + String str1 = "text"; + String str2 = " texts "; + assertThat(str1, not(equalToIgnoringWhiteSpace(str2))); + } + + @Test + public void given2Strings_whenNotEqual_thenCorrect() { + String str1 = "text"; + String str2 = "texts"; + assertThat(str1, not(str2)); + } + + @Test + public void given2Strings_whenIsEqual_thenCorrect() { + String str1 = "text"; + String str2 = "text"; + assertThat(str1, is(str2)); + } + + @Test + public void givenAStrings_whenContainsAnotherGivenString_thenCorrect() { + String str1 = "calligraphy"; + String str2 = "call"; + assertThat(str1, containsString(str2)); + } + + @Test + public void givenAString_whenEndsWithAnotherGivenString_thenCorrect() { + String str1 = "calligraphy"; + String str2 = "phy"; + assertThat(str1, endsWith(str2)); + } + + @Test + public void givenAString_whenStartsWithAnotherGivenString_thenCorrect() { + String str1 = "calligraphy"; + String str2 = "call"; + assertThat(str1, startsWith(str2)); + } + + @Test + public void given2Objects_whenSameInstance_thenCorrect() { + Cat cat = new Cat(); + assertThat(cat, sameInstance(cat)); + } + + @Test + public void givenAnObject_whenInstanceOfGivenClass_thenCorrect() { + Cat cat = new Cat(); + assertThat(cat, instanceOf(Cat.class)); + } + + @Test + public void givenList_whenEachElementGreaterThan0_thenCorrect() { + List list = Arrays.asList(1, 2, 3); + int baseCase = 0; + assertThat(list, everyItem(greaterThan(baseCase))); + } + + @Test + public void givenString_whenNotNull_thenCorrect() { + String str = "notnull"; + assertThat(str, notNullValue()); + } + + @Test + public void givenString_whenMeetsAnyOfGivenConditions_thenCorrect() { + String str = "calligraphy"; + String start = "call"; + String end = "foo"; + assertThat(str, anyOf(startsWith(start), containsString(end))); + } + + @Test + public void givenString_whenMeetsAllOfGivenConditions_thenCorrect() { + String str = "calligraphy"; + String start = "call"; + String end = "phy"; + assertThat(str, allOf(startsWith(start), endsWith(end))); + } + + @Test + public void givenInteger_whenAPositiveValue_thenCorrect() { + int num = 1; + assertThat(num, isAPositiveInteger()); + } + + @Test + public void givenAnInteger_whenGreaterThan0_thenCorrect() { + int num = 1; + assertThat(num, greaterThan(0)); + } + + @Test + public void givenAnInteger_whenGreaterThanOrEqTo5_thenCorrect() { + int num = 5; + assertThat(num, greaterThanOrEqualTo(5)); + } + + @Test + public void givenAnInteger_whenLessThan0_thenCorrect() { + int num = -1; + assertThat(num, lessThan(0)); + } + + @Test + public void givenAnInteger_whenLessThanOrEqTo5_thenCorrect() { + assertThat(-1, lessThanOrEqualTo(5)); + } + + @Test + public void givenADouble_whenCloseTo_thenCorrect() { + assertThat(1.2, closeTo(1, 0.5)); + } + +} diff --git a/guava/src/test/java/org/baeldung/hamcrest/IsPositiveInteger.java b/guava/src/test/java/org/baeldung/hamcrest/IsPositiveInteger.java new file mode 100644 index 0000000000..0d8d262538 --- /dev/null +++ b/guava/src/test/java/org/baeldung/hamcrest/IsPositiveInteger.java @@ -0,0 +1,24 @@ +package org.baeldung.hamcrest; + +import org.hamcrest.Description; +import org.hamcrest.Factory; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +public class IsPositiveInteger extends TypeSafeMatcher { + + public void describeTo(Description description) { + description.appendText("a positive integer"); + } + + @Factory + public static Matcher isAPositiveInteger() { + return new IsPositiveInteger(); + } + + @Override + protected boolean matchesSafely(Integer integer) { + return integer > 0; + } + +} diff --git a/guava/src/test/java/org/baeldung/hamcrest/Person.java b/guava/src/test/java/org/baeldung/hamcrest/Person.java new file mode 100644 index 0000000000..0053c98043 --- /dev/null +++ b/guava/src/test/java/org/baeldung/hamcrest/Person.java @@ -0,0 +1,37 @@ +package org.baeldung.hamcrest; + +public class Person { + String name; + String address; + + public Person(String personName, String personAddress) { + name = personName; + address = personAddress; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + @Override + public String toString() { + String str="[address:"+address+",name:"+name+"]"; + return str; + } + + + + +} diff --git a/guava18/README.md b/guava18/README.md index 8960b4676e..9924d7c16f 100644 --- a/guava18/README.md +++ b/guava18/README.md @@ -7,7 +7,6 @@ - [Guava Collections Cookbook](http://www.baeldung.com/guava-collections) - [Guava Ordering Cookbook](http://www.baeldung.com/guava-order) - [Guava Functional Cookbook](http://www.baeldung.com/guava-functions-predicates) - - [Hamcrest Collections Cookbook](http://www.baeldung.com/hamcrest-collections-arrays) - - [Partition a List in Java](http://www.baeldung.com/java-list-split) +- [Guava 18: What’s New?](http://www.baeldung.com/whats-new-in-guava-18) diff --git a/guava18/pom.xml b/guava18/pom.xml index 21f4697a73..6002b37d74 100644 --- a/guava18/pom.xml +++ b/guava18/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung - guava - 1.0-SNAPSHOT + guava18 + 0.1.0-SNAPSHOT diff --git a/guava19/README.md b/guava19/README.md new file mode 100644 index 0000000000..be9f2d72a4 --- /dev/null +++ b/guava19/README.md @@ -0,0 +1,7 @@ +========= + +## Guava 19 + + +### Relevant Articles: +- [Guava 19: What’s New?](http://www.baeldung.com/whats-new-in-guava-19) diff --git a/guava19/pom.xml b/guava19/pom.xml new file mode 100644 index 0000000000..13f3b471f1 --- /dev/null +++ b/guava19/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + com.baeldung + guava19 + 0.1.0-SNAPSHOT + + + + com.google.guava + guava + 19.0 + + + junit + junit + 4.12 + + + org.hamcrest + hamcrest-all + 1.3 + + + + + + + maven-compiler-plugin + 3.3 + + true + true + 1.8 + 1.8 + UTF-8 + true + true + + + + + + \ No newline at end of file diff --git a/guava19/src/main/java/com/baeldung/guava/entity/User.java b/guava19/src/main/java/com/baeldung/guava/entity/User.java new file mode 100644 index 0000000000..be673edb10 --- /dev/null +++ b/guava19/src/main/java/com/baeldung/guava/entity/User.java @@ -0,0 +1,36 @@ +package com.baeldung.guava.entity; + +import com.google.common.base.MoreObjects; + +public class User{ + private long id; + private String name; + private int age; + + public User(long id, String name, int age) { + this.id = id; + this.name = name; + this.age = age; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(User.class) + .add("id", id) + .add("name", name) + .add("age", age) + .toString(); + } +} \ No newline at end of file diff --git a/guava19/src/test/java/com/baeldung/guava/CharMatcherTest.java b/guava19/src/test/java/com/baeldung/guava/CharMatcherTest.java new file mode 100644 index 0000000000..f890d9abc1 --- /dev/null +++ b/guava19/src/test/java/com/baeldung/guava/CharMatcherTest.java @@ -0,0 +1,33 @@ +package com.baeldung.guava; + +import com.google.common.base.CharMatcher; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class CharMatcherTest { + @Test + public void whenMatchingLetterOrString_ShouldReturnTrueForCorrectString() throws Exception { + String inputString = "someString789"; + boolean result = CharMatcher.javaLetterOrDigit().matchesAllOf(inputString); + + assertTrue(result); + } + + @Test + public void whenCollapsingString_ShouldReturnStringWithDashesInsteadOfWhitespaces() throws Exception { + String inputPhoneNumber = "8 123 456 123"; + String result = CharMatcher.whitespace().collapseFrom(inputPhoneNumber, '-'); + + assertEquals("8-123-456-123", result); + } + + @Test + public void whenCountingDigitsInString_ShouldReturnActualCountOfDigits() throws Exception { + String inputPhoneNumber = "8 123 456 123"; + int result = CharMatcher.digit().countIn(inputPhoneNumber); + + assertEquals(10, result); + } +} diff --git a/guava19/src/test/java/com/baeldung/guava/GuavaMiscUtilsTest.java b/guava19/src/test/java/com/baeldung/guava/GuavaMiscUtilsTest.java new file mode 100644 index 0000000000..c7b8441b78 --- /dev/null +++ b/guava19/src/test/java/com/baeldung/guava/GuavaMiscUtilsTest.java @@ -0,0 +1,88 @@ +package com.baeldung.guava; + +import com.google.common.base.Throwables; +import com.google.common.collect.*; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.hamcrest.core.AnyOf.anyOf; +import static org.junit.Assert.*; + +public class GuavaMiscUtilsTest { + + @Test + public void whenGettingLazyStackTrace_ListShouldBeReturned() throws Exception { + IllegalArgumentException e = new IllegalArgumentException("Some argument is incorrect"); + + List stackTraceElements = Throwables.lazyStackTrace(e); + + assertTrue(stackTraceElements.size() > 0); + } + + @Test + public void multisetShouldCountHitsOfMultipleDuplicateObjects() throws Exception { + List userNames = Arrays.asList("David", "Eugene", "Alex", "Alex", "David", "David", "David"); + + Multiset userNamesMultiset = HashMultiset.create(userNames); + + assertEquals(7, userNamesMultiset.size()); + assertEquals(4, userNamesMultiset.count("David")); + assertEquals(2, userNamesMultiset.count("Alex")); + assertEquals(1, userNamesMultiset.count("Eugene")); + assertThat(userNamesMultiset.elementSet(), anyOf(containsInAnyOrder("Alex", "David", "Eugene"))); + } + + @Test + public void whenAddingNewConnectedRange_RangesShouldBeMerged() throws Exception { + RangeSet rangeSet = TreeRangeSet.create(); + + rangeSet.add(Range.closed(1, 10)); + rangeSet.add(Range.closed(5, 15)); + rangeSet.add(Range.closedOpen(10, 17)); + + assertTrue(rangeSet.encloses(Range.closedOpen(1, 17))); + assertTrue(rangeSet.encloses(Range.closed(2, 3))); + assertTrue(rangeSet.contains(15)); + assertFalse(rangeSet.contains(17)); + assertEquals(1, rangeSet.asDescendingSetOfRanges().size()); + } + + @Test + public void cartesianProductShouldReturnAllPossibleCombinations() throws Exception { + List first = Lists.newArrayList("value1", "value2"); + List second = Lists.newArrayList("value3", "value4"); + + List> cartesianProduct = Lists.cartesianProduct(first, second); + + List pair1 = Lists.newArrayList("value2", "value3"); + List pair2 = Lists.newArrayList("value2", "value4"); + List pair3 = Lists.newArrayList("value1", "value3"); + List pair4 = Lists.newArrayList("value1", "value4"); + + assertThat(cartesianProduct, anyOf(containsInAnyOrder(pair1, pair2, pair3, pair4))); + } + + @Test + public void multisetShouldRemoveOccurrencesOfSpecifiedObjects() throws Exception { + Multiset multisetToModify = HashMultiset.create(); + Multiset occurrencesToRemove = HashMultiset.create(); + + multisetToModify.add("John"); + multisetToModify.add("Max"); + multisetToModify.add("Alex"); + + occurrencesToRemove.add("Alex"); + occurrencesToRemove.add("John"); + + Multisets.removeOccurrences(multisetToModify, occurrencesToRemove); + + assertEquals(1, multisetToModify.size()); + assertTrue(multisetToModify.contains("Max")); + assertFalse(multisetToModify.contains("John")); + assertFalse(multisetToModify.contains("Alex")); + } +} \ No newline at end of file diff --git a/guava19/src/test/java/com/baeldung/guava/HashingTest.java b/guava19/src/test/java/com/baeldung/guava/HashingTest.java new file mode 100644 index 0000000000..9b4acde9f7 --- /dev/null +++ b/guava19/src/test/java/com/baeldung/guava/HashingTest.java @@ -0,0 +1,34 @@ +package com.baeldung.guava; + +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hashing; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class HashingTest { + @Test + public void whenHashingInSha384_hashFunctionShouldBeReturned() throws Exception { + int inputData = 15; + + HashFunction hashFunction = Hashing.sha384(); + HashCode hashCode = hashFunction.hashInt(inputData); + + assertEquals("0904b6277381dcfbdddd6b6c66e4e3e8f83d4690718d8e6f272c891f24773a12feaf8c449fa6e42240a621b2b5e3cda8", + hashCode.toString()); + } + + @Test + public void whenConcatenatingHashFunction_concatenatedHashShouldBeReturned() throws Exception { + int inputData = 15; + + HashFunction hashFunction = Hashing.concatenating(Hashing.crc32(), Hashing.crc32()); + HashFunction crc32Function = Hashing.crc32(); + + HashCode hashCode = hashFunction.hashInt(inputData); + HashCode crc32HashCode = crc32Function.hashInt(inputData); + + assertEquals(crc32HashCode.toString() + crc32HashCode.toString(), hashCode.toString()); + } +} diff --git a/guava19/src/test/java/com/baeldung/guava/TypeTokenTest.java b/guava19/src/test/java/com/baeldung/guava/TypeTokenTest.java new file mode 100644 index 0000000000..1923451f20 --- /dev/null +++ b/guava19/src/test/java/com/baeldung/guava/TypeTokenTest.java @@ -0,0 +1,45 @@ +package com.baeldung.guava; + +import com.google.common.reflect.TypeToken; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class TypeTokenTest { + @Test + public void whenCheckingIsAssignableFrom_shouldReturnTrueEvenIfGenericIsSpecified() throws Exception { + ArrayList stringList = new ArrayList<>(); + ArrayList intList = new ArrayList<>(); + boolean isAssignableFrom = stringList.getClass().isAssignableFrom(intList.getClass()); + + assertTrue(isAssignableFrom); + } + + @Test + public void whenCheckingIsSupertypeOf_shouldReturnFalseIfGenericIsSpecified() throws Exception { + TypeToken> listString = new TypeToken>() { + }; + TypeToken> integerString = new TypeToken>() { + }; + + boolean isSupertypeOf = listString.isSupertypeOf(integerString); + + assertFalse(isSupertypeOf); + } + + @Test + public void whenCheckingIsSubtypeOf_shouldReturnTrueIfClassIsExtendedFrom() throws Exception { + TypeToken> stringList = new TypeToken>() { + }; + TypeToken list = new TypeToken() { + }; + + boolean isSubtypeOf = stringList.isSubtypeOf(list); + + assertTrue(isSubtypeOf); + } +} diff --git a/handling-spring-static-resources/.classpath b/handling-spring-static-resources/.classpath deleted file mode 100644 index 71a1c1e0b5..0000000000 --- a/handling-spring-static-resources/.classpath +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/handling-spring-static-resources/.project b/handling-spring-static-resources/.project deleted file mode 100644 index a16def8042..0000000000 --- a/handling-spring-static-resources/.project +++ /dev/null @@ -1,54 +0,0 @@ - - - handling-spring-static-resources - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.hibernate.eclipse.console.hibernateBuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.wst.jsdt.core.jsNature - org.hibernate.eclipse.console.hibernateNature - - diff --git a/handling-spring-static-resources/.springBeans b/handling-spring-static-resources/.springBeans deleted file mode 100644 index dd8f096d1d..0000000000 --- a/handling-spring-static-resources/.springBeans +++ /dev/null @@ -1,16 +0,0 @@ - - - 1 - - - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/handling-spring-static-resources/pom.xml b/handling-spring-static-resources/pom.xml index 8efacc4b28..aca069e300 100644 --- a/handling-spring-static-resources/pom.xml +++ b/handling-spring-static-resources/pom.xml @@ -1,12 +1,14 @@ 4.0.0 - org.baeldung - handling-spring-static-resources - handling-spring-static-resources - 0.1-SNAPSHOT + + com.baeldung + spring-static-resources + 0.1.0-SNAPSHOT war + spring-static-resources + @@ -161,32 +163,66 @@ - handling-spring-static-resources + spring-static-resources src/main/resources true + + + net.alchim31.maven + yuicompressor-maven-plugin + 1.5.1 + + + + compress + + + + + true + ${project.build.directory}/min + + **/*.min.js + **/handlebars-3133af2.js + **/require.js + + + + + maven-war-plugin + + + + ${project.build.directory}/min + + + + + 1.8 + - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 1.8.1 2.3.2-b01 4.3.11.Final - 5.1.37 + 5.1.38 1.9.2.RELEASE - 2.6.4 + 2.7.2 1.7.13 @@ -207,13 +243,13 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 - 1.4.14 + 2.19.1 + 1.4.18 \ No newline at end of file diff --git a/handling-spring-static-resources/src/main/webapp/js/app.js b/handling-spring-static-resources/src/main/webapp/js/app.js deleted file mode 100644 index e312d6d670..0000000000 --- a/handling-spring-static-resources/src/main/webapp/js/app.js +++ /dev/null @@ -1,4 +0,0 @@ -/** - * - */ -window.Todos = Ember.Application.create(); \ No newline at end of file diff --git a/handling-spring-static-resources/src/main/webapp/js/ember-data.js b/handling-spring-static-resources/src/main/webapp/js/ember-data.js deleted file mode 100644 index 689e0d3cda..0000000000 --- a/handling-spring-static-resources/src/main/webapp/js/ember-data.js +++ /dev/null @@ -1,10548 +0,0 @@ -/*! - * @overview Ember Data - * @copyright Copyright 2011-2014 Tilde Inc. and contributors. - * Portions Copyright 2011 LivingSocial Inc. - * @license Licensed under MIT license (see license.js) - * @version 1.0.0-beta.5 - */ - - -(function() { -var define, requireModule; - -(function() { - var registry = {}, seen = {}; - - define = function(name, deps, callback) { - registry[name] = { deps: deps, callback: callback }; - }; - - requireModule = function(name) { - if (seen[name]) { return seen[name]; } - seen[name] = {}; - - var mod, deps, callback, reified , exports; - - mod = registry[name]; - - if (!mod) { - throw new Error("Module '" + name + "' not found."); - } - - deps = mod.deps; - callback = mod.callback; - reified = []; - exports; - - for (var i=0, l=deps.length; i self.attributeLimit) { return false; } - var desc = capitalize(underscore(name).replace('_', ' ')); - columns.push({ name: name, desc: desc }); - }); - return columns; - }, - - getRecords: function(type) { - return this.get('store').all(type); - }, - - getRecordColumnValues: function(record) { - var self = this, count = 0, - columnValues = { id: get(record, 'id') }; - - record.eachAttribute(function(key) { - if (count++ > self.attributeLimit) { - return false; - } - var value = get(record, key); - columnValues[key] = value; - }); - return columnValues; - }, - - getRecordKeywords: function(record) { - var keywords = [], keys = Ember.A(['id']); - record.eachAttribute(function(key) { - keys.push(key); - }); - keys.forEach(function(key) { - keywords.push(get(record, key)); - }); - return keywords; - }, - - getRecordFilterValues: function(record) { - return { - isNew: record.get('isNew'), - isModified: record.get('isDirty') && !record.get('isNew'), - isClean: !record.get('isDirty') - }; - }, - - getRecordColor: function(record) { - var color = 'black'; - if (record.get('isNew')) { - color = 'green'; - } else if (record.get('isDirty')) { - color = 'blue'; - } - return color; - }, - - observeRecord: function(record, recordUpdated) { - var releaseMethods = Ember.A(), self = this, - keysToObserve = Ember.A(['id', 'isNew', 'isDirty']); - - record.eachAttribute(function(key) { - keysToObserve.push(key); - }); - - keysToObserve.forEach(function(key) { - var handler = function() { - recordUpdated(self.wrapRecord(record)); - }; - Ember.addObserver(record, key, handler); - releaseMethods.push(function() { - Ember.removeObserver(record, key, handler); - }); - }); - - var release = function() { - releaseMethods.forEach(function(fn) { fn(); } ); - }; - - return release; - } - -}); - -})(); - - - -(function() { -/** - The `DS.Transform` class is used to serialize and deserialize model - attributes when they are saved or loaded from an - adapter. Subclassing `DS.Transform` is useful for creating custom - attributes. All subclasses of `DS.Transform` must implement a - `serialize` and a `deserialize` method. - - Example - - ```javascript - App.RawTransform = DS.Transform.extend({ - deserialize: function(serialized) { - return serialized; - }, - serialize: function(deserialized) { - return deserialized; - } - }); - ``` - - Usage - - ```javascript - var attr = DS.attr; - App.Requirement = DS.Model.extend({ - name: attr('string'), - optionsArray: attr('raw') - }); - ``` - - @class Transform - @namespace DS - */ -DS.Transform = Ember.Object.extend({ - /** - When given a deserialized value from a record attribute this - method must return the serialized value. - - Example - - ```javascript - serialize: function(deserialized) { - return Ember.isEmpty(deserialized) ? null : Number(deserialized); - } - ``` - - @method serialize - @param deserialized The deserialized value - @return The serialized value - */ - serialize: Ember.required(), - - /** - When given a serialize value from a JSON object this method must - return the deserialized value for the record attribute. - - Example - - ```javascript - deserialize: function(serialized) { - return empty(serialized) ? null : Number(serialized); - } - ``` - - @method deserialize - @param serialized The serialized value - @return The deserialized value - */ - deserialize: Ember.required() - -}); - -})(); - - - -(function() { - -/** - The `DS.BooleanTransform` class is used to serialize and deserialize - boolean attributes on Ember Data record objects. This transform is - used when `boolean` is passed as the type parameter to the - [DS.attr](../../data#method_attr) function. - - Usage - - ```javascript - var attr = DS.attr; - App.User = DS.Model.extend({ - isAdmin: attr('boolean'), - name: attr('string'), - email: attr('string') - }); - ``` - - @class BooleanTransform - @extends DS.Transform - @namespace DS - */ -DS.BooleanTransform = DS.Transform.extend({ - deserialize: function(serialized) { - var type = typeof serialized; - - if (type === "boolean") { - return serialized; - } else if (type === "string") { - return serialized.match(/^true$|^t$|^1$/i) !== null; - } else if (type === "number") { - return serialized === 1; - } else { - return false; - } - }, - - serialize: function(deserialized) { - return Boolean(deserialized); - } -}); - -})(); - - - -(function() { -/** - The `DS.DateTransform` class is used to serialize and deserialize - date attributes on Ember Data record objects. This transform is used - when `date` is passed as the type parameter to the - [DS.attr](../../data#method_attr) function. - - ```javascript - var attr = DS.attr; - App.Score = DS.Model.extend({ - value: attr('number'), - player: DS.belongsTo('player'), - date: attr('date') - }); - ``` - - @class DateTransform - @extends DS.Transform - @namespace DS - */ -DS.DateTransform = DS.Transform.extend({ - - deserialize: function(serialized) { - var type = typeof serialized; - - if (type === "string") { - return new Date(Ember.Date.parse(serialized)); - } else if (type === "number") { - return new Date(serialized); - } else if (serialized === null || serialized === undefined) { - // if the value is not present in the data, - // return undefined, not null. - return serialized; - } else { - return null; - } - }, - - serialize: function(date) { - if (date instanceof Date) { - var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - - var pad = function(num) { - return num < 10 ? "0"+num : ""+num; - }; - - var utcYear = date.getUTCFullYear(), - utcMonth = date.getUTCMonth(), - utcDayOfMonth = date.getUTCDate(), - utcDay = date.getUTCDay(), - utcHours = date.getUTCHours(), - utcMinutes = date.getUTCMinutes(), - utcSeconds = date.getUTCSeconds(); - - - var dayOfWeek = days[utcDay]; - var dayOfMonth = pad(utcDayOfMonth); - var month = months[utcMonth]; - - return dayOfWeek + ", " + dayOfMonth + " " + month + " " + utcYear + " " + - pad(utcHours) + ":" + pad(utcMinutes) + ":" + pad(utcSeconds) + " GMT"; - } else { - return null; - } - } - -}); - -})(); - - - -(function() { -var empty = Ember.isEmpty; -/** - The `DS.NumberTransform` class is used to serialize and deserialize - numeric attributes on Ember Data record objects. This transform is - used when `number` is passed as the type parameter to the - [DS.attr](../../data#method_attr) function. - - Usage - - ```javascript - var attr = DS.attr; - App.Score = DS.Model.extend({ - value: attr('number'), - player: DS.belongsTo('player'), - date: attr('date') - }); - ``` - - @class NumberTransform - @extends DS.Transform - @namespace DS - */ -DS.NumberTransform = DS.Transform.extend({ - - deserialize: function(serialized) { - return empty(serialized) ? null : Number(serialized); - }, - - serialize: function(deserialized) { - return empty(deserialized) ? null : Number(deserialized); - } -}); - -})(); - - - -(function() { -var none = Ember.isNone; - -/** - The `DS.StringTransform` class is used to serialize and deserialize - string attributes on Ember Data record objects. This transform is - used when `string` is passed as the type parameter to the - [DS.attr](../../data#method_attr) function. - - Usage - - ```javascript - var attr = DS.attr; - App.User = DS.Model.extend({ - isAdmin: attr('boolean'), - name: attr('string'), - email: attr('string') - }); - ``` - - @class StringTransform - @extends DS.Transform - @namespace DS - */ -DS.StringTransform = DS.Transform.extend({ - - deserialize: function(serialized) { - return none(serialized) ? null : String(serialized); - }, - - serialize: function(deserialized) { - return none(deserialized) ? null : String(deserialized); - } - -}); - -})(); - - - -(function() { - -})(); - - - -(function() { -/** - @module ember-data -*/ - -var set = Ember.set; - -/* - This code registers an injection for Ember.Application. - - If an Ember.js developer defines a subclass of DS.Store on their application, - this code will automatically instantiate it and make it available on the - router. - - Additionally, after an application's controllers have been injected, they will - each have the store made available to them. - - For example, imagine an Ember.js application with the following classes: - - App.Store = DS.Store.extend({ - adapter: 'custom' - }); - - App.PostsController = Ember.ArrayController.extend({ - // ... - }); - - When the application is initialized, `App.Store` will automatically be - instantiated, and the instance of `App.PostsController` will have its `store` - property set to that instance. - - Note that this code will only be run if the `ember-application` package is - loaded. If Ember Data is being used in an environment other than a - typical application (e.g., node.js where only `ember-runtime` is available), - this code will be ignored. -*/ - -Ember.onLoad('Ember.Application', function(Application) { - Application.initializer({ - name: "store", - - initialize: function(container, application) { - application.register('store:main', application.Store || DS.Store); - application.register('serializer:_default', DS.JSONSerializer); - application.register('serializer:_rest', DS.RESTSerializer); - application.register('adapter:_rest', DS.RESTAdapter); - - // Eagerly generate the store so defaultStore is populated. - // TODO: Do this in a finisher hook - container.lookup('store:main'); - } - }); - - Application.initializer({ - name: "transforms", - before: "store", - - initialize: function(container, application) { - application.register('transform:boolean', DS.BooleanTransform); - application.register('transform:date', DS.DateTransform); - application.register('transform:number', DS.NumberTransform); - application.register('transform:string', DS.StringTransform); - } - }); - - Application.initializer({ - name: "dataAdapter", - before: "store", - - initialize: function(container, application) { - application.register('dataAdapter:main', DS.DebugAdapter); - } - }); - - Application.initializer({ - name: "injectStore", - before: "store", - - initialize: function(container, application) { - application.inject('controller', 'store', 'store:main'); - application.inject('route', 'store', 'store:main'); - application.inject('serializer', 'store', 'store:main'); - application.inject('dataAdapter', 'store', 'store:main'); - } - }); - -}); - -})(); - - - -(function() { -/** - @module ember-data -*/ - -/** - Date.parse with progressive enhancement for ISO 8601 - - © 2011 Colin Snover - - Released under MIT license. - - @class Date - @namespace Ember - @static -*/ -Ember.Date = Ember.Date || {}; - -var origParse = Date.parse, numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ]; - -/** - @method parse - @param date -*/ -Ember.Date.parse = function (date) { - var timestamp, struct, minutesOffset = 0; - - // ES5 §15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string - // before falling back to any implementation-specific date parsing, so that’s what we do, even if native - // implementations could be faster - // 1 YYYY 2 MM 3 DD 4 HH 5 mm 6 ss 7 msec 8 Z 9 ± 10 tzHH 11 tzmm - if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date))) { - // avoid NaN timestamps caused by “undefined†values being passed to Date.UTC - for (var i = 0, k; (k = numericKeys[i]); ++i) { - struct[k] = +struct[k] || 0; - } - - // allow undefined days and months - struct[2] = (+struct[2] || 1) - 1; - struct[3] = +struct[3] || 1; - - if (struct[8] !== 'Z' && struct[9] !== undefined) { - minutesOffset = struct[10] * 60 + struct[11]; - - if (struct[9] === '+') { - minutesOffset = 0 - minutesOffset; - } - } - - timestamp = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]); - } - else { - timestamp = origParse ? origParse(date) : NaN; - } - - return timestamp; -}; - -if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Date) { - Date.parse = Ember.Date.parse; -} - -})(); - - - -(function() { - -})(); - - - -(function() { -/** - @module ember-data -*/ - -var get = Ember.get, set = Ember.set; - -/** - A record array is an array that contains records of a certain type. The record - array materializes records as needed when they are retrieved for the first - time. You should not create record arrays yourself. Instead, an instance of - `DS.RecordArray` or its subclasses will be returned by your application's store - in response to queries. - - @class RecordArray - @namespace DS - @extends Ember.ArrayProxy - @uses Ember.Evented -*/ - -DS.RecordArray = Ember.ArrayProxy.extend(Ember.Evented, { - /** - The model type contained by this record array. - - @property type - @type DS.Model - */ - type: null, - - /** - The array of client ids backing the record array. When a - record is requested from the record array, the record - for the client id at the same index is materialized, if - necessary, by the store. - - @property content - @private - @type Ember.Array - */ - content: null, - - /** - The flag to signal a `RecordArray` is currently loading data. - - Example - - ```javascript - var people = store.all(App.Person); - people.get('isLoaded'); // true - ``` - - @property isLoaded - @type Boolean - */ - isLoaded: false, - /** - The flag to signal a `RecordArray` is currently loading data. - - Example - - ```javascript - var people = store.all(App.Person); - people.get('isUpdating'); // false - people.update(); - people.get('isUpdating'); // true - ``` - - @property isUpdating - @type Boolean - */ - isUpdating: false, - - /** - The store that created this record array. - - @property store - @private - @type DS.Store - */ - store: null, - - /** - Retrieves an object from the content by index. - - @method objectAtContent - @private - @param {Number} index - @return {DS.Model} record - */ - objectAtContent: function(index) { - var content = get(this, 'content'); - - return content.objectAt(index); - }, - - /** - Used to get the latest version of all of the records in this array - from the adapter. - - Example - - ```javascript - var people = store.all(App.Person); - people.get('isUpdating'); // false - people.update(); - people.get('isUpdating'); // true - ``` - - @method update - */ - update: function() { - if (get(this, 'isUpdating')) { return; } - - var store = get(this, 'store'), - type = get(this, 'type'); - - store.fetchAll(type, this); - }, - - /** - Adds a record to the `RecordArray`. - - @method addRecord - @private - @param {DS.Model} record - */ - addRecord: function(record) { - get(this, 'content').addObject(record); - }, - - /** - Removes a record to the `RecordArray`. - - @method removeRecord - @private - @param {DS.Model} record - */ - removeRecord: function(record) { - get(this, 'content').removeObject(record); - }, - - /** - Saves all of the records in the `RecordArray`. - - Example - - ```javascript - var messages = store.all(App.Message); - messages.forEach(function(message) { - message.set('hasBeenSeen', true); - }); - messages.save(); - ``` - - @method save - @return {DS.PromiseArray} promise - */ - save: function() { - var promiseLabel = "DS: RecordArray#save " + get(this, 'type'); - var promise = Ember.RSVP.all(this.invoke("save"), promiseLabel).then(function(array) { - return Ember.A(array); - }, null, "DS: RecordArray#save apply Ember.NativeArray"); - - return DS.PromiseArray.create({ promise: promise }); - } -}); - -})(); - - - -(function() { -/** - @module ember-data -*/ - -var get = Ember.get; - -/** - Represents a list of records whose membership is determined by the - store. As records are created, loaded, or modified, the store - evaluates them to determine if they should be part of the record - array. - - @class FilteredRecordArray - @namespace DS - @extends DS.RecordArray -*/ -DS.FilteredRecordArray = DS.RecordArray.extend({ - /** - The filterFunction is a function used to test records from the store to - determine if they should be part of the record array. - - Example - - ```javascript - var allPeople = store.all('person'); - allPeople.mapBy('name'); // ["Tom Dale", "Yehuda Katz", "Trek Glowacki"] - - var people = store.filter('person', function(person) { - if (person.get('name').match(/Katz$/)) { return true; } - }); - people.mapBy('name'); // ["Yehuda Katz"] - - var notKatzFilter = function(person) { - return !person.get('name').match(/Katz$/); - }; - people.set('filterFunction', notKatzFilter); - people.mapBy('name'); // ["Tom Dale", "Trek Glowacki"] - ``` - - @method filterFunction - @param {DS.Model} record - @return {Boolean} `true` if the record should be in the array - */ - filterFunction: null, - isLoaded: true, - - replace: function() { - var type = get(this, 'type').toString(); - throw new Error("The result of a client-side filter (on " + type + ") is immutable."); - }, - - /** - @method updateFilter - @private - */ - updateFilter: Ember.observer(function() { - var manager = get(this, 'manager'); - manager.updateFilter(this, get(this, 'type'), get(this, 'filterFunction')); - }, 'filterFunction') -}); - -})(); - - - -(function() { -/** - @module ember-data -*/ - -var get = Ember.get, set = Ember.set; - -/** - Represents an ordered list of records whose order and membership is - determined by the adapter. For example, a query sent to the adapter - may trigger a search on the server, whose results would be loaded - into an instance of the `AdapterPopulatedRecordArray`. - - @class AdapterPopulatedRecordArray - @namespace DS - @extends DS.RecordArray -*/ -DS.AdapterPopulatedRecordArray = DS.RecordArray.extend({ - query: null, - - replace: function() { - var type = get(this, 'type').toString(); - throw new Error("The result of a server query (on " + type + ") is immutable."); - }, - - /** - @method load - @private - @param {Array} data - */ - load: function(data) { - var store = get(this, 'store'), - type = get(this, 'type'), - records = store.pushMany(type, data), - meta = store.metadataFor(type); - - this.setProperties({ - content: Ember.A(records), - isLoaded: true, - meta: meta - }); - - // TODO: does triggering didLoad event should be the last action of the runLoop? - Ember.run.once(this, 'trigger', 'didLoad'); - } -}); - -})(); - - - -(function() { -/** - @module ember-data -*/ - -var get = Ember.get, set = Ember.set; -var map = Ember.EnumerableUtils.map; - -/** - A `ManyArray` is a `RecordArray` that represents the contents of a has-many - relationship. - - The `ManyArray` is instantiated lazily the first time the relationship is - requested. - - ### Inverses - - Often, the relationships in Ember Data applications will have - an inverse. For example, imagine the following models are - defined: - - ```javascript - App.Post = DS.Model.extend({ - comments: DS.hasMany('comment') - }); - - App.Comment = DS.Model.extend({ - post: DS.belongsTo('post') - }); - ``` - - If you created a new instance of `App.Post` and added - a `App.Comment` record to its `comments` has-many - relationship, you would expect the comment's `post` - property to be set to the post that contained - the has-many. - - We call the record to which a relationship belongs the - relationship's _owner_. - - @class ManyArray - @namespace DS - @extends DS.RecordArray -*/ -DS.ManyArray = DS.RecordArray.extend({ - init: function() { - this._super.apply(this, arguments); - this._changesToSync = Ember.OrderedSet.create(); - }, - - /** - The property name of the relationship - - @property {String} name - @private - */ - name: null, - - /** - The record to which this relationship belongs. - - @property {DS.Model} owner - @private - */ - owner: null, - - /** - `true` if the relationship is polymorphic, `false` otherwise. - - @property {Boolean} isPolymorphic - @private - */ - isPolymorphic: false, - - // LOADING STATE - - isLoaded: false, - - /** - Used for async `hasMany` arrays - to keep track of when they will resolve. - - @property {Ember.RSVP.Promise} promise - @private - */ - promise: null, - - /** - @method loadingRecordsCount - @param {Number} count - @private - */ - loadingRecordsCount: function(count) { - this.loadingRecordsCount = count; - }, - - /** - @method loadedRecord - @private - */ - loadedRecord: function() { - this.loadingRecordsCount--; - if (this.loadingRecordsCount === 0) { - set(this, 'isLoaded', true); - this.trigger('didLoad'); - } - }, - - /** - @method fetch - @private - */ - fetch: function() { - var records = get(this, 'content'), - store = get(this, 'store'), - owner = get(this, 'owner'), - resolver = Ember.RSVP.defer("DS: ManyArray#fetch " + get(this, 'type')); - - var unloadedRecords = records.filterProperty('isEmpty', true); - store.fetchMany(unloadedRecords, owner, resolver); - }, - - // Overrides Ember.Array's replace method to implement - replaceContent: function(index, removed, added) { - // Map the array of record objects into an array of client ids. - added = map(added, function(record) { - Ember.assert("You cannot add '" + record.constructor.typeKey + "' records to this relationship (only '" + this.type.typeKey + "' allowed)", !this.type || record instanceof this.type); - return record; - }, this); - - this._super(index, removed, added); - }, - - arrangedContentDidChange: function() { - Ember.run.once(this, 'fetch'); - }, - - arrayContentWillChange: function(index, removed, added) { - var owner = get(this, 'owner'), - name = get(this, 'name'); - - if (!owner._suspendedRelationships) { - // This code is the first half of code that continues inside - // of arrayContentDidChange. It gets or creates a change from - // the child object, adds the current owner as the old - // parent if this is the first time the object was removed - // from a ManyArray, and sets `newParent` to null. - // - // Later, if the object is added to another ManyArray, - // the `arrayContentDidChange` will set `newParent` on - // the change. - for (var i=index; i "root.created.uncommitted" - ``` - - The hierarchy of valid states that ship with ember data looks like - this: - - ```text - * root - * deleted - * saved - * uncommitted - * inFlight - * empty - * loaded - * created - * uncommitted - * inFlight - * saved - * updated - * uncommitted - * inFlight - * loading - ``` - - The `DS.Model` states are themselves stateless. What we mean is - that, the hierarchical states that each of *those* points to is a - shared data structure. For performance reasons, instead of each - record getting its own copy of the hierarchy of states, each record - points to this global, immutable shared instance. How does a state - know which record it should be acting on? We pass the record - instance into the state's event handlers as the first argument. - - The record passed as the first parameter is where you should stash - state about the record if needed; you should never store data on the state - object itself. - - ### Events and Flags - - A state may implement zero or more events and flags. - - #### Events - - Events are named functions that are invoked when sent to a record. The - record will first look for a method with the given name on the - current state. If no method is found, it will search the current - state's parent, and then its grandparent, and so on until reaching - the top of the hierarchy. If the root is reached without an event - handler being found, an exception will be raised. This can be very - helpful when debugging new features. - - Here's an example implementation of a state with a `myEvent` event handler: - - ```javascript - aState: DS.State.create({ - myEvent: function(manager, param) { - console.log("Received myEvent with", param); - } - }) - ``` - - To trigger this event: - - ```javascript - record.send('myEvent', 'foo'); - //=> "Received myEvent with foo" - ``` - - Note that an optional parameter can be sent to a record's `send()` method, - which will be passed as the second parameter to the event handler. - - Events should transition to a different state if appropriate. This can be - done by calling the record's `transitionTo()` method with a path to the - desired state. The state manager will attempt to resolve the state path - relative to the current state. If no state is found at that path, it will - attempt to resolve it relative to the current state's parent, and then its - parent, and so on until the root is reached. For example, imagine a hierarchy - like this: - - * created - * uncommitted <-- currentState - * inFlight - * updated - * inFlight - - If we are currently in the `uncommitted` state, calling - `transitionTo('inFlight')` would transition to the `created.inFlight` state, - while calling `transitionTo('updated.inFlight')` would transition to - the `updated.inFlight` state. - - Remember that *only events* should ever cause a state transition. You should - never call `transitionTo()` from outside a state's event handler. If you are - tempted to do so, create a new event and send that to the state manager. - - #### Flags - - Flags are Boolean values that can be used to introspect a record's current - state in a more user-friendly way than examining its state path. For example, - instead of doing this: - - ```javascript - var statePath = record.get('stateManager.currentPath'); - if (statePath === 'created.inFlight') { - doSomething(); - } - ``` - - You can say: - - ```javascript - if (record.get('isNew') && record.get('isSaving')) { - doSomething(); - } - ``` - - If your state does not set a value for a given flag, the value will - be inherited from its parent (or the first place in the state hierarchy - where it is defined). - - The current set of flags are defined below. If you want to add a new flag, - in addition to the area below, you will also need to declare it in the - `DS.Model` class. - - - * [isEmpty](DS.Model.html#property_isEmpty) - * [isLoading](DS.Model.html#property_isLoading) - * [isLoaded](DS.Model.html#property_isLoaded) - * [isDirty](DS.Model.html#property_isDirty) - * [isSaving](DS.Model.html#property_isSaving) - * [isDeleted](DS.Model.html#property_isDeleted) - * [isNew](DS.Model.html#property_isNew) - * [isValid](DS.Model.html#property_isValid) - - @namespace DS - @class RootState -*/ - -var hasDefinedProperties = function(object) { - // Ignore internal property defined by simulated `Ember.create`. - var names = Ember.keys(object); - var i, l, name; - for (i = 0, l = names.length; i < l; i++ ) { - name = names[i]; - if (object.hasOwnProperty(name) && object[name]) { return true; } - } - - return false; -}; - -var didSetProperty = function(record, context) { - if (context.value === context.originalValue) { - delete record._attributes[context.name]; - record.send('propertyWasReset', context.name); - } else if (context.value !== context.oldValue) { - record.send('becomeDirty'); - } - - record.updateRecordArraysLater(); -}; - -// Implementation notes: -// -// Each state has a boolean value for all of the following flags: -// -// * isLoaded: The record has a populated `data` property. When a -// record is loaded via `store.find`, `isLoaded` is false -// until the adapter sets it. When a record is created locally, -// its `isLoaded` property is always true. -// * isDirty: The record has local changes that have not yet been -// saved by the adapter. This includes records that have been -// created (but not yet saved) or deleted. -// * isSaving: The record has been committed, but -// the adapter has not yet acknowledged that the changes have -// been persisted to the backend. -// * isDeleted: The record was marked for deletion. When `isDeleted` -// is true and `isDirty` is true, the record is deleted locally -// but the deletion was not yet persisted. When `isSaving` is -// true, the change is in-flight. When both `isDirty` and -// `isSaving` are false, the change has persisted. -// * isError: The adapter reported that it was unable to save -// local changes to the backend. This may also result in the -// record having its `isValid` property become false if the -// adapter reported that server-side validations failed. -// * isNew: The record was created on the client and the adapter -// did not yet report that it was successfully saved. -// * isValid: No client-side validations have failed and the -// adapter did not report any server-side validation failures. - -// The dirty state is a abstract state whose functionality is -// shared between the `created` and `updated` states. -// -// The deleted state shares the `isDirty` flag with the -// subclasses of `DirtyState`, but with a very different -// implementation. -// -// Dirty states have three child states: -// -// `uncommitted`: the store has not yet handed off the record -// to be saved. -// `inFlight`: the store has handed off the record to be saved, -// but the adapter has not yet acknowledged success. -// `invalid`: the record has invalid information and cannot be -// send to the adapter yet. -var DirtyState = { - initialState: 'uncommitted', - - // FLAGS - isDirty: true, - - // SUBSTATES - - // When a record first becomes dirty, it is `uncommitted`. - // This means that there are local pending changes, but they - // have not yet begun to be saved, and are not invalid. - uncommitted: { - // EVENTS - didSetProperty: didSetProperty, - - propertyWasReset: function(record, name) { - var stillDirty = false; - - for (var prop in record._attributes) { - stillDirty = true; - break; - } - - if (!stillDirty) { record.send('rolledBack'); } - }, - - pushedData: Ember.K, - - becomeDirty: Ember.K, - - willCommit: function(record) { - record.transitionTo('inFlight'); - }, - - reloadRecord: function(record, resolve) { - resolve(get(record, 'store').reloadRecord(record)); - }, - - rolledBack: function(record) { - record.transitionTo('loaded.saved'); - }, - - becameInvalid: function(record) { - record.transitionTo('invalid'); - }, - - rollback: function(record) { - record.rollback(); - } - }, - - // Once a record has been handed off to the adapter to be - // saved, it is in the 'in flight' state. Changes to the - // record cannot be made during this window. - inFlight: { - // FLAGS - isSaving: true, - - // EVENTS - didSetProperty: didSetProperty, - becomeDirty: Ember.K, - pushedData: Ember.K, - - // TODO: More robust semantics around save-while-in-flight - willCommit: Ember.K, - - didCommit: function(record) { - var dirtyType = get(this, 'dirtyType'); - - record.transitionTo('saved'); - record.send('invokeLifecycleCallbacks', dirtyType); - }, - - becameInvalid: function(record) { - record.transitionTo('invalid'); - record.send('invokeLifecycleCallbacks'); - }, - - becameError: function(record) { - record.transitionTo('uncommitted'); - record.triggerLater('becameError', record); - } - }, - - // A record is in the `invalid` state when its client-side - // invalidations have failed, or if the adapter has indicated - // the the record failed server-side invalidations. - invalid: { - // FLAGS - isValid: false, - - // EVENTS - deleteRecord: function(record) { - record.transitionTo('deleted.uncommitted'); - record.clearRelationships(); - }, - - didSetProperty: function(record, context) { - get(record, 'errors').remove(context.name); - - didSetProperty(record, context); - }, - - becomeDirty: Ember.K, - - rolledBack: function(record) { - get(record, 'errors').clear(); - }, - - becameValid: function(record) { - record.transitionTo('uncommitted'); - }, - - invokeLifecycleCallbacks: function(record) { - record.triggerLater('becameInvalid', record); - } - } -}; - -// The created and updated states are created outside the state -// chart so we can reopen their substates and add mixins as -// necessary. - -function deepClone(object) { - var clone = {}, value; - - for (var prop in object) { - value = object[prop]; - if (value && typeof value === 'object') { - clone[prop] = deepClone(value); - } else { - clone[prop] = value; - } - } - - return clone; -} - -function mixin(original, hash) { - for (var prop in hash) { - original[prop] = hash[prop]; - } - - return original; -} - -function dirtyState(options) { - var newState = deepClone(DirtyState); - return mixin(newState, options); -} - -var createdState = dirtyState({ - dirtyType: 'created', - - // FLAGS - isNew: true -}); - -createdState.uncommitted.rolledBack = function(record) { - record.transitionTo('deleted.saved'); -}; - -var updatedState = dirtyState({ - dirtyType: 'updated' -}); - -createdState.uncommitted.deleteRecord = function(record) { - record.clearRelationships(); - record.transitionTo('deleted.saved'); -}; - -createdState.uncommitted.rollback = function(record) { - DirtyState.uncommitted.rollback.apply(this, arguments); - record.transitionTo('deleted.saved'); -}; - -updatedState.uncommitted.deleteRecord = function(record) { - record.transitionTo('deleted.uncommitted'); - record.clearRelationships(); -}; - -var RootState = { - // FLAGS - isEmpty: false, - isLoading: false, - isLoaded: false, - isDirty: false, - isSaving: false, - isDeleted: false, - isNew: false, - isValid: true, - - // DEFAULT EVENTS - - // Trying to roll back if you're not in the dirty state - // doesn't change your state. For example, if you're in the - // in-flight state, rolling back the record doesn't move - // you out of the in-flight state. - rolledBack: Ember.K, - - propertyWasReset: Ember.K, - - // SUBSTATES - - // A record begins its lifecycle in the `empty` state. - // If its data will come from the adapter, it will - // transition into the `loading` state. Otherwise, if - // the record is being created on the client, it will - // transition into the `created` state. - empty: { - isEmpty: true, - - // EVENTS - loadingData: function(record, promise) { - record._loadingPromise = promise; - record.transitionTo('loading'); - }, - - loadedData: function(record) { - record.transitionTo('loaded.created.uncommitted'); - - record.suspendRelationshipObservers(function() { - record.notifyPropertyChange('data'); - }); - }, - - pushedData: function(record) { - record.transitionTo('loaded.saved'); - record.triggerLater('didLoad'); - } - }, - - // A record enters this state when the store askes - // the adapter for its data. It remains in this state - // until the adapter provides the requested data. - // - // Usually, this process is asynchronous, using an - // XHR to retrieve the data. - loading: { - // FLAGS - isLoading: true, - - exit: function(record) { - record._loadingPromise = null; - }, - - // EVENTS - pushedData: function(record) { - record.transitionTo('loaded.saved'); - record.triggerLater('didLoad'); - set(record, 'isError', false); - }, - - becameError: function(record) { - record.triggerLater('becameError', record); - }, - - notFound: function(record) { - record.transitionTo('empty'); - } - }, - - // A record enters this state when its data is populated. - // Most of a record's lifecycle is spent inside substates - // of the `loaded` state. - loaded: { - initialState: 'saved', - - // FLAGS - isLoaded: true, - - // SUBSTATES - - // If there are no local changes to a record, it remains - // in the `saved` state. - saved: { - setup: function(record) { - var attrs = record._attributes, - isDirty = false; - - for (var prop in attrs) { - if (attrs.hasOwnProperty(prop)) { - isDirty = true; - break; - } - } - - if (isDirty) { - record.adapterDidDirty(); - } - }, - - // EVENTS - didSetProperty: didSetProperty, - - pushedData: Ember.K, - - becomeDirty: function(record) { - record.transitionTo('updated.uncommitted'); - }, - - willCommit: function(record) { - record.transitionTo('updated.inFlight'); - }, - - reloadRecord: function(record, resolve) { - resolve(get(record, 'store').reloadRecord(record)); - }, - - deleteRecord: function(record) { - record.transitionTo('deleted.uncommitted'); - record.clearRelationships(); - }, - - unloadRecord: function(record) { - // clear relationships before moving to deleted state - // otherwise it fails - record.clearRelationships(); - record.transitionTo('deleted.saved'); - }, - - didCommit: function(record) { - record.send('invokeLifecycleCallbacks', get(record, 'lastDirtyType')); - }, - - // loaded.saved.notFound would be triggered by a failed - // `reload()` on an unchanged record - notFound: Ember.K - - }, - - // A record is in this state after it has been locally - // created but before the adapter has indicated that - // it has been saved. - created: createdState, - - // A record is in this state if it has already been - // saved to the server, but there are new local changes - // that have not yet been saved. - updated: updatedState - }, - - // A record is in this state if it was deleted from the store. - deleted: { - initialState: 'uncommitted', - dirtyType: 'deleted', - - // FLAGS - isDeleted: true, - isLoaded: true, - isDirty: true, - - // TRANSITIONS - setup: function(record) { - record.updateRecordArrays(); - }, - - // SUBSTATES - - // When a record is deleted, it enters the `start` - // state. It will exit this state when the record - // starts to commit. - uncommitted: { - - // EVENTS - - willCommit: function(record) { - record.transitionTo('inFlight'); - }, - - rollback: function(record) { - record.rollback(); - }, - - becomeDirty: Ember.K, - deleteRecord: Ember.K, - - rolledBack: function(record) { - record.transitionTo('loaded.saved'); - } - }, - - // After a record starts committing, but - // before the adapter indicates that the deletion - // has saved to the server, a record is in the - // `inFlight` substate of `deleted`. - inFlight: { - // FLAGS - isSaving: true, - - // EVENTS - - // TODO: More robust semantics around save-while-in-flight - willCommit: Ember.K, - didCommit: function(record) { - record.transitionTo('saved'); - - record.send('invokeLifecycleCallbacks'); - }, - - becameError: function(record) { - record.transitionTo('uncommitted'); - record.triggerLater('becameError', record); - } - }, - - // Once the adapter indicates that the deletion has - // been saved, the record enters the `saved` substate - // of `deleted`. - saved: { - // FLAGS - isDirty: false, - - setup: function(record) { - var store = get(record, 'store'); - store.dematerializeRecord(record); - }, - - invokeLifecycleCallbacks: function(record) { - record.triggerLater('didDelete', record); - record.triggerLater('didCommit', record); - } - } - }, - - invokeLifecycleCallbacks: function(record, dirtyType) { - if (dirtyType === 'created') { - record.triggerLater('didCreate', record); - } else { - record.triggerLater('didUpdate', record); - } - - record.triggerLater('didCommit', record); - } -}; - -function wireState(object, parent, name) { - /*jshint proto:true*/ - // TODO: Use Object.create and copy instead - object = mixin(parent ? Ember.create(parent) : {}, object); - object.parentState = parent; - object.stateName = name; - - for (var prop in object) { - if (!object.hasOwnProperty(prop) || prop === 'parentState' || prop === 'stateName') { continue; } - if (typeof object[prop] === 'object') { - object[prop] = wireState(object[prop], object, name + "." + prop); - } - } - - return object; -} - -RootState = wireState(RootState, null, "root"); - -DS.RootState = RootState; - -})(); - - - -(function() { -var get = Ember.get, isEmpty = Ember.isEmpty; - -/** -@module ember-data -*/ - -/** - Holds validation errors for a given record organized by attribute names. - - @class Errors - @namespace DS - @extends Ember.Object - @uses Ember.Enumerable - @uses Ember.Evented - */ -DS.Errors = Ember.Object.extend(Ember.Enumerable, Ember.Evented, { - /** - Register with target handler - - @method registerHandlers - @param {Object} target - @param {Function} becameInvalid - @param {Function} becameValid - */ - registerHandlers: function(target, becameInvalid, becameValid) { - this.on('becameInvalid', target, becameInvalid); - this.on('becameValid', target, becameValid); - }, - - /** - @property errorsByAttributeName - @type {Ember.MapWithDefault} - @private - */ - errorsByAttributeName: Ember.reduceComputed("content", { - initialValue: function() { - return Ember.MapWithDefault.create({ - defaultValue: function() { - return Ember.A(); - } - }); - }, - - addedItem: function(errors, error) { - errors.get(error.attribute).pushObject(error); - - return errors; - }, - - removedItem: function(errors, error) { - errors.get(error.attribute).removeObject(error); - - return errors; - } - }), - - /** - Returns errors for a given attribute - - @method errorsFor - @param {String} attribute - @returns {Array} - */ - errorsFor: function(attribute) { - return get(this, 'errorsByAttributeName').get(attribute); - }, - - /** - */ - messages: Ember.computed.mapBy('content', 'message'), - - /** - @property content - @type {Array} - @private - */ - content: Ember.computed(function() { - return Ember.A(); - }), - - /** - @method unknownProperty - @private - */ - unknownProperty: function(attribute) { - var errors = this.errorsFor(attribute); - if (isEmpty(errors)) { return null; } - return errors; - }, - - /** - @method nextObject - @private - */ - nextObject: function(index, previousObject, context) { - return get(this, 'content').objectAt(index); - }, - - /** - Total number of errors. - - @property length - @type {Number} - @readOnly - */ - length: Ember.computed.oneWay('content.length').readOnly(), - - /** - @property isEmpty - @type {Boolean} - @readOnly - */ - isEmpty: Ember.computed.not('length').readOnly(), - - /** - Adds error messages to a given attribute and sends - `becameInvalid` event to the record. - - @method add - @param {String} attribute - @param {Array|String} messages - */ - add: function(attribute, messages) { - var wasEmpty = get(this, 'isEmpty'); - - messages = this._findOrCreateMessages(attribute, messages); - get(this, 'content').addObjects(messages); - - this.notifyPropertyChange(attribute); - this.enumerableContentDidChange(); - - if (wasEmpty && !get(this, 'isEmpty')) { - this.trigger('becameInvalid'); - } - }, - - /** - @method _findOrCreateMessages - @private - */ - _findOrCreateMessages: function(attribute, messages) { - var errors = this.errorsFor(attribute); - - return Ember.makeArray(messages).map(function(message) { - return errors.findBy('message', message) || { - attribute: attribute, - message: message - }; - }); - }, - - /** - Removes all error messages from the given attribute and sends - `becameValid` event to the record if there no more errors left. - - @method remove - @param {String} attribute - */ - remove: function(attribute) { - if (get(this, 'isEmpty')) { return; } - - var content = get(this, 'content').rejectBy('attribute', attribute); - get(this, 'content').setObjects(content); - - this.notifyPropertyChange(attribute); - this.enumerableContentDidChange(); - - if (get(this, 'isEmpty')) { - this.trigger('becameValid'); - } - }, - - /** - Removes all error messages and sends `becameValid` event - to the record. - - @method clear - */ - clear: function() { - if (get(this, 'isEmpty')) { return; } - - get(this, 'content').clear(); - this.enumerableContentDidChange(); - - this.trigger('becameValid'); - }, - - /** - Checks if there is error messages for the given attribute. - - @method has - @param {String} attribute - @returns {Boolean} true if there some errors on given attribute - */ - has: function(attribute) { - return !isEmpty(this.errorsFor(attribute)); - } -}); - -})(); - - - -(function() { -/** - @module ember-data -*/ - -var get = Ember.get, set = Ember.set, - merge = Ember.merge, once = Ember.run.once; - -var retrieveFromCurrentState = Ember.computed('currentState', function(key, value) { - return get(get(this, 'currentState'), key); -}).readOnly(); - -/** - - The model class that all Ember Data records descend from. - - @class Model - @namespace DS - @extends Ember.Object - @uses Ember.Evented -*/ -DS.Model = Ember.Object.extend(Ember.Evented, { - /** - If this property is `true` the record is in the `empty` - state. Empty is the first state all records enter after they have - been created. Most records created by the store will quickly - transition to the `loading` state if data needs to be fetched from - the server or the `created` state if the record is created on the - client. A record can also enter the empty state if the adapter is - unable to locate the record. - - @property isEmpty - @type {Boolean} - @readOnly - */ - isEmpty: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `loading` state. A - record enters this state when the store askes the adapter for its - data. It remains in this state until the adapter provides the - requested data. - - @property isLoading - @type {Boolean} - @readOnly - */ - isLoading: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `loaded` state. A - record enters this state when its data is populated. Most of a - record's lifecycle is spent inside substates of the `loaded` - state. - - Example - - ```javascript - var record = store.createRecord(App.Model); - record.get('isLoaded'); // true - - store.find('model', 1).then(function(model) { - model.get('isLoaded'); // true - }); - ``` - - @property isLoaded - @type {Boolean} - @readOnly - */ - isLoaded: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `dirty` state. The - record has local changes that have not yet been saved by the - adapter. This includes records that have been created (but not yet - saved) or deleted. - - Example - - ```javascript - var record = store.createRecord(App.Model); - record.get('isDirty'); // true - - store.find('model', 1).then(function(model) { - model.get('isDirty'); // false - model.set('foo', 'some value'); - model.set('isDirty'); // true - }); - ``` - - @property isDirty - @type {Boolean} - @readOnly - */ - isDirty: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `saving` state. A - record enters the saving state when `save` is called, but the - adapter has not yet acknowledged that the changes have been - persisted to the backend. - - Example - - ```javascript - var record = store.createRecord(App.Model); - record.get('isSaving'); // false - var promise = record.save(); - record.get('isSaving'); // true - promise.then(function() { - record.get('isSaving'); // false - }); - ``` - - @property isSaving - @type {Boolean} - @readOnly - */ - isSaving: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `deleted` state - and has been marked for deletion. When `isDeleted` is true and - `isDirty` is true, the record is deleted locally but the deletion - was not yet persisted. When `isSaving` is true, the change is - in-flight. When both `isDirty` and `isSaving` are false, the - change has persisted. - - Example - - ```javascript - var record = store.createRecord(App.Model); - record.get('isDeleted'); // false - record.deleteRecord(); - record.get('isDeleted'); // true - ``` - - @property isDeleted - @type {Boolean} - @readOnly - */ - isDeleted: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `new` state. A - record will be in the `new` state when it has been created on the - client and the adapter has not yet report that it was successfully - saved. - - Example - - ```javascript - var record = store.createRecord(App.Model); - record.get('isNew'); // true - - store.find('model', 1).then(function(model) { - model.get('isNew'); // false - }); - ``` - - @property isNew - @type {Boolean} - @readOnly - */ - isNew: retrieveFromCurrentState, - /** - If this property is `true` the record is in the `valid` state. A - record will be in the `valid` state when no client-side - validations have failed and the adapter did not report any - server-side validation failures. - - @property isValid - @type {Boolean} - @readOnly - */ - isValid: retrieveFromCurrentState, - /** - If the record is in the dirty state this property will report what - kind of change has caused it to move into the dirty - state. Possible values are: - - - `created` The record has been created by the client and not yet saved to the adapter. - - `updated` The record has been updated by the client and not yet saved to the adapter. - - `deleted` The record has been deleted by the client and not yet saved to the adapter. - - Example - - ```javascript - var record = store.createRecord(App.Model); - record.get('dirtyType'); // 'created' - ``` - - @property dirtyType - @type {String} - @readOnly - */ - dirtyType: retrieveFromCurrentState, - - /** - If `true` the adapter reported that it was unable to save local - changes to the backend. This may also result in the record having - its `isValid` property become false if the adapter reported that - server-side validations failed. - - Example - - ```javascript - record.get('isError'); // false - record.set('foo', 'invalid value'); - record.save().then(null, function() { - record.get('isError'); // true - }); - ``` - - @property isError - @type {Boolean} - @readOnly - */ - isError: false, - /** - If `true` the store is attempting to reload the record form the adapter. - - Example - - ```javascript - record.get('isReloading'); // false - record.reload(); - record.get('isReloading'); // true - ``` - - @property isReloading - @type {Boolean} - @readOnly - */ - isReloading: false, - - /** - The `clientId` property is a transient numerical identifier - generated at runtime by the data store. It is important - primarily because newly created objects may not yet have an - externally generated id. - - @property clientId - @private - @type {Number|String} - */ - clientId: null, - /** - All ember models have an id property. This is an identifier - managed by an external source. These are always coerced to be - strings before being used internally. Note when declaring the - attributes for a model it is an error to declare an id - attribute. - - ```javascript - var record = store.createRecord(App.Model); - record.get('id'); // null - - store.find('model', 1).then(function(model) { - model.get('id'); // '1' - }); - ``` - - @property id - @type {String} - */ - id: null, - transaction: null, - /** - @property currentState - @private - @type {Object} - */ - currentState: null, - /** - When the record is in the `invalid` state this object will contain - any errors returned by the adapter. When present the errors hash - typically contains keys coresponding to the invalid property names - and values which are an array of error messages. - - ```javascript - record.get('errors.length'); // 0 - record.set('foo', 'invalid value'); - record.save().then(null, function() { - record.get('errors').get('foo'); // ['foo should be a number.'] - }); - ``` - - @property errors - @type {Object} - */ - errors: null, - - /** - Create a JSON representation of the record, using the serialization - strategy of the store's adapter. - - `serialize` takes an optional hash as a parameter, currently - supported options are: - - - `includeId`: `true` if the record's ID should be included in the - JSON representation. - - @method serialize - @param {Object} options - @returns {Object} an object whose values are primitive JSON values only - */ - serialize: function(options) { - var store = get(this, 'store'); - return store.serialize(this, options); - }, - - /** - Use [DS.JSONSerializer](DS.JSONSerializer.html) to - get the JSON representation of a record. - - `toJSON` takes an optional hash as a parameter, currently - supported options are: - - - `includeId`: `true` if the record's ID should be included in the - JSON representation. - - @method toJSON - @param {Object} options - @returns {Object} A JSON representation of the object. - */ - toJSON: function(options) { - // container is for lazy transform lookups - var serializer = DS.JSONSerializer.create({ container: this.container }); - return serializer.serialize(this, options); - }, - - /** - Fired when the record is loaded from the server. - - @event didLoad - */ - didLoad: Ember.K, - - /** - Fired when the record is updated. - - @event didUpdate - */ - didUpdate: Ember.K, - - /** - Fired when the record is created. - - @event didCreate - */ - didCreate: Ember.K, - - /** - Fired when the record is deleted. - - @event didDelete - */ - didDelete: Ember.K, - - /** - Fired when the record becomes invalid. - - @event becameInvalid - */ - becameInvalid: Ember.K, - - /** - Fired when the record enters the error state. - - @event becameError - */ - becameError: Ember.K, - - /** - @property data - @private - @type {Object} - */ - data: Ember.computed(function() { - this._data = this._data || {}; - return this._data; - }).property(), - - _data: null, - - init: function() { - set(this, 'currentState', DS.RootState.empty); - var errors = DS.Errors.create(); - errors.registerHandlers(this, function() { - this.send('becameInvalid'); - }, function() { - this.send('becameValid'); - }); - set(this, 'errors', errors); - this._super(); - this._setup(); - }, - - _setup: function() { - this._changesToSync = {}; - this._deferredTriggers = []; - this._data = {}; - this._attributes = {}; - this._inFlightAttributes = {}; - this._relationships = {}; - }, - - /** - @method send - @private - @param {String} name - @param {Object} context - */ - send: function(name, context) { - var currentState = get(this, 'currentState'); - - if (!currentState[name]) { - this._unhandledEvent(currentState, name, context); - } - - return currentState[name](this, context); - }, - - /** - @method transitionTo - @private - @param {String} name - */ - transitionTo: function(name) { - // POSSIBLE TODO: Remove this code and replace with - // always having direct references to state objects - - var pivotName = name.split(".", 1), - currentState = get(this, 'currentState'), - state = currentState; - - do { - if (state.exit) { state.exit(this); } - state = state.parentState; - } while (!state.hasOwnProperty(pivotName)); - - var path = name.split("."); - - var setups = [], enters = [], i, l; - - for (i=0, l=path.length; i')` from " + this.toString(), name !== 'id'); - - meta.name = name; - map.set(name, meta); - } - }); - - return map; - }), - - /** - A map whose keys are the attributes of the model (properties - described by DS.attr) and whose values are type of transformation - applied to each attribute. This map does not include any - attributes that do not have an transformation type. - - Example - - ```javascript - App.Person = DS.Model.extend({ - firstName: attr(), - lastName: attr('string'), - birthday: attr('date') - }); - - var transformedAttributes = Ember.get(App.Person, 'transformedAttributes') - - transformedAttributes.forEach(function(field, type) { - console.log(field, type); - }); - - // prints: - // lastName string - // birthday date - ``` - - @property transformedAttributes - @static - @type {Ember.Map} - @readOnly - */ - transformedAttributes: Ember.computed(function() { - var map = Ember.Map.create(); - - this.eachAttribute(function(key, meta) { - if (meta.type) { - map.set(key, meta.type); - } - }); - - return map; - }), - - /** - Iterates through the attributes of the model, calling the passed function on each - attribute. - - The callback method you provide should have the following signature (all - parameters are optional): - - ```javascript - function(name, meta); - ``` - - - `name` the name of the current property in the iteration - - `meta` the meta object for the attribute property in the iteration - - Note that in addition to a callback, you can also pass an optional target - object that will be set as `this` on the context. - - Example - - ```javascript - App.Person = DS.Model.extend({ - firstName: attr('string'), - lastName: attr('string'), - birthday: attr('date') - }); - - App.Person.eachAttribute(function(name, meta) { - console.log(name, meta); - }); - - // prints: - // firstName {type: "string", isAttribute: true, options: Object, parentType: function, name: "firstName"} - // lastName {type: "string", isAttribute: true, options: Object, parentType: function, name: "lastName"} - // birthday {type: "date", isAttribute: true, options: Object, parentType: function, name: "birthday"} - ``` - - @method eachAttribute - @param {Function} callback The callback to execute - @param {Object} [target] The target object to use - @static - */ - eachAttribute: function(callback, binding) { - get(this, 'attributes').forEach(function(name, meta) { - callback.call(binding, name, meta); - }, binding); - }, - - /** - Iterates through the transformedAttributes of the model, calling - the passed function on each attribute. Note the callback will not be - called for any attributes that do not have an transformation type. - - The callback method you provide should have the following signature (all - parameters are optional): - - ```javascript - function(name, type); - ``` - - - `name` the name of the current property in the iteration - - `type` a tring contrining the name of the type of transformed - applied to the attribute - - Note that in addition to a callback, you can also pass an optional target - object that will be set as `this` on the context. - - Example - - ```javascript - App.Person = DS.Model.extend({ - firstName: attr(), - lastName: attr('string'), - birthday: attr('date') - }); - - App.Person.eachTransformedAttribute(function(name, type) { - console.log(name, type); - }); - - // prints: - // lastName string - // birthday date - ``` - - @method eachTransformedAttribute - @param {Function} callback The callback to execute - @param {Object} [target] The target object to use - @static - */ - eachTransformedAttribute: function(callback, binding) { - get(this, 'transformedAttributes').forEach(function(name, type) { - callback.call(binding, name, type); - }); - } -}); - - -DS.Model.reopen({ - eachAttribute: function(callback, binding) { - this.constructor.eachAttribute(callback, binding); - } -}); - -function getDefaultValue(record, options, key) { - if (typeof options.defaultValue === "function") { - return options.defaultValue(); - } else { - return options.defaultValue; - } -} - -function hasValue(record, key) { - return record._attributes.hasOwnProperty(key) || - record._inFlightAttributes.hasOwnProperty(key) || - record._data.hasOwnProperty(key); -} - -function getValue(record, key) { - if (record._attributes.hasOwnProperty(key)) { - return record._attributes[key]; - } else if (record._inFlightAttributes.hasOwnProperty(key)) { - return record._inFlightAttributes[key]; - } else { - return record._data[key]; - } -} - -/** - `DS.attr` defines an attribute on a [DS.Model](DS.Model.html). - By default, attributes are passed through as-is, however you can specify an - optional type to have the value automatically transformed. - Ember Data ships with four basic transform types: `string`, `number`, - `boolean` and `date`. You can define your own transforms by subclassing - [DS.Transform](DS.Transform.html). - - `DS.attr` takes an optional hash as a second parameter, currently - supported options are: - - - `defaultValue`: Pass a string or a function to be called to set the attribute - to a default value if none is supplied. - - Example - - ```javascript - var attr = DS.attr; - - App.User = DS.Model.extend({ - username: attr('string'), - email: attr('string'), - verified: attr('boolean', {defaultValue: false}) - }); - ``` - - @namespace - @method attr - @for DS - @param {String} type the attribute type - @param {Object} options a hash of options - @return {Attribute} -*/ - -DS.attr = function(type, options) { - options = options || {}; - - var meta = { - type: type, - isAttribute: true, - options: options - }; - - return Ember.computed(function(key, value) { - if (arguments.length > 1) { - Ember.assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.constructor.toString(), key !== 'id'); - var oldValue = this._attributes[key] || this._inFlightAttributes[key] || this._data[key]; - - this.send('didSetProperty', { - name: key, - oldValue: oldValue, - originalValue: this._data[key], - value: value - }); - - this._attributes[key] = value; - return value; - } else if (hasValue(this, key)) { - return getValue(this, key); - } else { - return getDefaultValue(this, options, key); - } - - // `data` is never set directly. However, it may be - // invalidated from the state manager's setData - // event. - }).property('data').meta(meta); -}; - - -})(); - - - -(function() { -/** - @module ember-data -*/ - -})(); - - - -(function() { -/** - @module ember-data -*/ - -/** - An AttributeChange object is created whenever a record's - attribute changes value. It is used to track changes to a - record between transaction commits. - - @class AttributeChange - @namespace DS - @private - @constructor -*/ -var AttributeChange = DS.AttributeChange = function(options) { - this.record = options.record; - this.store = options.store; - this.name = options.name; - this.value = options.value; - this.oldValue = options.oldValue; -}; - -AttributeChange.createChange = function(options) { - return new AttributeChange(options); -}; - -AttributeChange.prototype = { - sync: function() { - if (this.value !== this.oldValue) { - this.record.send('becomeDirty'); - this.record.updateRecordArraysLater(); - } - - // TODO: Use this object in the commit process - this.destroy(); - }, - - /** - If the AttributeChange is destroyed (either by being rolled back - or being committed), remove it from the list of pending changes - on the record. - - @method destroy - */ - destroy: function() { - delete this.record._changesToSync[this.name]; - } -}; - -})(); - - - -(function() { -/** - @module ember-data -*/ - -var get = Ember.get, set = Ember.set; -var forEach = Ember.EnumerableUtils.forEach; - -/** - @class RelationshipChange - @namespace DS - @private - @construtor -*/ -DS.RelationshipChange = function(options) { - this.parentRecord = options.parentRecord; - this.childRecord = options.childRecord; - this.firstRecord = options.firstRecord; - this.firstRecordKind = options.firstRecordKind; - this.firstRecordName = options.firstRecordName; - this.secondRecord = options.secondRecord; - this.secondRecordKind = options.secondRecordKind; - this.secondRecordName = options.secondRecordName; - this.changeType = options.changeType; - this.store = options.store; - - this.committed = {}; -}; - -/** - @class RelationshipChangeAdd - @namespace DS - @private - @construtor -*/ -DS.RelationshipChangeAdd = function(options){ - DS.RelationshipChange.call(this, options); -}; - -/** - @class RelationshipChangeRemove - @namespace DS - @private - @construtor -*/ -DS.RelationshipChangeRemove = function(options){ - DS.RelationshipChange.call(this, options); -}; - -DS.RelationshipChange.create = function(options) { - return new DS.RelationshipChange(options); -}; - -DS.RelationshipChangeAdd.create = function(options) { - return new DS.RelationshipChangeAdd(options); -}; - -DS.RelationshipChangeRemove.create = function(options) { - return new DS.RelationshipChangeRemove(options); -}; - -DS.OneToManyChange = {}; -DS.OneToNoneChange = {}; -DS.ManyToNoneChange = {}; -DS.OneToOneChange = {}; -DS.ManyToManyChange = {}; - -DS.RelationshipChange._createChange = function(options){ - if(options.changeType === "add"){ - return DS.RelationshipChangeAdd.create(options); - } - if(options.changeType === "remove"){ - return DS.RelationshipChangeRemove.create(options); - } -}; - - -DS.RelationshipChange.determineRelationshipType = function(recordType, knownSide){ - var knownKey = knownSide.key, key, otherKind; - var knownKind = knownSide.kind; - - var inverse = recordType.inverseFor(knownKey); - - if (inverse){ - key = inverse.name; - otherKind = inverse.kind; - } - - if (!inverse){ - return knownKind === "belongsTo" ? "oneToNone" : "manyToNone"; - } - else{ - if(otherKind === "belongsTo"){ - return knownKind === "belongsTo" ? "oneToOne" : "manyToOne"; - } - else{ - return knownKind === "belongsTo" ? "oneToMany" : "manyToMany"; - } - } - -}; - -DS.RelationshipChange.createChange = function(firstRecord, secondRecord, store, options){ - // Get the type of the child based on the child's client ID - var firstRecordType = firstRecord.constructor, changeType; - changeType = DS.RelationshipChange.determineRelationshipType(firstRecordType, options); - if (changeType === "oneToMany"){ - return DS.OneToManyChange.createChange(firstRecord, secondRecord, store, options); - } - else if (changeType === "manyToOne"){ - return DS.OneToManyChange.createChange(secondRecord, firstRecord, store, options); - } - else if (changeType === "oneToNone"){ - return DS.OneToNoneChange.createChange(firstRecord, secondRecord, store, options); - } - else if (changeType === "manyToNone"){ - return DS.ManyToNoneChange.createChange(firstRecord, secondRecord, store, options); - } - else if (changeType === "oneToOne"){ - return DS.OneToOneChange.createChange(firstRecord, secondRecord, store, options); - } - else if (changeType === "manyToMany"){ - return DS.ManyToManyChange.createChange(firstRecord, secondRecord, store, options); - } -}; - -DS.OneToNoneChange.createChange = function(childRecord, parentRecord, store, options) { - var key = options.key; - var change = DS.RelationshipChange._createChange({ - parentRecord: parentRecord, - childRecord: childRecord, - firstRecord: childRecord, - store: store, - changeType: options.changeType, - firstRecordName: key, - firstRecordKind: "belongsTo" - }); - - store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change); - - return change; -}; - -DS.ManyToNoneChange.createChange = function(childRecord, parentRecord, store, options) { - var key = options.key; - var change = DS.RelationshipChange._createChange({ - parentRecord: childRecord, - childRecord: parentRecord, - secondRecord: childRecord, - store: store, - changeType: options.changeType, - secondRecordName: options.key, - secondRecordKind: "hasMany" - }); - - store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change); - return change; -}; - - -DS.ManyToManyChange.createChange = function(childRecord, parentRecord, store, options) { - // If the name of the belongsTo side of the relationship is specified, - // use that - // If the type of the parent is specified, look it up on the child's type - // definition. - var key = options.key; - - var change = DS.RelationshipChange._createChange({ - parentRecord: parentRecord, - childRecord: childRecord, - firstRecord: childRecord, - secondRecord: parentRecord, - firstRecordKind: "hasMany", - secondRecordKind: "hasMany", - store: store, - changeType: options.changeType, - firstRecordName: key - }); - - store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change); - - - return change; -}; - -DS.OneToOneChange.createChange = function(childRecord, parentRecord, store, options) { - var key; - - // If the name of the belongsTo side of the relationship is specified, - // use that - // If the type of the parent is specified, look it up on the child's type - // definition. - if (options.parentType) { - key = options.parentType.inverseFor(options.key).name; - } else if (options.key) { - key = options.key; - } else { - Ember.assert("You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent", false); - } - - var change = DS.RelationshipChange._createChange({ - parentRecord: parentRecord, - childRecord: childRecord, - firstRecord: childRecord, - secondRecord: parentRecord, - firstRecordKind: "belongsTo", - secondRecordKind: "belongsTo", - store: store, - changeType: options.changeType, - firstRecordName: key - }); - - store.addRelationshipChangeFor(childRecord, key, parentRecord, null, change); - - - return change; -}; - -DS.OneToOneChange.maintainInvariant = function(options, store, childRecord, key){ - if (options.changeType === "add" && store.recordIsMaterialized(childRecord)) { - var oldParent = get(childRecord, key); - if (oldParent){ - var correspondingChange = DS.OneToOneChange.createChange(childRecord, oldParent, store, { - parentType: options.parentType, - hasManyName: options.hasManyName, - changeType: "remove", - key: options.key - }); - store.addRelationshipChangeFor(childRecord, key, options.parentRecord , null, correspondingChange); - correspondingChange.sync(); - } - } -}; - -DS.OneToManyChange.createChange = function(childRecord, parentRecord, store, options) { - var key; - - // If the name of the belongsTo side of the relationship is specified, - // use that - // If the type of the parent is specified, look it up on the child's type - // definition. - if (options.parentType) { - key = options.parentType.inverseFor(options.key).name; - DS.OneToManyChange.maintainInvariant( options, store, childRecord, key ); - } else if (options.key) { - key = options.key; - } else { - Ember.assert("You must pass either a parentType or belongsToName option to OneToManyChange.forChildAndParent", false); - } - - var change = DS.RelationshipChange._createChange({ - parentRecord: parentRecord, - childRecord: childRecord, - firstRecord: childRecord, - secondRecord: parentRecord, - firstRecordKind: "belongsTo", - secondRecordKind: "hasMany", - store: store, - changeType: options.changeType, - firstRecordName: key - }); - - store.addRelationshipChangeFor(childRecord, key, parentRecord, change.getSecondRecordName(), change); - - - return change; -}; - - -DS.OneToManyChange.maintainInvariant = function(options, store, childRecord, key){ - if (options.changeType === "add" && childRecord) { - var oldParent = get(childRecord, key); - if (oldParent){ - var correspondingChange = DS.OneToManyChange.createChange(childRecord, oldParent, store, { - parentType: options.parentType, - hasManyName: options.hasManyName, - changeType: "remove", - key: options.key - }); - store.addRelationshipChangeFor(childRecord, key, options.parentRecord, correspondingChange.getSecondRecordName(), correspondingChange); - correspondingChange.sync(); - } - } -}; - -/** - @class RelationshipChange - @namespace DS -*/ -DS.RelationshipChange.prototype = { - - getSecondRecordName: function() { - var name = this.secondRecordName, parent; - - if (!name) { - parent = this.secondRecord; - if (!parent) { return; } - - var childType = this.firstRecord.constructor; - var inverse = childType.inverseFor(this.firstRecordName); - this.secondRecordName = inverse.name; - } - - return this.secondRecordName; - }, - - /** - Get the name of the relationship on the belongsTo side. - - @method getFirstRecordName - @return {String} - */ - getFirstRecordName: function() { - var name = this.firstRecordName; - return name; - }, - - /** - @method destroy - @private - */ - destroy: function() { - var childRecord = this.childRecord, - belongsToName = this.getFirstRecordName(), - hasManyName = this.getSecondRecordName(), - store = this.store; - - store.removeRelationshipChangeFor(childRecord, belongsToName, this.parentRecord, hasManyName, this.changeType); - }, - - getSecondRecord: function(){ - return this.secondRecord; - }, - - /** - @method getFirstRecord - @private - */ - getFirstRecord: function() { - return this.firstRecord; - }, - - coalesce: function(){ - var relationshipPairs = this.store.relationshipChangePairsFor(this.firstRecord); - forEach(relationshipPairs, function(pair){ - var addedChange = pair["add"]; - var removedChange = pair["remove"]; - if(addedChange && removedChange) { - addedChange.destroy(); - removedChange.destroy(); - } - }); - } -}; - -DS.RelationshipChangeAdd.prototype = Ember.create(DS.RelationshipChange.create({})); -DS.RelationshipChangeRemove.prototype = Ember.create(DS.RelationshipChange.create({})); - -// the object is a value, and not a promise -function isValue(object) { - return typeof object === 'object' && (!object.then || typeof object.then !== 'function'); -} - -DS.RelationshipChangeAdd.prototype.changeType = "add"; -DS.RelationshipChangeAdd.prototype.sync = function() { - var secondRecordName = this.getSecondRecordName(), - firstRecordName = this.getFirstRecordName(), - firstRecord = this.getFirstRecord(), - secondRecord = this.getSecondRecord(); - - //Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName); - //Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName); - - if (secondRecord instanceof DS.Model && firstRecord instanceof DS.Model) { - if(this.secondRecordKind === "belongsTo"){ - secondRecord.suspendRelationshipObservers(function(){ - set(secondRecord, secondRecordName, firstRecord); - }); - - } - else if(this.secondRecordKind === "hasMany"){ - secondRecord.suspendRelationshipObservers(function(){ - var relationship = get(secondRecord, secondRecordName); - if (isValue(relationship)) { relationship.addObject(firstRecord); } - }); - } - } - - if (firstRecord instanceof DS.Model && secondRecord instanceof DS.Model && get(firstRecord, firstRecordName) !== secondRecord) { - if(this.firstRecordKind === "belongsTo"){ - firstRecord.suspendRelationshipObservers(function(){ - set(firstRecord, firstRecordName, secondRecord); - }); - } - else if(this.firstRecordKind === "hasMany"){ - firstRecord.suspendRelationshipObservers(function(){ - var relationship = get(firstRecord, firstRecordName); - if (isValue(relationship)) { relationship.addObject(secondRecord); } - }); - } - } - - this.coalesce(); -}; - -DS.RelationshipChangeRemove.prototype.changeType = "remove"; -DS.RelationshipChangeRemove.prototype.sync = function() { - var secondRecordName = this.getSecondRecordName(), - firstRecordName = this.getFirstRecordName(), - firstRecord = this.getFirstRecord(), - secondRecord = this.getSecondRecord(); - - //Ember.assert("You specified a hasMany (" + hasManyName + ") on " + (!belongsToName && (newParent || oldParent || this.lastParent).constructor) + " but did not specify an inverse belongsTo on " + child.constructor, belongsToName); - //Ember.assert("You specified a belongsTo (" + belongsToName + ") on " + child.constructor + " but did not specify an inverse hasMany on " + (!hasManyName && (newParent || oldParent || this.lastParentRecord).constructor), hasManyName); - - if (secondRecord instanceof DS.Model && firstRecord instanceof DS.Model) { - if(this.secondRecordKind === "belongsTo"){ - secondRecord.suspendRelationshipObservers(function(){ - set(secondRecord, secondRecordName, null); - }); - } - else if(this.secondRecordKind === "hasMany"){ - secondRecord.suspendRelationshipObservers(function(){ - var relationship = get(secondRecord, secondRecordName); - if (isValue(relationship)) { relationship.removeObject(firstRecord); } - }); - } - } - - if (firstRecord instanceof DS.Model && get(firstRecord, firstRecordName)) { - if(this.firstRecordKind === "belongsTo"){ - firstRecord.suspendRelationshipObservers(function(){ - set(firstRecord, firstRecordName, null); - }); - } - else if(this.firstRecordKind === "hasMany"){ - firstRecord.suspendRelationshipObservers(function(){ - var relationship = get(firstRecord, firstRecordName); - if (isValue(relationship)) { relationship.removeObject(secondRecord); } - }); - } - } - - this.coalesce(); -}; - -})(); - - - -(function() { -/** - @module ember-data -*/ - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set, - isNone = Ember.isNone; - -/** - @module ember-data -*/ - -function asyncBelongsTo(type, options, meta) { - return Ember.computed(function(key, value) { - var data = get(this, 'data'), - store = get(this, 'store'), - promiseLabel = "DS: Async belongsTo " + this + " : " + key; - - if (arguments.length === 2) { - Ember.assert("You can only add a '" + type + "' record to this relationship", !value || value instanceof store.modelFor(type)); - return value === undefined ? null : DS.PromiseObject.create({ promise: Ember.RSVP.resolve(value, promiseLabel) }); - } - - var link = data.links && data.links[key], - belongsTo = data[key]; - - if(!isNone(belongsTo)) { - var promise = store.fetchRecord(belongsTo) || Ember.RSVP.resolve(belongsTo, promiseLabel); - return DS.PromiseObject.create({ promise: promise}); - } else if (link) { - var resolver = Ember.RSVP.defer("DS: Async belongsTo (link) " + this + " : " + key); - store.findBelongsTo(this, link, meta, resolver); - return DS.PromiseObject.create({ promise: resolver.promise }); - } else { - return null; - } - }).property('data').meta(meta); -} - -/** - `DS.belongsTo` is used to define One-To-One and One-To-Many - relationships on a [DS.Model](DS.Model.html). - - - `DS.belongsTo` takes an optional hash as a second parameter, currently - supported options are: - - - `async`: A boolean value used to explicitly declare this to be an async relationship. - - `inverse`: A string used to identify the inverse property on a - related model in a One-To-Many relationship. See [Explicit Inverses](#toc_explicit-inverses) - - #### One-To-One - To declare a one-to-one relationship between two models, use - `DS.belongsTo`: - - ```javascript - App.User = DS.Model.extend({ - profile: DS.belongsTo('profile') - }); - - App.Profile = DS.Model.extend({ - user: DS.belongsTo('user') - }); - ``` - - #### One-To-Many - To declare a one-to-many relationship between two models, use - `DS.belongsTo` in combination with `DS.hasMany`, like this: - - ```javascript - App.Post = DS.Model.extend({ - comments: DS.hasMany('comment') - }); - - App.Comment = DS.Model.extend({ - post: DS.belongsTo('post') - }); - ``` - - @namespace - @method belongsTo - @for DS - @param {String or DS.Model} type the model type of the relationship - @param {Object} options a hash of options - @return {Ember.computed} relationship -*/ -DS.belongsTo = function(type, options) { - if (typeof type === 'object') { - options = type; - type = undefined; - } else { - Ember.assert("The first argument DS.belongsTo must be a model type or string, like DS.belongsTo(App.Person)", !!type && (typeof type === 'string' || DS.Model.detect(type))); - } - - options = options || {}; - - var meta = { type: type, isRelationship: true, options: options, kind: 'belongsTo' }; - - if (options.async) { - return asyncBelongsTo(type, options, meta); - } - - return Ember.computed(function(key, value) { - var data = get(this, 'data'), - store = get(this, 'store'), belongsTo, typeClass; - - if (typeof type === 'string') { - typeClass = store.modelFor(type); - } else { - typeClass = type; - } - - if (arguments.length === 2) { - Ember.assert("You can only add a '" + type + "' record to this relationship", !value || value instanceof typeClass); - return value === undefined ? null : value; - } - - belongsTo = data[key]; - - if (isNone(belongsTo)) { return null; } - - store.fetchRecord(belongsTo); - - return belongsTo; - }).property('data').meta(meta); -}; - -/** - These observers observe all `belongsTo` relationships on the record. See - `relationships/ext` to see how these observers get their dependencies. - - @class Model - @namespace DS -*/ -DS.Model.reopen({ - - /** - @method belongsToWillChange - @private - @static - @param record - @param key - */ - belongsToWillChange: Ember.beforeObserver(function(record, key) { - if (get(record, 'isLoaded')) { - var oldParent = get(record, key); - - if (oldParent) { - var store = get(record, 'store'), - change = DS.RelationshipChange.createChange(record, oldParent, store, { key: key, kind: "belongsTo", changeType: "remove" }); - - change.sync(); - this._changesToSync[key] = change; - } - } - }), - - /** - @method belongsToDidChange - @private - @static - @param record - @param key - */ - belongsToDidChange: Ember.immediateObserver(function(record, key) { - if (get(record, 'isLoaded')) { - var newParent = get(record, key); - - if (newParent) { - var store = get(record, 'store'), - change = DS.RelationshipChange.createChange(record, newParent, store, { key: key, kind: "belongsTo", changeType: "add" }); - - change.sync(); - } - } - - delete this._changesToSync[key]; - }) -}); - -})(); - - - -(function() { -/** - @module ember-data -*/ - -var get = Ember.get, set = Ember.set, setProperties = Ember.setProperties; - -function asyncHasMany(type, options, meta) { - return Ember.computed(function(key, value) { - var relationship = this._relationships[key], - promiseLabel = "DS: Async hasMany " + this + " : " + key; - - if (!relationship) { - var resolver = Ember.RSVP.defer(promiseLabel); - relationship = buildRelationship(this, key, options, function(store, data) { - var link = data.links && data.links[key]; - var rel; - if (link) { - rel = store.findHasMany(this, link, meta, resolver); - } else { - rel = store.findMany(this, data[key], meta.type, resolver); - } - // cache the promise so we can use it - // when we come back and don't need to rebuild - // the relationship. - set(rel, 'promise', resolver.promise); - return rel; - }); - } - - var promise = relationship.get('promise').then(function() { - return relationship; - }, null, "DS: Async hasMany records received"); - - return DS.PromiseArray.create({ promise: promise }); - }).property('data').meta(meta); -} - -function buildRelationship(record, key, options, callback) { - var rels = record._relationships; - - if (rels[key]) { return rels[key]; } - - var data = get(record, 'data'), - store = get(record, 'store'); - - var relationship = rels[key] = callback.call(record, store, data); - - return setProperties(relationship, { - owner: record, name: key, isPolymorphic: options.polymorphic - }); -} - -function hasRelationship(type, options) { - options = options || {}; - - var meta = { type: type, isRelationship: true, options: options, kind: 'hasMany' }; - - if (options.async) { - return asyncHasMany(type, options, meta); - } - - return Ember.computed(function(key, value) { - return buildRelationship(this, key, options, function(store, data) { - var records = data[key]; - Ember.assert("You looked up the '" + key + "' relationship on '" + this + "' but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.hasMany({ async: true })`)", Ember.A(records).everyProperty('isEmpty', false)); - return store.findMany(this, data[key], meta.type); - }); - }).property('data').meta(meta); -} - -/** - `DS.hasMany` is used to define One-To-Many and Many-To-Many - relationships on a [DS.Model](DS.Model.html). - - `DS.hasMany` takes an optional hash as a second parameter, currently - supported options are: - - - `async`: A boolean value used to explicitly declare this to be an async relationship. - - `inverse`: A string used to identify the inverse property on a related model. - - #### One-To-Many - To declare a one-to-many relationship between two models, use - `DS.belongsTo` in combination with `DS.hasMany`, like this: - - ```javascript - App.Post = DS.Model.extend({ - comments: DS.hasMany('comment') - }); - - App.Comment = DS.Model.extend({ - post: DS.belongsTo('post') - }); - ``` - - #### Many-To-Many - To declare a many-to-many relationship between two models, use - `DS.hasMany`: - - ```javascript - App.Post = DS.Model.extend({ - tags: DS.hasMany('tag') - }); - - App.Tag = DS.Model.extend({ - posts: DS.hasMany('post') - }); - ``` - - #### Explicit Inverses - - Ember Data will do its best to discover which relationships map to - one another. In the one-to-many code above, for example, Ember Data - can figure out that changing the `comments` relationship should update - the `post` relationship on the inverse because post is the only - relationship to that model. - - However, sometimes you may have multiple `belongsTo`/`hasManys` for the - same type. You can specify which property on the related model is - the inverse using `DS.hasMany`'s `inverse` option: - - ```javascript - var belongsTo = DS.belongsTo, - hasMany = DS.hasMany; - - App.Comment = DS.Model.extend({ - onePost: belongsTo('post'), - twoPost: belongsTo('post'), - redPost: belongsTo('post'), - bluePost: belongsTo('post') - }); - - App.Post = DS.Model.extend({ - comments: hasMany('comment', { - inverse: 'redPost' - }) - }); - ``` - - You can also specify an inverse on a `belongsTo`, which works how - you'd expect. - - @namespace - @method hasMany - @for DS - @param {String or DS.Model} type the model type of the relationship - @param {Object} options a hash of options - @return {Ember.computed} relationship -*/ -DS.hasMany = function(type, options) { - if (typeof type === 'object') { - options = type; - type = undefined; - } - return hasRelationship(type, options); -}; - -})(); - - - -(function() { -var get = Ember.get, set = Ember.set; - -/** - @module ember-data -*/ - -/* - This file defines several extensions to the base `DS.Model` class that - add support for one-to-many relationships. -*/ - -/** - @class Model - @namespace DS -*/ -DS.Model.reopen({ - - /** - This Ember.js hook allows an object to be notified when a property - is defined. - - In this case, we use it to be notified when an Ember Data user defines a - belongs-to relationship. In that case, we need to set up observers for - each one, allowing us to track relationship changes and automatically - reflect changes in the inverse has-many array. - - This hook passes the class being set up, as well as the key and value - being defined. So, for example, when the user does this: - - ```javascript - DS.Model.extend({ - parent: DS.belongsTo('user') - }); - ``` - - This hook would be called with "parent" as the key and the computed - property returned by `DS.belongsTo` as the value. - - @method didDefineProperty - @param proto - @param key - @param value - */ - didDefineProperty: function(proto, key, value) { - // Check if the value being set is a computed property. - if (value instanceof Ember.Descriptor) { - - // If it is, get the metadata for the relationship. This is - // populated by the `DS.belongsTo` helper when it is creating - // the computed property. - var meta = value.meta(); - - if (meta.isRelationship && meta.kind === 'belongsTo') { - Ember.addObserver(proto, key, null, 'belongsToDidChange'); - Ember.addBeforeObserver(proto, key, null, 'belongsToWillChange'); - } - - meta.parentType = proto.constructor; - } - } -}); - -/* - These DS.Model extensions add class methods that provide relationship - introspection abilities about relationships. - - A note about the computed properties contained here: - - **These properties are effectively sealed once called for the first time.** - To avoid repeatedly doing expensive iteration over a model's fields, these - values are computed once and then cached for the remainder of the runtime of - your application. - - If your application needs to modify a class after its initial definition - (for example, using `reopen()` to add additional attributes), make sure you - do it before using your model with the store, which uses these properties - extensively. -*/ - -DS.Model.reopenClass({ - /** - For a given relationship name, returns the model type of the relationship. - - For example, if you define a model like this: - - ```javascript - App.Post = DS.Model.extend({ - comments: DS.hasMany('comment') - }); - ``` - - Calling `App.Post.typeForRelationship('comments')` will return `App.Comment`. - - @method typeForRelationship - @static - @param {String} name the name of the relationship - @return {subclass of DS.Model} the type of the relationship, or undefined - */ - typeForRelationship: function(name) { - var relationship = get(this, 'relationshipsByName').get(name); - return relationship && relationship.type; - }, - - inverseFor: function(name) { - var inverseType = this.typeForRelationship(name); - - if (!inverseType) { return null; } - - var options = this.metaForProperty(name).options; - - if (options.inverse === null) { return null; } - - var inverseName, inverseKind; - - if (options.inverse) { - inverseName = options.inverse; - inverseKind = Ember.get(inverseType, 'relationshipsByName').get(inverseName).kind; - } else { - var possibleRelationships = findPossibleInverses(this, inverseType); - - if (possibleRelationships.length === 0) { return null; } - - Ember.assert("You defined the '" + name + "' relationship on " + this + ", but multiple possible inverse relationships of type " + this + " were found on " + inverseType + ". Look at http://emberjs.com/guides/models/defining-models/#toc_explicit-inverses for how to explicitly specify inverses", possibleRelationships.length === 1); - - inverseName = possibleRelationships[0].name; - inverseKind = possibleRelationships[0].kind; - } - - function findPossibleInverses(type, inverseType, possibleRelationships) { - possibleRelationships = possibleRelationships || []; - - var relationshipMap = get(inverseType, 'relationships'); - if (!relationshipMap) { return; } - - var relationships = relationshipMap.get(type); - if (relationships) { - possibleRelationships.push.apply(possibleRelationships, relationshipMap.get(type)); - } - - if (type.superclass) { - findPossibleInverses(type.superclass, inverseType, possibleRelationships); - } - - return possibleRelationships; - } - - return { - type: inverseType, - name: inverseName, - kind: inverseKind - }; - }, - - /** - The model's relationships as a map, keyed on the type of the - relationship. The value of each entry is an array containing a descriptor - for each relationship with that type, describing the name of the relationship - as well as the type. - - For example, given the following model definition: - - ```javascript - App.Blog = DS.Model.extend({ - users: DS.hasMany('user'), - owner: DS.belongsTo('user'), - posts: DS.hasMany('post') - }); - ``` - - This computed property would return a map describing these - relationships, like this: - - ```javascript - var relationships = Ember.get(App.Blog, 'relationships'); - relationships.get(App.User); - //=> [ { name: 'users', kind: 'hasMany' }, - // { name: 'owner', kind: 'belongsTo' } ] - relationships.get(App.Post); - //=> [ { name: 'posts', kind: 'hasMany' } ] - ``` - - @property relationships - @static - @type Ember.Map - @readOnly - */ - relationships: Ember.computed(function() { - var map = new Ember.MapWithDefault({ - defaultValue: function() { return []; } - }); - - // Loop through each computed property on the class - this.eachComputedProperty(function(name, meta) { - - // If the computed property is a relationship, add - // it to the map. - if (meta.isRelationship) { - if (typeof meta.type === 'string') { - meta.type = this.store.modelFor(meta.type); - } - - var relationshipsForType = map.get(meta.type); - - relationshipsForType.push({ name: name, kind: meta.kind }); - } - }); - - return map; - }), - - /** - A hash containing lists of the model's relationships, grouped - by the relationship kind. For example, given a model with this - definition: - - ```javascript - App.Blog = DS.Model.extend({ - users: DS.hasMany('user'), - owner: DS.belongsTo('user'), - - posts: DS.hasMany('post') - }); - ``` - - This property would contain the following: - - ```javascript - var relationshipNames = Ember.get(App.Blog, 'relationshipNames'); - relationshipNames.hasMany; - //=> ['users', 'posts'] - relationshipNames.belongsTo; - //=> ['owner'] - ``` - - @property relationshipNames - @static - @type Object - @readOnly - */ - relationshipNames: Ember.computed(function() { - var names = { hasMany: [], belongsTo: [] }; - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - names[meta.kind].push(name); - } - }); - - return names; - }), - - /** - An array of types directly related to a model. Each type will be - included once, regardless of the number of relationships it has with - the model. - - For example, given a model with this definition: - - ```javascript - App.Blog = DS.Model.extend({ - users: DS.hasMany('user'), - owner: DS.belongsTo('user'), - - posts: DS.hasMany('post') - }); - ``` - - This property would contain the following: - - ```javascript - var relatedTypes = Ember.get(App.Blog, 'relatedTypes'); - //=> [ App.User, App.Post ] - ``` - - @property relatedTypes - @static - @type Ember.Array - @readOnly - */ - relatedTypes: Ember.computed(function() { - var type, - types = Ember.A(); - - // Loop through each computed property on the class, - // and create an array of the unique types involved - // in relationships - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - type = meta.type; - - if (typeof type === 'string') { - type = get(this, type, false) || this.store.modelFor(type); - } - - Ember.assert("You specified a hasMany (" + meta.type + ") on " + meta.parentType + " but " + meta.type + " was not found.", type); - - if (!types.contains(type)) { - Ember.assert("Trying to sideload " + name + " on " + this.toString() + " but the type doesn't exist.", !!type); - types.push(type); - } - } - }); - - return types; - }), - - /** - A map whose keys are the relationships of a model and whose values are - relationship descriptors. - - For example, given a model with this - definition: - - ```javascript - App.Blog = DS.Model.extend({ - users: DS.hasMany('user'), - owner: DS.belongsTo('user'), - - posts: DS.hasMany('post') - }); - ``` - - This property would contain the following: - - ```javascript - var relationshipsByName = Ember.get(App.Blog, 'relationshipsByName'); - relationshipsByName.get('users'); - //=> { key: 'users', kind: 'hasMany', type: App.User } - relationshipsByName.get('owner'); - //=> { key: 'owner', kind: 'belongsTo', type: App.User } - ``` - - @property relationshipsByName - @static - @type Ember.Map - @readOnly - */ - relationshipsByName: Ember.computed(function() { - var map = Ember.Map.create(), type; - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - meta.key = name; - type = meta.type; - - if (!type && meta.kind === 'hasMany') { - type = Ember.String.singularize(name); - } else if (!type) { - type = name; - } - - if (typeof type === 'string') { - meta.type = this.store.modelFor(type); - } - - map.set(name, meta); - } - }); - - return map; - }), - - /** - A map whose keys are the fields of the model and whose values are strings - describing the kind of the field. A model's fields are the union of all of its - attributes and relationships. - - For example: - - ```javascript - - App.Blog = DS.Model.extend({ - users: DS.hasMany('user'), - owner: DS.belongsTo('user'), - - posts: DS.hasMany('post'), - - title: DS.attr('string') - }); - - var fields = Ember.get(App.Blog, 'fields'); - fields.forEach(function(field, kind) { - console.log(field, kind); - }); - - // prints: - // users, hasMany - // owner, belongsTo - // posts, hasMany - // title, attribute - ``` - - @property fields - @static - @type Ember.Map - @readOnly - */ - fields: Ember.computed(function() { - var map = Ember.Map.create(); - - this.eachComputedProperty(function(name, meta) { - if (meta.isRelationship) { - map.set(name, meta.kind); - } else if (meta.isAttribute) { - map.set(name, 'attribute'); - } - }); - - return map; - }), - - /** - Given a callback, iterates over each of the relationships in the model, - invoking the callback with the name of each relationship and its relationship - descriptor. - - @method eachRelationship - @static - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelationship: function(callback, binding) { - get(this, 'relationshipsByName').forEach(function(name, relationship) { - callback.call(binding, name, relationship); - }); - }, - - /** - Given a callback, iterates over each of the types related to a model, - invoking the callback with the related type's class. Each type will be - returned just once, regardless of how many different relationships it has - with a model. - - @method eachRelatedType - @static - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelatedType: function(callback, binding) { - get(this, 'relatedTypes').forEach(function(type) { - callback.call(binding, type); - }); - } -}); - -DS.Model.reopen({ - /** - Given a callback, iterates over each of the relationships in the model, - invoking the callback with the name of each relationship and its relationship - descriptor. - - @method eachRelationship - @param {Function} callback the callback to invoke - @param {any} binding the value to which the callback's `this` should be bound - */ - eachRelationship: function(callback, binding) { - this.constructor.eachRelationship(callback, binding); - } -}); - -})(); - - - -(function() { -/** - @module ember-data -*/ - -})(); - - - -(function() { -/** - @module ember-data -*/ - -var get = Ember.get, set = Ember.set; -var once = Ember.run.once; -var forEach = Ember.EnumerableUtils.forEach; - -/** - @class RecordArrayManager - @namespace DS - @private - @extends Ember.Object -*/ -DS.RecordArrayManager = Ember.Object.extend({ - init: function() { - this.filteredRecordArrays = Ember.MapWithDefault.create({ - defaultValue: function() { return []; } - }); - - this.changedRecords = []; - }, - - recordDidChange: function(record) { - this.changedRecords.push(record); - once(this, this.updateRecordArrays); - }, - - recordArraysForRecord: function(record) { - record._recordArrays = record._recordArrays || Ember.OrderedSet.create(); - return record._recordArrays; - }, - - /** - This method is invoked whenever data is loaded into the store by the - adapter or updated by the adapter, or when a record has changed. - - It updates all record arrays that a record belongs to. - - To avoid thrashing, it only runs at most once per run loop. - - @method updateRecordArrays - @param {Class} type - @param {Number|String} clientId - */ - updateRecordArrays: function() { - forEach(this.changedRecords, function(record) { - if (get(record, 'isDeleted')) { - this._recordWasDeleted(record); - } else { - this._recordWasChanged(record); - } - }, this); - - this.changedRecords = []; - }, - - _recordWasDeleted: function (record) { - var recordArrays = record._recordArrays; - - if (!recordArrays) { return; } - - forEach(recordArrays, function(array) { - array.removeRecord(record); - }); - }, - - _recordWasChanged: function (record) { - var type = record.constructor, - recordArrays = this.filteredRecordArrays.get(type), - filter; - - forEach(recordArrays, function(array) { - filter = get(array, 'filterFunction'); - this.updateRecordArray(array, filter, type, record); - }, this); - - // loop through all manyArrays containing an unloaded copy of this - // clientId and notify them that the record was loaded. - var manyArrays = record._loadingRecordArrays; - - if (manyArrays) { - for (var i=0, l=manyArrays.length; i 'kine' - inflector.singularize('kine') //=> 'cow' - ``` - - Creating an inflector and adding rules later. - - ```javascript - var inflector = Ember.Inflector.inflector; - - inflector.pluralize('advice') // => 'advices' - inflector.uncountable('advice'); - inflector.pluralize('advice') // => 'advice' - - inflector.pluralize('formula') // => 'formulas' - inflector.irregular('formula', 'formulae'); - inflector.pluralize('formula') // => 'formulae' - - // you would not need to add these as they are the default rules - inflector.plural(/$/, 's'); - inflector.singular(/s$/i, ''); - ``` - - Creating an inflector with a nondefault ruleset. - - ```javascript - var rules = { - plurals: [ /$/, 's' ], - singular: [ /\s$/, '' ], - irregularPairs: [ - [ 'cow', 'kine' ] - ], - uncountable: [ 'fish' ] - }; - - var inflector = new Ember.Inflector(rules); - ``` - - @class Inflector - @namespace Ember -*/ -function Inflector(ruleSet) { - ruleSet = ruleSet || {}; - ruleSet.uncountable = ruleSet.uncountable || {}; - ruleSet.irregularPairs = ruleSet.irregularPairs || {}; - - var rules = this.rules = { - plurals: ruleSet.plurals || [], - singular: ruleSet.singular || [], - irregular: {}, - irregularInverse: {}, - uncountable: {} - }; - - loadUncountable(rules, ruleSet.uncountable); - loadIrregular(rules, ruleSet.irregularPairs); -} - -Inflector.prototype = { - /** - @method plural - @param {RegExp} regex - @param {String} string - */ - plural: function(regex, string) { - this.rules.plurals.push([regex, string.toLowerCase()]); - }, - - /** - @method singular - @param {RegExp} regex - @param {String} string - */ - singular: function(regex, string) { - this.rules.singular.push([regex, string.toLowerCase()]); - }, - - /** - @method uncountable - @param {String} regex - */ - uncountable: function(string) { - loadUncountable(this.rules, [string.toLowerCase()]); - }, - - /** - @method irregular - @param {String} singular - @param {String} plural - */ - irregular: function (singular, plural) { - loadIrregular(this.rules, [[singular, plural]]); - }, - - /** - @method pluralize - @param {String} word - */ - pluralize: function(word) { - return this.inflect(word, this.rules.plurals, this.rules.irregular); - }, - - /** - @method singularize - @param {String} word - */ - singularize: function(word) { - return this.inflect(word, this.rules.singular, this.rules.irregularInverse); - }, - - /** - @protected - - @method inflect - @param {String} word - @param {Object} typeRules - @param {Object} irregular - */ - inflect: function(word, typeRules, irregular) { - var inflection, substitution, result, lowercase, isBlank, - isUncountable, isIrregular, isIrregularInverse, rule; - - isBlank = BLANK_REGEX.test(word); - - if (isBlank) { - return word; - } - - lowercase = word.toLowerCase(); - - isUncountable = this.rules.uncountable[lowercase]; - - if (isUncountable) { - return word; - } - - isIrregular = irregular && irregular[lowercase]; - - if (isIrregular) { - return isIrregular; - } - - for (var i = typeRules.length, min = 0; i > min; i--) { - inflection = typeRules[i-1]; - rule = inflection[0]; - - if (rule.test(word)) { - break; - } - } - - inflection = inflection || []; - - rule = inflection[0]; - substitution = inflection[1]; - - result = word.replace(rule, substitution); - - return result; - } -}; - -Ember.Inflector = Inflector; - -})(); - - - -(function() { -Ember.Inflector.defaultRules = { - plurals: [ - [/$/, 's'], - [/s$/i, 's'], - [/^(ax|test)is$/i, '$1es'], - [/(octop|vir)us$/i, '$1i'], - [/(octop|vir)i$/i, '$1i'], - [/(alias|status)$/i, '$1es'], - [/(bu)s$/i, '$1ses'], - [/(buffal|tomat)o$/i, '$1oes'], - [/([ti])um$/i, '$1a'], - [/([ti])a$/i, '$1a'], - [/sis$/i, 'ses'], - [/(?:([^f])fe|([lr])f)$/i, '$1$2ves'], - [/(hive)$/i, '$1s'], - [/([^aeiouy]|qu)y$/i, '$1ies'], - [/(x|ch|ss|sh)$/i, '$1es'], - [/(matr|vert|ind)(?:ix|ex)$/i, '$1ices'], - [/^(m|l)ouse$/i, '$1ice'], - [/^(m|l)ice$/i, '$1ice'], - [/^(ox)$/i, '$1en'], - [/^(oxen)$/i, '$1'], - [/(quiz)$/i, '$1zes'] - ], - - singular: [ - [/s$/i, ''], - [/(ss)$/i, '$1'], - [/(n)ews$/i, '$1ews'], - [/([ti])a$/i, '$1um'], - [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '$1sis'], - [/(^analy)(sis|ses)$/i, '$1sis'], - [/([^f])ves$/i, '$1fe'], - [/(hive)s$/i, '$1'], - [/(tive)s$/i, '$1'], - [/([lr])ves$/i, '$1f'], - [/([^aeiouy]|qu)ies$/i, '$1y'], - [/(s)eries$/i, '$1eries'], - [/(m)ovies$/i, '$1ovie'], - [/(x|ch|ss|sh)es$/i, '$1'], - [/^(m|l)ice$/i, '$1ouse'], - [/(bus)(es)?$/i, '$1'], - [/(o)es$/i, '$1'], - [/(shoe)s$/i, '$1'], - [/(cris|test)(is|es)$/i, '$1is'], - [/^(a)x[ie]s$/i, '$1xis'], - [/(octop|vir)(us|i)$/i, '$1us'], - [/(alias|status)(es)?$/i, '$1'], - [/^(ox)en/i, '$1'], - [/(vert|ind)ices$/i, '$1ex'], - [/(matr)ices$/i, '$1ix'], - [/(quiz)zes$/i, '$1'], - [/(database)s$/i, '$1'] - ], - - irregularPairs: [ - ['person', 'people'], - ['man', 'men'], - ['child', 'children'], - ['sex', 'sexes'], - ['move', 'moves'], - ['cow', 'kine'], - ['zombie', 'zombies'] - ], - - uncountable: [ - 'equipment', - 'information', - 'rice', - 'money', - 'species', - 'series', - 'fish', - 'sheep', - 'jeans', - 'police' - ] -}; - -})(); - - - -(function() { -if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) { - /** - See {{#crossLink "Ember.String/pluralize"}}{{/crossLink}} - - @method pluralize - @for String - */ - String.prototype.pluralize = function() { - return Ember.String.pluralize(this); - }; - - /** - See {{#crossLink "Ember.String/singularize"}}{{/crossLink}} - - @method singularize - @for String - */ - String.prototype.singularize = function() { - return Ember.String.singularize(this); - }; -} - -})(); - - - -(function() { -Ember.Inflector.inflector = new Ember.Inflector(Ember.Inflector.defaultRules); - -})(); - - - -(function() { - -})(); - -(function() { -/** - @module ember-data -*/ - -var get = Ember.get; -var forEach = Ember.EnumerableUtils.forEach; - -DS.ActiveModelSerializer = DS.RESTSerializer.extend({ - // SERIALIZE - - /** - Converts camelcased attributes to underscored when serializing. - - @method keyForAttribute - @param {String} attribute - @returns String - */ - keyForAttribute: function(attr) { - return Ember.String.decamelize(attr); - }, - - /** - Underscores relationship names and appends "_id" or "_ids" when serializing - relationship keys. - - @method keyForRelationship - @param {String} key - @param {String} kind - @returns String - */ - keyForRelationship: function(key, kind) { - key = Ember.String.decamelize(key); - if (kind === "belongsTo") { - return key + "_id"; - } else if (kind === "hasMany") { - return Ember.String.singularize(key) + "_ids"; - } else { - return key; - } - }, - - /** - Does not serialize hasMany relationships by default. - */ - serializeHasMany: Ember.K, - - /** - Underscores the JSON root keys when serializing. - - @method serializeIntoHash - @param {Object} hash - @param {subclass of DS.Model} type - @param {DS.Model} record - @param {Object} options - */ - serializeIntoHash: function(data, type, record, options) { - var root = Ember.String.decamelize(type.typeKey); - data[root] = this.serialize(record, options); - }, - - /** - Serializes a polymorphic type as a fully capitalized model name. - - @method serializePolymorphicType - @param {DS.Model} record - @param {Object} json - @param relationship - */ - serializePolymorphicType: function(record, json, relationship) { - var key = relationship.key, - belongsTo = get(record, key); - key = this.keyForAttribute(key); - json[key + "_type"] = Ember.String.capitalize(belongsTo.constructor.typeKey); - }, - - // EXTRACT - - /** - Extracts the model typeKey from underscored root objects. - - @method typeForRoot - @param {String} root - @returns String the model's typeKey - */ - typeForRoot: function(root) { - var camelized = Ember.String.camelize(root); - return Ember.String.singularize(camelized); - }, - - /** - Add extra step to `DS.RESTSerializer.normalize` so links are - normalized. - - If your payload looks like this - - ```js - { - "post": { - "id": 1, - "title": "Rails is omakase", - "links": { "flagged_comments": "api/comments/flagged" } - } - } - ``` - The normalized version would look like this - - ```js - { - "post": { - "id": 1, - "title": "Rails is omakase", - "links": { "flaggedComments": "api/comments/flagged" } - } - } - ``` - - @method normalize - @param {subclass of DS.Model} type - @param {Object} hash - @param {String} prop - @returns Object - */ - - normalize: function(type, hash, prop) { - this.normalizeLinks(hash); - - return this._super(type, hash, prop); - }, - - /** - Convert `snake_cased` links to `camelCase` - - @method normalizeLinks - @param {Object} hash - */ - - normalizeLinks: function(data){ - if (data.links) { - var links = data.links; - - for (var link in links) { - var camelizedLink = Ember.String.camelize(link); - - if (camelizedLink !== link) { - links[camelizedLink] = links[link]; - delete links[link]; - } - } - } - }, - - /** - Normalize the polymorphic type from the JSON. - - Normalize: - ```js - { - id: "1" - minion: { type: "evil_minion", id: "12"} - } - ``` - - To: - ```js - { - id: "1" - minion: { type: "evilMinion", id: "12"} - } - ``` - - @method normalizeRelationships - @private - */ - normalizeRelationships: function(type, hash) { - var payloadKey, payload; - - if (this.keyForRelationship) { - type.eachRelationship(function(key, relationship) { - if (relationship.options.polymorphic) { - payloadKey = this.keyForAttribute(key); - payload = hash[payloadKey]; - if (payload && payload.type) { - payload.type = this.typeForRoot(payload.type); - } else if (payload && relationship.kind === "hasMany") { - var self = this; - forEach(payload, function(single) { - single.type = self.typeForRoot(single.type); - }); - } - } else { - payloadKey = this.keyForRelationship(key, relationship.kind); - payload = hash[payloadKey]; - } - - hash[key] = payload; - - if (key !== payloadKey) { - delete hash[payloadKey]; - } - }, this); - } - } -}); - -})(); - - - -(function() { -var get = Ember.get; -var forEach = Ember.EnumerableUtils.forEach; - -/** - The EmbeddedRecordsMixin allows you to add embedded record support to your - serializers. - To set up embedded records, you include the mixin into the serializer and then - define your embedded relations. - - ```js - App.PostSerializer = DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - comments: {embedded: 'always'} - } - }) - ``` - - Currently only `{embedded: 'always'}` records are supported. - - @class EmbeddedRecordsMixin - @namespace DS -*/ -DS.EmbeddedRecordsMixin = Ember.Mixin.create({ - - /** - Serialize has-may relationship when it is configured as embedded objects. - - @method serializeHasMany - */ - serializeHasMany: function(record, json, relationship) { - var key = relationship.key, - attrs = get(this, 'attrs'), - embed = attrs && attrs[key] && attrs[key].embedded === 'always'; - - if (embed) { - json[this.keyForAttribute(key)] = get(record, key).map(function(relation) { - var data = relation.serialize(), - primaryKey = get(this, 'primaryKey'); - - data[primaryKey] = get(relation, primaryKey); - - return data; - }, this); - } - }, - - /** - Extract embedded objects out of the payload for a single object - and add them as sideloaded objects instead. - - @method extractSingle - */ - extractSingle: function(store, primaryType, payload, recordId, requestType) { - var root = this.keyForAttribute(primaryType.typeKey), - partial = payload[root]; - - updatePayloadWithEmbedded(store, this, primaryType, partial, payload); - - return this._super(store, primaryType, payload, recordId, requestType); - }, - - /** - Extract embedded objects out of a standard payload - and add them as sideloaded objects instead. - - @method extractArray - */ - extractArray: function(store, type, payload) { - var root = this.keyForAttribute(type.typeKey), - partials = payload[Ember.String.pluralize(root)]; - - forEach(partials, function(partial) { - updatePayloadWithEmbedded(store, this, type, partial, payload); - }, this); - - return this._super(store, type, payload); - } -}); - -function updatePayloadWithEmbedded(store, serializer, type, partial, payload) { - var attrs = get(serializer, 'attrs'); - - if (!attrs) { - return; - } - - type.eachRelationship(function(key, relationship) { - var expandedKey, embeddedTypeKey, attribute, ids, - config = attrs[key], - serializer = store.serializerFor(relationship.type.typeKey), - primaryKey = get(serializer, "primaryKey"); - - if (relationship.kind !== "hasMany") { - return; - } - - if (config && (config.embedded === 'always' || config.embedded === 'load')) { - // underscore forces the embedded records to be side loaded. - // it is needed when main type === relationship.type - embeddedTypeKey = '_' + Ember.String.pluralize(relationship.type.typeKey); - expandedKey = this.keyForRelationship(key, relationship.kind); - attribute = this.keyForAttribute(key); - ids = []; - - if (!partial[attribute]) { - return; - } - - payload[embeddedTypeKey] = payload[embeddedTypeKey] || []; - - forEach(partial[attribute], function(data) { - var embeddedType = store.modelFor(relationship.type.typeKey); - updatePayloadWithEmbedded(store, serializer, embeddedType, data, payload); - ids.push(data[primaryKey]); - payload[embeddedTypeKey].push(data); - }); - - partial[expandedKey] = ids; - delete partial[attribute]; - } - }, serializer); -} -})(); - - - -(function() { -/** - @module ember-data -*/ - -var forEach = Ember.EnumerableUtils.forEach; - -/** - The ActiveModelAdapter is a subclass of the RESTAdapter designed to integrate - with a JSON API that uses an underscored naming convention instead of camelcasing. - It has been designed to work out of the box with the - [active_model_serializers](http://github.com/rails-api/active_model_serializers) - Ruby gem. - - This adapter extends the DS.RESTAdapter by making consistent use of the camelization, - decamelization and pluralization methods to normalize the serialized JSON into a - format that is compatible with a conventional Rails backend and Ember Data. - - ## JSON Structure - - The ActiveModelAdapter expects the JSON returned from your server to follow - the REST adapter conventions substituting underscored keys for camelcased ones. - - ### Conventional Names - - Attribute names in your JSON payload should be the underscored versions of - the attributes in your Ember.js models. - - For example, if you have a `Person` model: - - ```js - App.FamousPerson = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - occupation: DS.attr('string') - }); - ``` - - The JSON returned should look like this: - - ```js - { - "famous_person": { - "first_name": "Barack", - "last_name": "Obama", - "occupation": "President" - } - } - ``` - - @class ActiveModelAdapter - @constructor - @namespace DS - @extends DS.Adapter -**/ - -DS.ActiveModelAdapter = DS.RESTAdapter.extend({ - defaultSerializer: '_ams', - /** - The ActiveModelAdapter overrides the `pathForType` method to build - underscored URLs by decamelizing and pluralizing the object type name. - - ```js - this.pathForType("famousPerson"); - //=> "famous_people" - ``` - - @method pathForType - @param {String} type - @returns String - */ - pathForType: function(type) { - var decamelized = Ember.String.decamelize(type); - return Ember.String.pluralize(decamelized); - }, - - /** - The ActiveModelAdapter overrides the `ajaxError` method - to return a DS.InvalidError for all 422 Unprocessable Entity - responses. - - A 422 HTTP response from the server generally implies that the request - was well formed but the API was unable to process it because the - content was not semantically correct or meaningful per the API. - - For more information on 422 HTTP Error code see 11.2 WebDAV RFC 4918 - https://tools.ietf.org/html/rfc4918#section-11.2 - - @method ajaxError - @param jqXHR - @returns error - */ - ajaxError: function(jqXHR) { - var error = this._super(jqXHR); - - if (jqXHR && jqXHR.status === 422) { - var jsonErrors = Ember.$.parseJSON(jqXHR.responseText)["errors"], - errors = {}; - - forEach(Ember.keys(jsonErrors), function(key) { - errors[Ember.String.camelize(key)] = jsonErrors[key]; - }); - - return new DS.InvalidError(errors); - } else { - return error; - } - } -}); - -})(); - - - -(function() { - -})(); - - - -(function() { -Ember.onLoad('Ember.Application', function(Application) { - Application.initializer({ - name: "activeModelAdapter", - - initialize: function(container, application) { - application.register('serializer:_ams', DS.ActiveModelSerializer); - application.register('adapter:_ams', DS.ActiveModelAdapter); - } - }); -}); - -})(); - - - -(function() { - -})(); - - -})(); diff --git a/handling-spring-static-resources/src/main/webapp/js/ember.js b/handling-spring-static-resources/src/main/webapp/js/ember.js deleted file mode 100644 index 44c4687e4a..0000000000 --- a/handling-spring-static-resources/src/main/webapp/js/ember.js +++ /dev/null @@ -1,47755 +0,0 @@ -/*! - * @overview Ember - JavaScript Application Framework - * @copyright Copyright 2011-2014 Tilde Inc. and contributors - * Portions Copyright 2006-2011 Strobe Inc. - * Portions Copyright 2008-2011 Apple Inc. All rights reserved. - * @license Licensed under MIT license - * See https://raw.github.com/emberjs/ember.js/master/LICENSE - * @version 1.7.0 - */ - -(function() { -var define, requireModule, require, requirejs, Ember; - -(function() { - Ember = this.Ember = this.Ember || {}; - if (typeof Ember === 'undefined') { Ember = {} }; - - if (typeof Ember.__loader === 'undefined') { - var registry = {}, seen = {}; - - define = function(name, deps, callback) { - registry[name] = { deps: deps, callback: callback }; - }; - - requirejs = require = requireModule = function(name) { - if (seen.hasOwnProperty(name)) { return seen[name]; } - seen[name] = {}; - - if (!registry[name]) { - throw new Error("Could not find module " + name); - } - - var mod = registry[name], - deps = mod.deps, - callback = mod.callback, - reified = [], - exports; - - for (var i=0, l=deps.length; i 3 ? slice.call(arguments, 3) : undefined; - if (!this.currentInstance) { createAutorun(this); } - return this.currentInstance.schedule(queueName, target, method, args, false, stack); - }, - - deferOnce: function(queueName, target, method /* , args */) { - if (!method) { - method = target; - target = null; - } - - if (isString(method)) { - method = target[method]; - } - - var stack = this.DEBUG ? new Error() : undefined, - args = arguments.length > 3 ? slice.call(arguments, 3) : undefined; - if (!this.currentInstance) { createAutorun(this); } - return this.currentInstance.schedule(queueName, target, method, args, true, stack); - }, - - setTimeout: function() { - var args = slice.call(arguments), - length = args.length, - method, wait, target, - methodOrTarget, methodOrWait, methodOrArgs; - - if (length === 0) { - return; - } else if (length === 1) { - method = args.shift(); - wait = 0; - } else if (length === 2) { - methodOrTarget = args[0]; - methodOrWait = args[1]; - - if (isFunction(methodOrWait) || isFunction(methodOrTarget[methodOrWait])) { - target = args.shift(); - method = args.shift(); - wait = 0; - } else if (isCoercableNumber(methodOrWait)) { - method = args.shift(); - wait = args.shift(); - } else { - method = args.shift(); - wait = 0; - } - } else { - var last = args[args.length - 1]; - - if (isCoercableNumber(last)) { - wait = args.pop(); - } else { - wait = 0; - } - - methodOrTarget = args[0]; - methodOrArgs = args[1]; - - if (isFunction(methodOrArgs) || (isString(methodOrArgs) && - methodOrTarget !== null && - methodOrArgs in methodOrTarget)) { - target = args.shift(); - method = args.shift(); - } else { - method = args.shift(); - } - } - - var executeAt = (+new Date()) + parseInt(wait, 10); - - if (isString(method)) { - method = target[method]; - } - - var onError = getOnError(this.options); - - function fn() { - if (onError) { - try { - method.apply(target, args); - } catch (e) { - onError(e); - } - } else { - method.apply(target, args); - } - } - - // find position to insert - var i = searchTimer(executeAt, timers); - - timers.splice(i, 0, executeAt, fn); - - updateLaterTimer(this, executeAt, wait); - - return fn; - }, - - throttle: function(target, method /* , args, wait, [immediate] */) { - var self = this, - args = arguments, - immediate = pop.call(args), - wait, - throttler, - index, - timer; - - if (isNumber(immediate) || isString(immediate)) { - wait = immediate; - immediate = true; - } else { - wait = pop.call(args); - } - - wait = parseInt(wait, 10); - - index = findThrottler(target, method, this._throttlers); - if (index > -1) { return this._throttlers[index]; } // throttled - - timer = global.setTimeout(function() { - if (!immediate) { - self.run.apply(self, args); - } - var index = findThrottler(target, method, self._throttlers); - if (index > -1) { - self._throttlers.splice(index, 1); - } - }, wait); - - if (immediate) { - self.run.apply(self, args); - } - - throttler = [target, method, timer]; - - this._throttlers.push(throttler); - - return throttler; - }, - - debounce: function(target, method /* , args, wait, [immediate] */) { - var self = this, - args = arguments, - immediate = pop.call(args), - wait, - index, - debouncee, - timer; - - if (isNumber(immediate) || isString(immediate)) { - wait = immediate; - immediate = false; - } else { - wait = pop.call(args); - } - - wait = parseInt(wait, 10); - // Remove debouncee - index = findDebouncee(target, method, this._debouncees); - - if (index > -1) { - debouncee = this._debouncees[index]; - this._debouncees.splice(index, 1); - clearTimeout(debouncee[2]); - } - - timer = global.setTimeout(function() { - if (!immediate) { - self.run.apply(self, args); - } - var index = findDebouncee(target, method, self._debouncees); - if (index > -1) { - self._debouncees.splice(index, 1); - } - }, wait); - - if (immediate && index === -1) { - self.run.apply(self, args); - } - - debouncee = [target, method, timer]; - - self._debouncees.push(debouncee); - - return debouncee; - }, - - cancelTimers: function() { - var clearItems = function(item) { - clearTimeout(item[2]); - }; - - each(this._throttlers, clearItems); - this._throttlers = []; - - each(this._debouncees, clearItems); - this._debouncees = []; - - if (this._laterTimer) { - clearTimeout(this._laterTimer); - this._laterTimer = null; - } - timers = []; - - if (this._autorun) { - clearTimeout(this._autorun); - this._autorun = null; - } - }, - - hasTimers: function() { - return !!timers.length || !!this._debouncees.length || !!this._throttlers.length || this._autorun; - }, - - cancel: function(timer) { - var timerType = typeof timer; - - if (timer && timerType === 'object' && timer.queue && timer.method) { // we're cancelling a deferOnce - return timer.queue.cancel(timer); - } else if (timerType === 'function') { // we're cancelling a setTimeout - for (var i = 0, l = timers.length; i < l; i += 2) { - if (timers[i + 1] === timer) { - timers.splice(i, 2); // remove the two elements - return true; - } - } - } else if (Object.prototype.toString.call(timer) === "[object Array]"){ // we're cancelling a throttle or debounce - return this._cancelItem(findThrottler, this._throttlers, timer) || - this._cancelItem(findDebouncee, this._debouncees, timer); - } else { - return; // timer was null or not a timer - } - }, - - _cancelItem: function(findMethod, array, timer){ - var item, - index; - - if (timer.length < 3) { return false; } - - index = findMethod(timer[0], timer[1], array); - - if(index > -1) { - - item = array[index]; - - if(item[2] === timer[2]){ - array.splice(index, 1); - clearTimeout(timer[2]); - return true; - } - } - - return false; - } - }; - - Backburner.prototype.schedule = Backburner.prototype.defer; - Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce; - Backburner.prototype.later = Backburner.prototype.setTimeout; - - if (needsIETryCatchFix) { - var originalRun = Backburner.prototype.run; - Backburner.prototype.run = wrapInTryCatch(originalRun); - - var originalEnd = Backburner.prototype.end; - Backburner.prototype.end = wrapInTryCatch(originalEnd); - } - - function wrapInTryCatch(func) { - return function () { - try { - return func.apply(this, arguments); - } catch (e) { - throw e; - } - }; - } - - function getOnError(options) { - return options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]); - } - - - function createAutorun(backburner) { - backburner.begin(); - backburner._autorun = global.setTimeout(function() { - backburner._autorun = null; - backburner.end(); - }); - } - - function updateLaterTimer(self, executeAt, wait) { - if (!self._laterTimer || executeAt < self._laterTimerExpiresAt) { - self._laterTimer = global.setTimeout(function() { - self._laterTimer = null; - self._laterTimerExpiresAt = null; - executeTimers(self); - }, wait); - self._laterTimerExpiresAt = executeAt; - } - } - - function executeTimers(self) { - var now = +new Date(), - time, fns, i, l; - - self.run(function() { - i = searchTimer(now, timers); - - fns = timers.splice(0, i); - - for (i = 1, l = fns.length; i < l; i += 2) { - self.schedule(self.options.defaultQueue, null, fns[i]); - } - }); - - if (timers.length) { - updateLaterTimer(self, timers[0], timers[0] - now); - } - } - - function findDebouncee(target, method, debouncees) { - return findItem(target, method, debouncees); - } - - function findThrottler(target, method, throttlers) { - return findItem(target, method, throttlers); - } - - function findItem(target, method, collection) { - var item, - index = -1; - - for (var i = 0, l = collection.length; i < l; i++) { - item = collection[i]; - if (item[0] === target && item[1] === method) { - index = i; - break; - } - } - - return index; - } - - function searchTimer(time, timers) { - var start = 0, - end = timers.length - 2, - middle, l; - - while (start < end) { - // since timers is an array of pairs 'l' will always - // be an integer - l = (end - start) / 2; - - // compensate for the index in case even number - // of pairs inside timers - middle = start + l - (l % 2); - - if (time >= timers[middle]) { - start = middle + 2; - } else { - end = middle; - } - } - - return (time >= timers[start]) ? start + 2 : start; - } - - __exports__.Backburner = Backburner; - }); -define("backburner/deferred_action_queues", - ["backburner/utils","backburner/queue","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Utils = __dependency1__["default"]; - var Queue = __dependency2__.Queue; - - var each = Utils.each, - isString = Utils.isString; - - function DeferredActionQueues(queueNames, options) { - var queues = this.queues = {}; - this.queueNames = queueNames = queueNames || []; - - this.options = options; - - each(queueNames, function(queueName) { - queues[queueName] = new Queue(this, queueName, options); - }); - } - - DeferredActionQueues.prototype = { - queueNames: null, - queues: null, - options: null, - - schedule: function(queueName, target, method, args, onceFlag, stack) { - var queues = this.queues, - queue = queues[queueName]; - - if (!queue) { throw new Error("You attempted to schedule an action in a queue (" + queueName + ") that doesn't exist"); } - - if (onceFlag) { - return queue.pushUnique(target, method, args, stack); - } else { - return queue.push(target, method, args, stack); - } - }, - - invoke: function(target, method, args, _) { - if (args && args.length > 0) { - method.apply(target, args); - } else { - method.call(target); - } - }, - - invokeWithOnError: function(target, method, args, onError) { - try { - if (args && args.length > 0) { - method.apply(target, args); - } else { - method.call(target); - } - } catch(error) { - onError(error); - } - }, - - flush: function() { - var queues = this.queues, - queueNames = this.queueNames, - queueName, queue, queueItems, priorQueueNameIndex, - queueNameIndex = 0, numberOfQueues = queueNames.length, - options = this.options, - onError = options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]), - invoke = onError ? this.invokeWithOnError : this.invoke; - - outerloop: - while (queueNameIndex < numberOfQueues) { - queueName = queueNames[queueNameIndex]; - queue = queues[queueName]; - queueItems = queue._queueBeingFlushed = queue._queue.slice(); - queue._queue = []; - - var queueOptions = queue.options, // TODO: write a test for this - before = queueOptions && queueOptions.before, - after = queueOptions && queueOptions.after, - target, method, args, stack, - queueIndex = 0, numberOfQueueItems = queueItems.length; - - if (numberOfQueueItems && before) { before(); } - - while (queueIndex < numberOfQueueItems) { - target = queueItems[queueIndex]; - method = queueItems[queueIndex+1]; - args = queueItems[queueIndex+2]; - stack = queueItems[queueIndex+3]; // Debugging assistance - - if (isString(method)) { method = target[method]; } - - // method could have been nullified / canceled during flush - if (method) { - invoke(target, method, args, onError); - } - - queueIndex += 4; - } - - queue._queueBeingFlushed = null; - if (numberOfQueueItems && after) { after(); } - - if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) { - queueNameIndex = priorQueueNameIndex; - continue outerloop; - } - - queueNameIndex++; - } - } - }; - - function indexOfPriorQueueWithActions(daq, currentQueueIndex) { - var queueName, queue; - - for (var i = 0, l = currentQueueIndex; i <= l; i++) { - queueName = daq.queueNames[i]; - queue = daq.queues[queueName]; - if (queue._queue.length) { return i; } - } - - return -1; - } - - __exports__.DeferredActionQueues = DeferredActionQueues; - }); -define("backburner/queue", - ["exports"], - function(__exports__) { - "use strict"; - function Queue(daq, name, options) { - this.daq = daq; - this.name = name; - this.globalOptions = options; - this.options = options[name]; - this._queue = []; - } - - Queue.prototype = { - daq: null, - name: null, - options: null, - onError: null, - _queue: null, - - push: function(target, method, args, stack) { - var queue = this._queue; - queue.push(target, method, args, stack); - return {queue: this, target: target, method: method}; - }, - - pushUnique: function(target, method, args, stack) { - var queue = this._queue, currentTarget, currentMethod, i, l; - - for (i = 0, l = queue.length; i < l; i += 4) { - currentTarget = queue[i]; - currentMethod = queue[i+1]; - - if (currentTarget === target && currentMethod === method) { - queue[i+2] = args; // replace args - queue[i+3] = stack; // replace stack - return {queue: this, target: target, method: method}; - } - } - - queue.push(target, method, args, stack); - return {queue: this, target: target, method: method}; - }, - - // TODO: remove me, only being used for Ember.run.sync - flush: function() { - var queue = this._queue, - globalOptions = this.globalOptions, - options = this.options, - before = options && options.before, - after = options && options.after, - onError = globalOptions.onError || (globalOptions.onErrorTarget && globalOptions.onErrorTarget[globalOptions.onErrorMethod]), - target, method, args, stack, i, l = queue.length; - - if (l && before) { before(); } - for (i = 0; i < l; i += 4) { - target = queue[i]; - method = queue[i+1]; - args = queue[i+2]; - stack = queue[i+3]; // Debugging assistance - - // TODO: error handling - if (args && args.length > 0) { - if (onError) { - try { - method.apply(target, args); - } catch (e) { - onError(e); - } - } else { - method.apply(target, args); - } - } else { - if (onError) { - try { - method.call(target); - } catch(e) { - onError(e); - } - } else { - method.call(target); - } - } - } - if (l && after) { after(); } - - // check if new items have been added - if (queue.length > l) { - this._queue = queue.slice(l); - this.flush(); - } else { - this._queue.length = 0; - } - }, - - cancel: function(actionToCancel) { - var queue = this._queue, currentTarget, currentMethod, i, l; - - for (i = 0, l = queue.length; i < l; i += 4) { - currentTarget = queue[i]; - currentMethod = queue[i+1]; - - if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) { - queue.splice(i, 4); - return true; - } - } - - // if not found in current queue - // could be in the queue that is being flushed - queue = this._queueBeingFlushed; - if (!queue) { - return; - } - for (i = 0, l = queue.length; i < l; i += 4) { - currentTarget = queue[i]; - currentMethod = queue[i+1]; - - if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) { - // don't mess with array during flush - // just nullify the method - queue[i+1] = null; - return true; - } - } - } - }; - - __exports__.Queue = Queue; - }); -define("backburner/utils", - ["exports"], - function(__exports__) { - "use strict"; - __exports__["default"] = { - each: function(collection, callback) { - for (var i = 0; i < collection.length; i++) { - callback(collection[i]); - } - }, - - isString: function(suspect) { - return typeof suspect === 'string'; - }, - - isFunction: function(suspect) { - return typeof suspect === 'function'; - }, - - isNumber: function(suspect) { - return typeof suspect === 'number'; - } - }; - }); - -define("calculateVersion", - [], - function() { - "use strict"; - 'use strict'; - - var fs = require('fs'); - var path = require('path'); - - module.exports = function () { - var packageVersion = require('../package.json').version; - var output = [packageVersion]; - var gitPath = path.join(__dirname,'..','.git'); - var headFilePath = path.join(gitPath, 'HEAD'); - - if (packageVersion.indexOf('+') > -1) { - try { - if (fs.existsSync(headFilePath)) { - var headFile = fs.readFileSync(headFilePath, {encoding: 'utf8'}); - var branchName = headFile.split('/').slice(-1)[0].trim(); - var refPath = headFile.split(' ')[1]; - var branchSHA; - - if (refPath) { - var branchPath = path.join(gitPath, refPath.trim()); - branchSHA = fs.readFileSync(branchPath); - } else { - branchSHA = branchName; - } - - output.push(branchSHA.slice(0,10)); - } - } catch (err) { - console.error(err.stack); - } - return output.join('.'); - } else { - return packageVersion; - } - }; - }); -define("container", - ["container/container","exports"], - function(__dependency1__, __exports__) { - "use strict"; - /* - Public api for the container is still in flux. - The public api, specified on the application namespace should be considered the stable api. - // @module container - @private - */ - - /* - Flag to enable/disable model factory injections (disabled by default) - If model factory injections are enabled, models should not be - accessed globally (only through `container.lookupFactory('model:modelName'))`); - */ - Ember.MODEL_FACTORY_INJECTIONS = false; - - if (Ember.ENV && typeof Ember.ENV.MODEL_FACTORY_INJECTIONS !== 'undefined') { - Ember.MODEL_FACTORY_INJECTIONS = !!Ember.ENV.MODEL_FACTORY_INJECTIONS; - } - - - var Container = __dependency1__["default"]; - - __exports__["default"] = Container; - }); -define("container/container", - ["container/inheriting_dict","ember-metal/core","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var InheritingDict = __dependency1__["default"]; - var Ember = __dependency2__["default"]; - // Ember.assert - - // A lightweight container that helps to assemble and decouple components. - // Public api for the container is still in flux. - // The public api, specified on the application namespace should be considered the stable api. - function Container(parent) { - this.parent = parent; - this.children = []; - - this.resolver = parent && parent.resolver || function() {}; - - this.registry = new InheritingDict(parent && parent.registry); - this.cache = new InheritingDict(parent && parent.cache); - this.factoryCache = new InheritingDict(parent && parent.factoryCache); - this.resolveCache = new InheritingDict(parent && parent.resolveCache); - this.typeInjections = new InheritingDict(parent && parent.typeInjections); - this.injections = {}; - - this.factoryTypeInjections = new InheritingDict(parent && parent.factoryTypeInjections); - this.factoryInjections = {}; - - this._options = new InheritingDict(parent && parent._options); - this._typeOptions = new InheritingDict(parent && parent._typeOptions); - } - - Container.prototype = { - - /** - @property parent - @type Container - @default null - */ - parent: null, - - /** - @property children - @type Array - @default [] - */ - children: null, - - /** - @property resolver - @type function - */ - resolver: null, - - /** - @property registry - @type InheritingDict - */ - registry: null, - - /** - @property cache - @type InheritingDict - */ - cache: null, - - /** - @property typeInjections - @type InheritingDict - */ - typeInjections: null, - - /** - @property injections - @type Object - @default {} - */ - injections: null, - - /** - @private - - @property _options - @type InheritingDict - @default null - */ - _options: null, - - /** - @private - - @property _typeOptions - @type InheritingDict - */ - _typeOptions: null, - - /** - Returns a new child of the current container. These children are configured - to correctly inherit from the current container. - - @method child - @return {Container} - */ - child: function() { - var container = new Container(this); - this.children.push(container); - return container; - }, - - /** - Sets a key-value pair on the current container. If a parent container, - has the same key, once set on a child, the parent and child will diverge - as expected. - - @method set - @param {Object} object - @param {String} key - @param {any} value - */ - set: function(object, key, value) { - object[key] = value; - }, - - /** - Registers a factory for later injection. - - Example: - - ```javascript - var container = new Container(); - - container.register('model:user', Person, {singleton: false }); - container.register('fruit:favorite', Orange); - container.register('communication:main', Email, {singleton: false}); - ``` - - @method register - @param {String} fullName - @param {Function} factory - @param {Object} options - */ - register: function(fullName, factory, options) { - - if (factory === undefined) { - throw new TypeError('Attempting to register an unknown factory: `' + fullName + '`'); - } - - var normalizedName = this.normalize(fullName); - - if (this.cache.has(normalizedName)) { - throw new Error('Cannot re-register: `' + fullName +'`, as it has already been looked up.'); - } - - this.registry.set(normalizedName, factory); - this._options.set(normalizedName, options || {}); - }, - - /** - Unregister a fullName - - ```javascript - var container = new Container(); - container.register('model:user', User); - - container.lookup('model:user') instanceof User //=> true - - container.unregister('model:user') - container.lookup('model:user') === undefined //=> true - ``` - - @method unregister - @param {String} fullName - */ - unregister: function(fullName) { - - var normalizedName = this.normalize(fullName); - - this.registry.remove(normalizedName); - this.cache.remove(normalizedName); - this.factoryCache.remove(normalizedName); - this.resolveCache.remove(normalizedName); - this._options.remove(normalizedName); - }, - - /** - Given a fullName return the corresponding factory. - - By default `resolve` will retrieve the factory from - its container's registry. - - ```javascript - var container = new Container(); - container.register('api:twitter', Twitter); - - container.resolve('api:twitter') // => Twitter - ``` - - Optionally the container can be provided with a custom resolver. - If provided, `resolve` will first provide the custom resolver - the opportunity to resolve the fullName, otherwise it will fallback - to the registry. - - ```javascript - var container = new Container(); - container.resolver = function(fullName) { - // lookup via the module system of choice - }; - - // the twitter factory is added to the module system - container.resolve('api:twitter') // => Twitter - ``` - - @method resolve - @param {String} fullName - @return {Function} fullName's factory - */ - resolve: function(fullName) { - return resolve(this, this.normalize(fullName)); - }, - - /** - A hook that can be used to describe how the resolver will - attempt to find the factory. - - For example, the default Ember `.describe` returns the full - class name (including namespace) where Ember's resolver expects - to find the `fullName`. - - @method describe - @param {String} fullName - @return {string} described fullName - */ - describe: function(fullName) { - return fullName; - }, - - /** - A hook to enable custom fullName normalization behaviour - - @method normalize - @param {String} fullName - @return {string} normalized fullName - */ - normalize: function(fullName) { - return fullName; - }, - - /** - @method makeToString - - @param {any} factory - @param {string} fullName - @return {function} toString function - */ - makeToString: function(factory, fullName) { - return factory.toString(); - }, - - /** - Given a fullName return a corresponding instance. - - The default behaviour is for lookup to return a singleton instance. - The singleton is scoped to the container, allowing multiple containers - to all have their own locally scoped singletons. - - ```javascript - var container = new Container(); - container.register('api:twitter', Twitter); - - var twitter = container.lookup('api:twitter'); - - twitter instanceof Twitter; // => true - - // by default the container will return singletons - var twitter2 = container.lookup('api:twitter'); - twitter2 instanceof Twitter; // => true - - twitter === twitter2; //=> true - ``` - - If singletons are not wanted an optional flag can be provided at lookup. - - ```javascript - var container = new Container(); - container.register('api:twitter', Twitter); - - var twitter = container.lookup('api:twitter', { singleton: false }); - var twitter2 = container.lookup('api:twitter', { singleton: false }); - - twitter === twitter2; //=> false - ``` - - @method lookup - @param {String} fullName - @param {Object} options - @return {any} - */ - lookup: function(fullName, options) { - return lookup(this, this.normalize(fullName), options); - }, - - /** - Given a fullName return the corresponding factory. - - @method lookupFactory - @param {String} fullName - @return {any} - */ - lookupFactory: function(fullName) { - return factoryFor(this, this.normalize(fullName)); - }, - - /** - Given a fullName check if the container is aware of its factory - or singleton instance. - - @method has - @param {String} fullName - @return {Boolean} - */ - has: function(fullName) { - return has(this, this.normalize(fullName)); - }, - - /** - Allow registering options for all factories of a type. - - ```javascript - var container = new Container(); - - // if all of type `connection` must not be singletons - container.optionsForType('connection', { singleton: false }); - - container.register('connection:twitter', TwitterConnection); - container.register('connection:facebook', FacebookConnection); - - var twitter = container.lookup('connection:twitter'); - var twitter2 = container.lookup('connection:twitter'); - - twitter === twitter2; // => false - - var facebook = container.lookup('connection:facebook'); - var facebook2 = container.lookup('connection:facebook'); - - facebook === facebook2; // => false - ``` - - @method optionsForType - @param {String} type - @param {Object} options - */ - optionsForType: function(type, options) { - if (this.parent) { illegalChildOperation('optionsForType'); } - - this._typeOptions.set(type, options); - }, - - /** - @method options - @param {String} type - @param {Object} options - */ - options: function(type, options) { - this.optionsForType(type, options); - }, - - /** - Used only via `injection`. - - Provides a specialized form of injection, specifically enabling - all objects of one type to be injected with a reference to another - object. - - For example, provided each object of type `controller` needed a `router`. - one would do the following: - - ```javascript - var container = new Container(); - - container.register('router:main', Router); - container.register('controller:user', UserController); - container.register('controller:post', PostController); - - container.typeInjection('controller', 'router', 'router:main'); - - var user = container.lookup('controller:user'); - var post = container.lookup('controller:post'); - - user.router instanceof Router; //=> true - post.router instanceof Router; //=> true - - // both controllers share the same router - user.router === post.router; //=> true - ``` - - @private - @method typeInjection - @param {String} type - @param {String} property - @param {String} fullName - */ - typeInjection: function(type, property, fullName) { - if (this.parent) { illegalChildOperation('typeInjection'); } - - var fullNameType = fullName.split(':')[0]; - if(fullNameType === type) { - throw new Error('Cannot inject a `' + fullName + '` on other ' + type + '(s). Register the `' + fullName + '` as a different type and perform the typeInjection.'); - } - addTypeInjection(this.typeInjections, type, property, fullName); - }, - - /** - Defines injection rules. - - These rules are used to inject dependencies onto objects when they - are instantiated. - - Two forms of injections are possible: - - * Injecting one fullName on another fullName - * Injecting one fullName on a type - - Example: - - ```javascript - var container = new Container(); - - container.register('source:main', Source); - container.register('model:user', User); - container.register('model:post', Post); - - // injecting one fullName on another fullName - // eg. each user model gets a post model - container.injection('model:user', 'post', 'model:post'); - - // injecting one fullName on another type - container.injection('model', 'source', 'source:main'); - - var user = container.lookup('model:user'); - var post = container.lookup('model:post'); - - user.source instanceof Source; //=> true - post.source instanceof Source; //=> true - - user.post instanceof Post; //=> true - - // and both models share the same source - user.source === post.source; //=> true - ``` - - @method injection - @param {String} factoryName - @param {String} property - @param {String} injectionName - */ - injection: function(fullName, property, injectionName) { - if (this.parent) { illegalChildOperation('injection'); } - - validateFullName(injectionName); - var normalizedInjectionName = this.normalize(injectionName); - - if (fullName.indexOf(':') === -1) { - return this.typeInjection(fullName, property, normalizedInjectionName); - } - - var normalizedName = this.normalize(fullName); - - if (this.cache.has(normalizedName)) { - throw new Error("Attempted to register an injection for a type that has already been looked up. ('" + normalizedName + "', '" + property + "', '" + injectionName + "')"); - } - addInjection(this.injections, normalizedName, property, normalizedInjectionName); - }, - - - /** - Used only via `factoryInjection`. - - Provides a specialized form of injection, specifically enabling - all factory of one type to be injected with a reference to another - object. - - For example, provided each factory of type `model` needed a `store`. - one would do the following: - - ```javascript - var container = new Container(); - - container.register('store:main', SomeStore); - - container.factoryTypeInjection('model', 'store', 'store:main'); - - var store = container.lookup('store:main'); - var UserFactory = container.lookupFactory('model:user'); - - UserFactory.store instanceof SomeStore; //=> true - ``` - - @private - @method factoryTypeInjection - @param {String} type - @param {String} property - @param {String} fullName - */ - factoryTypeInjection: function(type, property, fullName) { - if (this.parent) { illegalChildOperation('factoryTypeInjection'); } - - addTypeInjection(this.factoryTypeInjections, type, property, this.normalize(fullName)); - }, - - /** - Defines factory injection rules. - - Similar to regular injection rules, but are run against factories, via - `Container#lookupFactory`. - - These rules are used to inject objects onto factories when they - are looked up. - - Two forms of injections are possible: - - * Injecting one fullName on another fullName - * Injecting one fullName on a type - - Example: - - ```javascript - var container = new Container(); - - container.register('store:main', Store); - container.register('store:secondary', OtherStore); - container.register('model:user', User); - container.register('model:post', Post); - - // injecting one fullName on another type - container.factoryInjection('model', 'store', 'store:main'); - - // injecting one fullName on another fullName - container.factoryInjection('model:post', 'secondaryStore', 'store:secondary'); - - var UserFactory = container.lookupFactory('model:user'); - var PostFactory = container.lookupFactory('model:post'); - var store = container.lookup('store:main'); - - UserFactory.store instanceof Store; //=> true - UserFactory.secondaryStore instanceof OtherStore; //=> false - - PostFactory.store instanceof Store; //=> true - PostFactory.secondaryStore instanceof OtherStore; //=> true - - // and both models share the same source instance - UserFactory.store === PostFactory.store; //=> true - ``` - - @method factoryInjection - @param {String} factoryName - @param {String} property - @param {String} injectionName - */ - factoryInjection: function(fullName, property, injectionName) { - if (this.parent) { illegalChildOperation('injection'); } - - var normalizedName = this.normalize(fullName); - var normalizedInjectionName = this.normalize(injectionName); - - validateFullName(injectionName); - - if (fullName.indexOf(':') === -1) { - return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName); - } - - - if (this.factoryCache.has(normalizedName)) { - throw new Error('Attempted to register a factoryInjection for a type that has already ' + - 'been looked up. (\'' + normalizedName + '\', \'' + property + '\', \'' + injectionName + '\')'); - } - - addInjection(this.factoryInjections, normalizedName, property, normalizedInjectionName); - }, - - /** - A depth first traversal, destroying the container, its descendant containers and all - their managed objects. - - @method destroy - */ - destroy: function() { - for (var i = 0, length = this.children.length; i < length; i++) { - this.children[i].destroy(); - } - - this.children = []; - - eachDestroyable(this, function(item) { - item.destroy(); - }); - - this.parent = undefined; - this.isDestroyed = true; - }, - - /** - @method reset - */ - reset: function() { - for (var i = 0, length = this.children.length; i < length; i++) { - resetCache(this.children[i]); - } - - resetCache(this); - } - }; - - function resolve(container, normalizedName) { - var cached = container.resolveCache.get(normalizedName); - if (cached) { return cached; } - - var resolved = container.resolver(normalizedName) || container.registry.get(normalizedName); - container.resolveCache.set(normalizedName, resolved); - - return resolved; - } - - function has(container, fullName){ - if (container.cache.has(fullName)) { - return true; - } - - return !!container.resolve(fullName); - } - - function lookup(container, fullName, options) { - options = options || {}; - - if (container.cache.has(fullName) && options.singleton !== false) { - return container.cache.get(fullName); - } - - var value = instantiate(container, fullName); - - if (value === undefined) { return; } - - if (isSingleton(container, fullName) && options.singleton !== false) { - container.cache.set(fullName, value); - } - - return value; - } - - function illegalChildOperation(operation) { - throw new Error(operation + ' is not currently supported on child containers'); - } - - function isSingleton(container, fullName) { - var singleton = option(container, fullName, 'singleton'); - - return singleton !== false; - } - - function buildInjections(container, injections) { - var hash = {}; - - if (!injections) { return hash; } - - var injection, injectable; - - for (var i = 0, length = injections.length; i < length; i++) { - injection = injections[i]; - injectable = lookup(container, injection.fullName); - - if (injectable !== undefined) { - hash[injection.property] = injectable; - } else { - throw new Error('Attempting to inject an unknown injection: `' + injection.fullName + '`'); - } - } - - return hash; - } - - function option(container, fullName, optionName) { - var options = container._options.get(fullName); - - if (options && options[optionName] !== undefined) { - return options[optionName]; - } - - var type = fullName.split(':')[0]; - options = container._typeOptions.get(type); - - if (options) { - return options[optionName]; - } - } - - function factoryFor(container, fullName) { - var cache = container.factoryCache; - if (cache.has(fullName)) { - return cache.get(fullName); - } - var factory = container.resolve(fullName); - if (factory === undefined) { return; } - - var type = fullName.split(':')[0]; - if (!factory || typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS && type === 'model')) { - // TODO: think about a 'safe' merge style extension - // for now just fallback to create time injection - return factory; - } else { - var injections = injectionsFor(container, fullName); - var factoryInjections = factoryInjectionsFor(container, fullName); - - factoryInjections._toString = container.makeToString(factory, fullName); - - var injectedFactory = factory.extend(injections); - injectedFactory.reopenClass(factoryInjections); - - cache.set(fullName, injectedFactory); - - return injectedFactory; - } - } - - function injectionsFor(container, fullName) { - var splitName = fullName.split(':'), - type = splitName[0], - injections = []; - - injections = injections.concat(container.typeInjections.get(type) || []); - injections = injections.concat(container.injections[fullName] || []); - - injections = buildInjections(container, injections); - injections._debugContainerKey = fullName; - injections.container = container; - - return injections; - } - - function factoryInjectionsFor(container, fullName) { - var splitName = fullName.split(':'), - type = splitName[0], - factoryInjections = []; - - factoryInjections = factoryInjections.concat(container.factoryTypeInjections.get(type) || []); - factoryInjections = factoryInjections.concat(container.factoryInjections[fullName] || []); - - factoryInjections = buildInjections(container, factoryInjections); - factoryInjections._debugContainerKey = fullName; - - return factoryInjections; - } - - function instantiate(container, fullName) { - var factory = factoryFor(container, fullName); - - if (option(container, fullName, 'instantiate') === false) { - return factory; - } - - if (factory) { - if (typeof factory.create !== 'function') { - throw new Error('Failed to create an instance of \'' + fullName + '\'. ' + - 'Most likely an improperly defined class or an invalid module export.'); - } - - if (typeof factory.extend === 'function') { - // assume the factory was extendable and is already injected - return factory.create(); - } else { - // assume the factory was extendable - // to create time injections - // TODO: support new'ing for instantiation and merge injections for pure JS Functions - return factory.create(injectionsFor(container, fullName)); - } - } - } - - function eachDestroyable(container, callback) { - container.cache.eachLocal(function(key, value) { - if (option(container, key, 'instantiate') === false) { return; } - callback(value); - }); - } - - function resetCache(container) { - container.cache.eachLocal(function(key, value) { - if (option(container, key, 'instantiate') === false) { return; } - value.destroy(); - }); - container.cache.dict = {}; - } - - function addTypeInjection(rules, type, property, fullName) { - var injections = rules.get(type); - - if (!injections) { - injections = []; - rules.set(type, injections); - } - - injections.push({ - property: property, - fullName: fullName - }); - } - - var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/; - function validateFullName(fullName) { - if (!VALID_FULL_NAME_REGEXP.test(fullName)) { - throw new TypeError('Invalid Fullname, expected: `type:name` got: ' + fullName); - } - return true; - } - - function addInjection(rules, factoryName, property, injectionName) { - var injections = rules[factoryName] = rules[factoryName] || []; - injections.push({ property: property, fullName: injectionName }); - } - - __exports__["default"] = Container; - }); -define("container/inheriting_dict", - ["exports"], - function(__exports__) { - "use strict"; - // A safe and simple inheriting object. - function InheritingDict(parent) { - this.parent = parent; - this.dict = {}; - } - - InheritingDict.prototype = { - - /** - @property parent - @type InheritingDict - @default null - */ - - parent: null, - - /** - Object used to store the current nodes data. - - @property dict - @type Object - @default Object - */ - dict: null, - - /** - Retrieve the value given a key, if the value is present at the current - level use it, otherwise walk up the parent hierarchy and try again. If - no matching key is found, return undefined. - - @method get - @param {String} key - @return {any} - */ - get: function(key) { - var dict = this.dict; - - if (dict.hasOwnProperty(key)) { - return dict[key]; - } - - if (this.parent) { - return this.parent.get(key); - } - }, - - /** - Set the given value for the given key, at the current level. - - @method set - @param {String} key - @param {Any} value - */ - set: function(key, value) { - this.dict[key] = value; - }, - - /** - Delete the given key - - @method remove - @param {String} key - */ - remove: function(key) { - delete this.dict[key]; - }, - - /** - Check for the existence of given a key, if the key is present at the current - level return true, otherwise walk up the parent hierarchy and try again. If - no matching key is found, return false. - - @method has - @param {String} key - @return {Boolean} - */ - has: function(key) { - var dict = this.dict; - - if (dict.hasOwnProperty(key)) { - return true; - } - - if (this.parent) { - return this.parent.has(key); - } - - return false; - }, - - /** - Iterate and invoke a callback for each local key-value pair. - - @method eachLocal - @param {Function} callback - @param {Object} binding - */ - eachLocal: function(callback, binding) { - var dict = this.dict; - - for (var prop in dict) { - if (dict.hasOwnProperty(prop)) { - callback.call(binding, prop, dict[prop]); - } - } - } - }; - - __exports__["default"] = InheritingDict; - }); -define("ember-application", - ["ember-metal/core","ember-runtime/system/lazy_load","ember-application/system/dag","ember-application/system/resolver","ember-application/system/application","ember-application/ext/controller"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__) { - "use strict"; - var Ember = __dependency1__["default"]; - var runLoadHooks = __dependency2__.runLoadHooks; - - /** - Ember Application - - @module ember - @submodule ember-application - @requires ember-views, ember-routing - */ - - var DAG = __dependency3__["default"]; - var Resolver = __dependency4__.Resolver; - var DefaultResolver = __dependency4__["default"]; - var Application = __dependency5__["default"]; - // side effect of extending ControllerMixin - - Ember.Application = Application; - Ember.DAG = DAG; - Ember.Resolver = Resolver; - Ember.DefaultResolver = DefaultResolver; - - runLoadHooks('Ember.Application', Application); - }); -define("ember-application/ext/controller", - ["ember-metal/core","ember-metal/property_get","ember-metal/property_set","ember-metal/error","ember-metal/utils","ember-metal/computed","ember-runtime/mixins/controller","ember-routing/system/controller_for","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-application - */ - - var Ember = __dependency1__["default"]; - // Ember.assert - var get = __dependency2__.get; - var set = __dependency3__.set; - var EmberError = __dependency4__["default"]; - var inspect = __dependency5__.inspect; - var computed = __dependency6__.computed; - var ControllerMixin = __dependency7__["default"]; - var meta = __dependency5__.meta; - var controllerFor = __dependency8__["default"]; - - function verifyNeedsDependencies(controller, container, needs) { - var dependency, i, l, missing = []; - - for (i=0, l=needs.length; i 1 ? 'they' : 'it') + " could not be found"); - } - } - - var defaultControllersComputedProperty = computed(function() { - var controller = this; - - return { - needs: get(controller, 'needs'), - container: get(controller, 'container'), - unknownProperty: function(controllerName) { - var needs = this.needs, - dependency, i, l; - for (i=0, l=needs.length; i 0) { - - if (this.container) { - verifyNeedsDependencies(this, this.container, needs); - } - - // if needs then initialize controllers proxy - get(this, 'controllers'); - } - - this._super.apply(this, arguments); - }, - - /** - @method controllerFor - @see {Ember.Route#controllerFor} - @deprecated Use `needs` instead - */ - controllerFor: function(controllerName) { - return controllerFor(get(this, 'container'), controllerName); - }, - - /** - Stores the instances of other controllers available from within - this controller. Any controller listed by name in the `needs` - property will be accessible by name through this property. - - ```javascript - App.CommentsController = Ember.ArrayController.extend({ - needs: ['post'], - postTitle: function(){ - var currentPost = this.get('controllers.post'); // instance of App.PostController - return currentPost.get('title'); - }.property('controllers.post.title') - }); - ``` - - @see {Ember.ControllerMixin#needs} - @property {Object} controllers - @default null - */ - controllers: defaultControllersComputedProperty - }); - - __exports__["default"] = ControllerMixin; - }); -define("ember-application/system/application", - ["ember-metal","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/lazy_load","ember-application/system/dag","ember-runtime/system/namespace","ember-runtime/mixins/deferred","ember-application/system/resolver","ember-metal/platform","ember-metal/run_loop","ember-metal/utils","container/container","ember-runtime/controllers/controller","ember-metal/enumerable_utils","ember-runtime/controllers/object_controller","ember-runtime/controllers/array_controller","ember-views/system/event_dispatcher","ember-views/system/jquery","ember-routing/system/route","ember-routing/system/router","ember-routing/location/hash_location","ember-routing/location/history_location","ember-routing/location/auto_location","ember-routing/location/none_location","ember-routing/system/cache","ember-metal/core","ember-handlebars-compiler","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-application - */ - - var Ember = __dependency1__["default"]; - // Ember.FEATURES, Ember.deprecate, Ember.assert, Ember.libraries, LOG_VERSION, Namespace, BOOTED - var get = __dependency2__.get; - var set = __dependency3__.set; - var runLoadHooks = __dependency4__.runLoadHooks; - var DAG = __dependency5__["default"]; - var Namespace = __dependency6__["default"]; - var DeferredMixin = __dependency7__["default"]; - var DefaultResolver = __dependency8__["default"]; - var create = __dependency9__.create; - var run = __dependency10__["default"]; - var canInvoke = __dependency11__.canInvoke; - var Container = __dependency12__["default"]; - var Controller = __dependency13__["default"]; - var EnumerableUtils = __dependency14__["default"]; - var ObjectController = __dependency15__["default"]; - var ArrayController = __dependency16__["default"]; - var EventDispatcher = __dependency17__["default"]; - //import ContainerDebugAdapter from "ember-extension-support/container_debug_adapter"; - var jQuery = __dependency18__["default"]; - var Route = __dependency19__["default"]; - var Router = __dependency20__["default"]; - var HashLocation = __dependency21__["default"]; - var HistoryLocation = __dependency22__["default"]; - var AutoLocation = __dependency23__["default"]; - var NoneLocation = __dependency24__["default"]; - var BucketCache = __dependency25__["default"]; - - var K = __dependency26__.K; - var EmberHandlebars = __dependency27__["default"]; - - var ContainerDebugAdapter; - - /** - An instance of `Ember.Application` is the starting point for every Ember - application. It helps to instantiate, initialize and coordinate the many - objects that make up your app. - - Each Ember app has one and only one `Ember.Application` object. In fact, the - very first thing you should do in your application is create the instance: - - ```javascript - window.App = Ember.Application.create(); - ``` - - Typically, the application object is the only global variable. All other - classes in your app should be properties on the `Ember.Application` instance, - which highlights its first role: a global namespace. - - For example, if you define a view class, it might look like this: - - ```javascript - App.MyView = Ember.View.extend(); - ``` - - By default, calling `Ember.Application.create()` will automatically initialize - your application by calling the `Ember.Application.initialize()` method. If - you need to delay initialization, you can call your app's `deferReadiness()` - method. When you are ready for your app to be initialized, call its - `advanceReadiness()` method. - - You can define a `ready` method on the `Ember.Application` instance, which - will be run by Ember when the application is initialized. - - Because `Ember.Application` inherits from `Ember.Namespace`, any classes - you create will have useful string representations when calling `toString()`. - See the `Ember.Namespace` documentation for more information. - - While you can think of your `Ember.Application` as a container that holds the - other classes in your application, there are several other responsibilities - going on under-the-hood that you may want to understand. - - ### Event Delegation - - Ember uses a technique called _event delegation_. This allows the framework - to set up a global, shared event listener instead of requiring each view to - do it manually. For example, instead of each view registering its own - `mousedown` listener on its associated element, Ember sets up a `mousedown` - listener on the `body`. - - If a `mousedown` event occurs, Ember will look at the target of the event and - start walking up the DOM node tree, finding corresponding views and invoking - their `mouseDown` method as it goes. - - `Ember.Application` has a number of default events that it listens for, as - well as a mapping from lowercase events to camel-cased view method names. For - example, the `keypress` event causes the `keyPress` method on the view to be - called, the `dblclick` event causes `doubleClick` to be called, and so on. - - If there is a bubbling browser event that Ember does not listen for by - default, you can specify custom events and their corresponding view method - names by setting the application's `customEvents` property: - - ```javascript - App = Ember.Application.create({ - customEvents: { - // add support for the paste event - paste: "paste" - } - }); - ``` - - By default, the application sets up these event listeners on the document - body. However, in cases where you are embedding an Ember application inside - an existing page, you may want it to set up the listeners on an element - inside the body. - - For example, if only events inside a DOM element with the ID of `ember-app` - should be delegated, set your application's `rootElement` property: - - ```javascript - window.App = Ember.Application.create({ - rootElement: '#ember-app' - }); - ``` - - The `rootElement` can be either a DOM element or a jQuery-compatible selector - string. Note that *views appended to the DOM outside the root element will - not receive events.* If you specify a custom root element, make sure you only - append views inside it! - - To learn more about the advantages of event delegation and the Ember view - layer, and a list of the event listeners that are setup by default, visit the - [Ember View Layer guide](http://emberjs.com/guides/understanding-ember/the-view-layer/#toc_event-delegation). - - ### Initializers - - Libraries on top of Ember can add initializers, like so: - - ```javascript - Ember.Application.initializer({ - name: 'api-adapter', - - initialize: function(container, application) { - application.register('api-adapter:main', ApiAdapter); - } - }); - ``` - - Initializers provide an opportunity to access the container, which - organizes the different components of an Ember application. Additionally - they provide a chance to access the instantiated application. Beyond - being used for libraries, initializers are also a great way to organize - dependency injection or setup in your own application. - - ### Routing - - In addition to creating your application's router, `Ember.Application` is - also responsible for telling the router when to start routing. Transitions - between routes can be logged with the `LOG_TRANSITIONS` flag, and more - detailed intra-transition logging can be logged with - the `LOG_TRANSITIONS_INTERNAL` flag: - - ```javascript - window.App = Ember.Application.create({ - LOG_TRANSITIONS: true, // basic logging of successful transitions - LOG_TRANSITIONS_INTERNAL: true // detailed logging of all routing steps - }); - ``` - - By default, the router will begin trying to translate the current URL into - application state once the browser emits the `DOMContentReady` event. If you - need to defer routing, you can call the application's `deferReadiness()` - method. Once routing can begin, call the `advanceReadiness()` method. - - If there is any setup required before routing begins, you can implement a - `ready()` method on your app that will be invoked immediately before routing - begins. - ``` - - @class Application - @namespace Ember - @extends Ember.Namespace - */ - - var Application = Namespace.extend(DeferredMixin, { - _suppressDeferredDeprecation: true, - - /** - The root DOM element of the Application. This can be specified as an - element or a - [jQuery-compatible selector string](http://api.jquery.com/category/selectors/). - - This is the element that will be passed to the Application's, - `eventDispatcher`, which sets up the listeners for event delegation. Every - view in your application should be a child of the element you specify here. - - @property rootElement - @type DOMElement - @default 'body' - */ - rootElement: 'body', - - /** - The `Ember.EventDispatcher` responsible for delegating events to this - application's views. - - The event dispatcher is created by the application at initialization time - and sets up event listeners on the DOM element described by the - application's `rootElement` property. - - See the documentation for `Ember.EventDispatcher` for more information. - - @property eventDispatcher - @type Ember.EventDispatcher - @default null - */ - eventDispatcher: null, - - /** - The DOM events for which the event dispatcher should listen. - - By default, the application's `Ember.EventDispatcher` listens - for a set of standard DOM events, such as `mousedown` and - `keyup`, and delegates them to your application's `Ember.View` - instances. - - If you would like additional bubbling events to be delegated to your - views, set your `Ember.Application`'s `customEvents` property - to a hash containing the DOM event name as the key and the - corresponding view method name as the value. For example: - - ```javascript - App = Ember.Application.create({ - customEvents: { - // add support for the paste event - paste: "paste" - } - }); - ``` - - @property customEvents - @type Object - @default null - */ - customEvents: null, - - // Start off the number of deferrals at 1. This will be - // decremented by the Application's own `initialize` method. - _readinessDeferrals: 1, - - init: function() { - if (!this.$) { this.$ = jQuery; } - this.__container__ = this.buildContainer(); - - this.Router = this.defaultRouter(); - - this._super(); - - this.scheduleInitialize(); - - Ember.libraries.registerCoreLibrary('Handlebars', EmberHandlebars.VERSION); - Ember.libraries.registerCoreLibrary('jQuery', jQuery().jquery); - - if ( Ember.LOG_VERSION ) { - Ember.LOG_VERSION = false; // we only need to see this once per Application#init - - var nameLengths = EnumerableUtils.map(Ember.libraries, function(item) { - return get(item, "name.length"); - }); - - var maxNameLength = Math.max.apply(this, nameLengths); - - Ember.libraries.each(function(name, version) { - var spaces = new Array(maxNameLength - name.length + 1).join(" "); - }); - } - }, - - /** - Build the container for the current application. - - Also register a default application view in case the application - itself does not. - - @private - @method buildContainer - @return {Ember.Container} the configured container - */ - buildContainer: function() { - var container = this.__container__ = Application.buildContainer(this); - - return container; - }, - - /** - If the application has not opted out of routing and has not explicitly - defined a router, supply a default router for the application author - to configure. - - This allows application developers to do: - - ```javascript - var App = Ember.Application.create(); - - App.Router.map(function() { - this.resource('posts'); - }); - ``` - - @private - @method defaultRouter - @return {Ember.Router} the default router - */ - - defaultRouter: function() { - if (this.Router === false) { return; } - var container = this.__container__; - - if (this.Router) { - container.unregister('router:main'); - container.register('router:main', this.Router); - } - - return container.lookupFactory('router:main'); - }, - - /** - Automatically initialize the application once the DOM has - become ready. - - The initialization itself is scheduled on the actions queue - which ensures that application loading finishes before - booting. - - If you are asynchronously loading code, you should call - `deferReadiness()` to defer booting, and then call - `advanceReadiness()` once all of your code has finished - loading. - - @private - @method scheduleInitialize - */ - scheduleInitialize: function() { - var self = this; - - if (!this.$ || this.$.isReady) { - run.schedule('actions', self, '_initialize'); - } else { - this.$().ready(function runInitialize() { - run(self, '_initialize'); - }); - } - }, - - /** - Use this to defer readiness until some condition is true. - - Example: - - ```javascript - App = Ember.Application.create(); - App.deferReadiness(); - - jQuery.getJSON("/auth-token", function(token) { - App.token = token; - App.advanceReadiness(); - }); - ``` - - This allows you to perform asynchronous setup logic and defer - booting your application until the setup has finished. - - However, if the setup requires a loading UI, it might be better - to use the router for this purpose. - - @method deferReadiness - */ - deferReadiness: function() { - this._readinessDeferrals++; - }, - - /** - Call `advanceReadiness` after any asynchronous setup logic has completed. - Each call to `deferReadiness` must be matched by a call to `advanceReadiness` - or the application will never become ready and routing will not begin. - - @method advanceReadiness - @see {Ember.Application#deferReadiness} - */ - advanceReadiness: function() { - this._readinessDeferrals--; - - if (this._readinessDeferrals === 0) { - run.once(this, this.didBecomeReady); - } - }, - - /** - Registers a factory that can be used for dependency injection (with - `App.inject`) or for service lookup. Each factory is registered with - a full name including two parts: `type:name`. - - A simple example: - - ```javascript - var App = Ember.Application.create(); - App.Orange = Ember.Object.extend(); - App.register('fruit:favorite', App.Orange); - ``` - - Ember will resolve factories from the `App` namespace automatically. - For example `App.CarsController` will be discovered and returned if - an application requests `controller:cars`. - - An example of registering a controller with a non-standard name: - - ```javascript - var App = Ember.Application.create(), - Session = Ember.Controller.extend(); - - App.register('controller:session', Session); - - // The Session controller can now be treated like a normal controller, - // despite its non-standard name. - App.ApplicationController = Ember.Controller.extend({ - needs: ['session'] - }); - ``` - - Registered factories are **instantiated** by having `create` - called on them. Additionally they are **singletons**, each time - they are looked up they return the same instance. - - Some examples modifying that default behavior: - - ```javascript - var App = Ember.Application.create(); - - App.Person = Ember.Object.extend(); - App.Orange = Ember.Object.extend(); - App.Email = Ember.Object.extend(); - App.session = Ember.Object.create(); - - App.register('model:user', App.Person, {singleton: false }); - App.register('fruit:favorite', App.Orange); - App.register('communication:main', App.Email, {singleton: false}); - App.register('session', App.session, {instantiate: false}); - ``` - - @method register - @param fullName {String} type:name (e.g., 'model:user') - @param factory {Function} (e.g., App.Person) - @param options {Object} (optional) disable instantiation or singleton usage - **/ - register: function() { - var container = this.__container__; - container.register.apply(container, arguments); - }, - - /** - Define a dependency injection onto a specific factory or all factories - of a type. - - When Ember instantiates a controller, view, or other framework component - it can attach a dependency to that component. This is often used to - provide services to a set of framework components. - - An example of providing a session object to all controllers: - - ```javascript - var App = Ember.Application.create(), - Session = Ember.Object.extend({ isAuthenticated: false }); - - // A factory must be registered before it can be injected - App.register('session:main', Session); - - // Inject 'session:main' onto all factories of the type 'controller' - // with the name 'session' - App.inject('controller', 'session', 'session:main'); - - App.IndexController = Ember.Controller.extend({ - isLoggedIn: Ember.computed.alias('session.isAuthenticated') - }); - ``` - - Injections can also be performed on specific factories. - - ```javascript - App.inject(, , ) - App.inject('route', 'source', 'source:main') - App.inject('route:application', 'email', 'model:email') - ``` - - It is important to note that injections can only be performed on - classes that are instantiated by Ember itself. Instantiating a class - directly (via `create` or `new`) bypasses the dependency injection - system. - - Ember-Data instantiates its models in a unique manner, and consequently - injections onto models (or all models) will not work as expected. Injections - on models can be enabled by setting `Ember.MODEL_FACTORY_INJECTIONS` - to `true`. - - @method inject - @param factoryNameOrType {String} - @param property {String} - @param injectionName {String} - **/ - inject: function() { - var container = this.__container__; - container.injection.apply(container, arguments); - }, - - /** - Calling initialize manually is not supported. - - Please see Ember.Application#advanceReadiness and - Ember.Application#deferReadiness. - - @private - @deprecated - @method initialize - **/ - initialize: function() { - }, - - /** - Initialize the application. This happens automatically. - - Run any initializers and run the application load hook. These hooks may - choose to defer readiness. For example, an authentication hook might want - to defer readiness until the auth token has been retrieved. - - @private - @method _initialize - */ - _initialize: function() { - if (this.isDestroyed) { return; } - - // At this point, the App.Router must already be assigned - if (this.Router) { - var container = this.__container__; - container.unregister('router:main'); - container.register('router:main', this.Router); - } - - this.runInitializers(); - runLoadHooks('application', this); - - // At this point, any initializers or load hooks that would have wanted - // to defer readiness have fired. In general, advancing readiness here - // will proceed to didBecomeReady. - this.advanceReadiness(); - - return this; - }, - - /** - Reset the application. This is typically used only in tests. It cleans up - the application in the following order: - - 1. Deactivate existing routes - 2. Destroy all objects in the container - 3. Create a new application container - 4. Re-route to the existing url - - Typical Example: - - ```javascript - - var App; - - run(function() { - App = Ember.Application.create(); - }); - - module("acceptance test", { - setup: function() { - App.reset(); - } - }); - - test("first test", function() { - // App is freshly reset - }); - - test("first test", function() { - // App is again freshly reset - }); - ``` - - Advanced Example: - - Occasionally you may want to prevent the app from initializing during - setup. This could enable extra configuration, or enable asserting prior - to the app becoming ready. - - ```javascript - - var App; - - run(function() { - App = Ember.Application.create(); - }); - - module("acceptance test", { - setup: function() { - run(function() { - App.reset(); - App.deferReadiness(); - }); - } - }); - - test("first test", function() { - ok(true, 'something before app is initialized'); - - run(function() { - App.advanceReadiness(); - }); - ok(true, 'something after app is initialized'); - }); - ``` - - @method reset - **/ - reset: function() { - this._readinessDeferrals = 1; - - function handleReset() { - var router = this.__container__.lookup('router:main'); - router.reset(); - - run(this.__container__, 'destroy'); - - this.buildContainer(); - - run.schedule('actions', this, function() { - this._initialize(); - }); - } - - run.join(this, handleReset); - }, - - /** - @private - @method runInitializers - */ - runInitializers: function() { - var initializers = get(this.constructor, 'initializers'); - var container = this.__container__; - var graph = new DAG(); - var namespace = this; - var name, initializer; - - for (name in initializers) { - initializer = initializers[name]; - graph.addEdges(initializer.name, initializer.initialize, initializer.before, initializer.after); - } - - graph.topsort(function (vertex) { - var initializer = vertex.value; - initializer(container, namespace); - }); - }, - - /** - @private - @method didBecomeReady - */ - didBecomeReady: function() { - this.setupEventDispatcher(); - this.ready(); // user hook - this.startRouting(); - - if (!Ember.testing) { - // Eagerly name all classes that are already loaded - Ember.Namespace.processAll(); - Ember.BOOTED = true; - } - - this.resolve(this); - }, - - /** - Setup up the event dispatcher to receive events on the - application's `rootElement` with any registered - `customEvents`. - - @private - @method setupEventDispatcher - */ - setupEventDispatcher: function() { - var customEvents = get(this, 'customEvents'); - var rootElement = get(this, 'rootElement'); - var dispatcher = this.__container__.lookup('event_dispatcher:main'); - - set(this, 'eventDispatcher', dispatcher); - dispatcher.setup(customEvents, rootElement); - }, - - /** - If the application has a router, use it to route to the current URL, and - trigger a new call to `route` whenever the URL changes. - - @private - @method startRouting - @property router {Ember.Router} - */ - startRouting: function() { - var router = this.__container__.lookup('router:main'); - if (!router) { return; } - - router.startRouting(); - }, - - handleURL: function(url) { - var router = this.__container__.lookup('router:main'); - - router.handleURL(url); - }, - - /** - Called when the Application has become ready. - The call will be delayed until the DOM has become ready. - - @event ready - */ - ready: K, - - /** - @deprecated Use 'Resolver' instead - Set this to provide an alternate class to `Ember.DefaultResolver` - - - @property resolver - */ - resolver: null, - - /** - Set this to provide an alternate class to `Ember.DefaultResolver` - - @property resolver - */ - Resolver: null, - - willDestroy: function() { - Ember.BOOTED = false; - // Ensure deactivation of routes before objects are destroyed - this.__container__.lookup('router:main').reset(); - - this.__container__.destroy(); - }, - - initializer: function(options) { - this.constructor.initializer(options); - }, - - /** - @method then - @private - @deprecated - */ - then: function() { - - this._super.apply(this, arguments); - } - }); - - Application.reopenClass({ - initializers: {}, - - /** - Initializer receives an object which has the following attributes: - `name`, `before`, `after`, `initialize`. The only required attribute is - `initialize, all others are optional. - - * `name` allows you to specify under which name the initializer is registered. - This must be a unique name, as trying to register two initializers with the - same name will result in an error. - - ```javascript - Ember.Application.initializer({ - name: 'namedInitializer', - initialize: function(container, application) { - Ember.debug("Running namedInitializer!"); - } - }); - ``` - - * `before` and `after` are used to ensure that this initializer is ran prior - or after the one identified by the value. This value can be a single string - or an array of strings, referencing the `name` of other initializers. - - An example of ordering initializers, we create an initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'first', - initialize: function(container, application) { - Ember.debug("First initializer!"); - } - }); - - // DEBUG: First initializer! - ``` - - We add another initializer named `second`, specifying that it should run - after the initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'second', - after: 'first', - - initialize: function(container, application) { - Ember.debug("Second initializer!"); - } - }); - - // DEBUG: First initializer! - // DEBUG: Second initializer! - ``` - - Afterwards we add a further initializer named `pre`, this time specifying - that it should run before the initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'pre', - before: 'first', - - initialize: function(container, application) { - Ember.debug("Pre initializer!"); - } - }); - - // DEBUG: Pre initializer! - // DEBUG: First initializer! - // DEBUG: Second initializer! - ``` - - Finally we add an initializer named `post`, specifying it should run after - both the `first` and the `second` initializers: - - ```javascript - Ember.Application.initializer({ - name: 'post', - after: ['first', 'second'], - - initialize: function(container, application) { - Ember.debug("Post initializer!"); - } - }); - - // DEBUG: Pre initializer! - // DEBUG: First initializer! - // DEBUG: Second initializer! - // DEBUG: Post initializer! - ``` - - * `initialize` is a callback function that receives two arguments, `container` - and `application` on which you can operate. - - Example of using `container` to preload data into the store: - - ```javascript - Ember.Application.initializer({ - name: "preload-data", - - initialize: function(container, application) { - var store = container.lookup('store:main'); - store.pushPayload(preloadedData); - } - }); - ``` - - Example of using `application` to register an adapter: - - ```javascript - Ember.Application.initializer({ - name: 'api-adapter', - - initialize: function(container, application) { - application.register('api-adapter:main', ApiAdapter); - } - }); - ``` - - @method initializer - @param initializer {Object} - */ - initializer: function(initializer) { - // If this is the first initializer being added to a subclass, we are going to reopen the class - // to make sure we have a new `initializers` object, which extends from the parent class' using - // prototypal inheritance. Without this, attempting to add initializers to the subclass would - // pollute the parent class as well as other subclasses. - if (this.superclass.initializers !== undefined && this.superclass.initializers === this.initializers) { - this.reopenClass({ - initializers: create(this.initializers) - }); - } - - - this.initializers[initializer.name] = initializer; - }, - - /** - This creates a container with the default Ember naming conventions. - - It also configures the container: - - * registered views are created every time they are looked up (they are - not singletons) - * registered templates are not factories; the registered value is - returned directly. - * the router receives the application as its `namespace` property - * all controllers receive the router as their `target` and `controllers` - properties - * all controllers receive the application as their `namespace` property - * the application view receives the application controller as its - `controller` property - * the application view receives the application template as its - `defaultTemplate` property - - @private - @method buildContainer - @static - @param {Ember.Application} namespace the application to build the - container for. - @return {Ember.Container} the built container - */ - buildContainer: function(namespace) { - var container = new Container(); - - container.set = set; - container.resolver = resolverFor(namespace); - container.normalize = container.resolver.normalize; - container.describe = container.resolver.describe; - container.makeToString = container.resolver.makeToString; - - container.optionsForType('component', { singleton: false }); - container.optionsForType('view', { singleton: false }); - container.optionsForType('template', { instantiate: false }); - container.optionsForType('helper', { instantiate: false }); - - container.register('application:main', namespace, { instantiate: false }); - - container.register('controller:basic', Controller, { instantiate: false }); - container.register('controller:object', ObjectController, { instantiate: false }); - container.register('controller:array', ArrayController, { instantiate: false }); - container.register('route:basic', Route, { instantiate: false }); - container.register('event_dispatcher:main', EventDispatcher); - - container.register('router:main', Router); - container.injection('router:main', 'namespace', 'application:main'); - - container.register('location:auto', AutoLocation); - container.register('location:hash', HashLocation); - container.register('location:history', HistoryLocation); - container.register('location:none', NoneLocation); - - container.injection('controller', 'target', 'router:main'); - container.injection('controller', 'namespace', 'application:main'); - - container.register('-bucket-cache:main', BucketCache); - container.injection('router', '_bucketCache', '-bucket-cache:main'); - container.injection('route', '_bucketCache', '-bucket-cache:main'); - container.injection('controller', '_bucketCache', '-bucket-cache:main'); - - container.injection('route', 'router', 'router:main'); - container.injection('location', 'rootURL', '-location-setting:root-url'); - - // DEBUGGING - container.register('resolver-for-debugging:main', container.resolver.__resolver__, { instantiate: false }); - container.injection('container-debug-adapter:main', 'resolver', 'resolver-for-debugging:main'); - container.injection('data-adapter:main', 'containerDebugAdapter', 'container-debug-adapter:main'); - // Custom resolver authors may want to register their own ContainerDebugAdapter with this key - - // ES6TODO: resolve this via import once ember-application package is ES6'ed - if (!ContainerDebugAdapter) { ContainerDebugAdapter = requireModule('ember-extension-support/container_debug_adapter')['default']; } - container.register('container-debug-adapter:main', ContainerDebugAdapter); - - return container; - } - }); - - /** - This function defines the default lookup rules for container lookups: - - * templates are looked up on `Ember.TEMPLATES` - * other names are looked up on the application after classifying the name. - For example, `controller:post` looks up `App.PostController` by default. - * if the default lookup fails, look for registered classes on the container - - This allows the application to register default injections in the container - that could be overridden by the normal naming convention. - - @private - @method resolverFor - @param {Ember.Namespace} namespace the namespace to look for classes - @return {*} the resolved value for a given lookup - */ - function resolverFor(namespace) { - if (namespace.get('resolver')) { - } - - var ResolverClass = namespace.get('resolver') || namespace.get('Resolver') || DefaultResolver; - var resolver = ResolverClass.create({ - namespace: namespace - }); - - function resolve(fullName) { - return resolver.resolve(fullName); - } - - resolve.describe = function(fullName) { - return resolver.lookupDescription(fullName); - }; - - resolve.makeToString = function(factory, fullName) { - return resolver.makeToString(factory, fullName); - }; - - resolve.normalize = function(fullName) { - if (resolver.normalize) { - return resolver.normalize(fullName); - } else { - return fullName; - } - }; - - resolve.__resolver__ = resolver; - - return resolve; - } - - __exports__["default"] = Application; - }); -define("ember-application/system/dag", - ["ember-metal/error","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var EmberError = __dependency1__["default"]; - - function visit(vertex, fn, visited, path) { - var name = vertex.name; - var vertices = vertex.incoming; - var names = vertex.incomingNames; - var len = names.length; - var i; - - if (!visited) { - visited = {}; - } - if (!path) { - path = []; - } - if (visited.hasOwnProperty(name)) { - return; - } - path.push(name); - visited[name] = true; - for (i = 0; i < len; i++) { - visit(vertices[names[i]], fn, visited, path); - } - fn(vertex, path); - path.pop(); - } - - - /** - * DAG stands for Directed acyclic graph. - * - * It is used to build a graph of dependencies checking that there isn't circular - * dependencies. p.e Registering initializers with a certain precedence order. - * - * @class DAG - * @constructor - */ - function DAG() { - this.names = []; - this.vertices = {}; - } - - /** - * Adds a vertex entry to the graph unless it is already added. - * - * @private - * @method add - * @param {String} name The name of the vertex to add - */ - DAG.prototype.add = function(name) { - if (!name) { return; } - if (this.vertices.hasOwnProperty(name)) { - return this.vertices[name]; - } - var vertex = { - name: name, incoming: {}, incomingNames: [], hasOutgoing: false, value: null - }; - this.vertices[name] = vertex; - this.names.push(name); - return vertex; - }; - - /** - * Adds a vertex to the graph and sets its value. - * - * @private - * @method map - * @param {String} name The name of the vertex. - * @param value The value to put in the vertex. - */ - DAG.prototype.map = function(name, value) { - this.add(name).value = value; - }; - - /** - * Connects the vertices with the given names, adding them to the graph if - * necesary, only if this does not produce is any circular dependency. - * - * @private - * @method addEdge - * @param {String} fromName The name the vertex where the edge starts. - * @param {String} toName The name the vertex where the edge ends. - */ - DAG.prototype.addEdge = function(fromName, toName) { - if (!fromName || !toName || fromName === toName) { - return; - } - var from = this.add(fromName), to = this.add(toName); - if (to.incoming.hasOwnProperty(fromName)) { - return; - } - function checkCycle(vertex, path) { - if (vertex.name === toName) { - throw new EmberError("cycle detected: " + toName + " <- " + path.join(" <- ")); - } - } - visit(from, checkCycle); - from.hasOutgoing = true; - to.incoming[fromName] = from; - to.incomingNames.push(fromName); - }; - - /** - * Visits all the vertex of the graph calling the given function with each one, - * ensuring that the vertices are visited respecting their precedence. - * - * @method topsort - * @param {Function} fn The function to be invoked on each vertex. - */ - DAG.prototype.topsort = function(fn) { - var visited = {}; - var vertices = this.vertices; - var names = this.names; - var len = names.length; - var i, vertex; - - for (i = 0; i < len; i++) { - vertex = vertices[names[i]]; - if (!vertex.hasOutgoing) { - visit(vertex, fn, visited); - } - } - }; - - /** - * Adds a vertex with the given name and value to the graph and joins it with the - * vertices referenced in _before_ and _after_. If there isn't vertices with those - * names, they are added too. - * - * If either _before_ or _after_ are falsy/empty, the added vertex will not have - * an incoming/outgoing edge. - * - * @method addEdges - * @param {String} name The name of the vertex to be added. - * @param value The value of that vertex. - * @param before An string or array of strings with the names of the vertices before - * which this vertex must be visited. - * @param after An string or array of strings with the names of the vertex after - * which this vertex must be visited. - * - */ - DAG.prototype.addEdges = function(name, value, before, after) { - var i; - this.map(name, value); - if (before) { - if (typeof before === 'string') { - this.addEdge(name, before); - } else { - for (i = 0; i < before.length; i++) { - this.addEdge(name, before[i]); - } - } - } - if (after) { - if (typeof after === 'string') { - this.addEdge(after, name); - } else { - for (i = 0; i < after.length; i++) { - this.addEdge(after[i], name); - } - } - } - }; - - __exports__["default"] = DAG; - }); -define("ember-application/system/resolver", - ["ember-metal/core","ember-metal/property_get","ember-metal/logger","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/system/namespace","ember-handlebars","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-application - */ - - var Ember = __dependency1__["default"]; - // Ember.TEMPLATES, Ember.assert - var get = __dependency2__.get; - var Logger = __dependency3__["default"]; - var classify = __dependency4__.classify; - var capitalize = __dependency4__.capitalize; - var decamelize = __dependency4__.decamelize; - var EmberObject = __dependency5__["default"]; - var Namespace = __dependency6__["default"]; - var EmberHandlebars = __dependency7__["default"]; - - var Resolver = EmberObject.extend({ - /** - This will be set to the Application instance when it is - created. - - @property namespace - */ - namespace: null, - normalize: Ember.required(Function), - resolve: Ember.required(Function), - parseName: Ember.required(Function), - lookupDescription: Ember.required(Function), - makeToString: Ember.required(Function), - resolveOther: Ember.required(Function), - _logLookup: Ember.required(Function) - }); - __exports__.Resolver = Resolver; - /** - The DefaultResolver defines the default lookup rules to resolve - container lookups before consulting the container for registered - items: - - * templates are looked up on `Ember.TEMPLATES` - * other names are looked up on the application after converting - the name. For example, `controller:post` looks up - `App.PostController` by default. - * there are some nuances (see examples below) - - ### How Resolving Works - - The container calls this object's `resolve` method with the - `fullName` argument. - - It first parses the fullName into an object using `parseName`. - - Then it checks for the presence of a type-specific instance - method of the form `resolve[Type]` and calls it if it exists. - For example if it was resolving 'template:post', it would call - the `resolveTemplate` method. - - Its last resort is to call the `resolveOther` method. - - The methods of this object are designed to be easy to override - in a subclass. For example, you could enhance how a template - is resolved like so: - - ```javascript - App = Ember.Application.create({ - Resolver: Ember.DefaultResolver.extend({ - resolveTemplate: function(parsedName) { - var resolvedTemplate = this._super(parsedName); - if (resolvedTemplate) { return resolvedTemplate; } - return Ember.TEMPLATES['not_found']; - } - }) - }); - ``` - - Some examples of how names are resolved: - - ``` - 'template:post' //=> Ember.TEMPLATES['post'] - 'template:posts/byline' //=> Ember.TEMPLATES['posts/byline'] - 'template:posts.byline' //=> Ember.TEMPLATES['posts/byline'] - 'template:blogPost' //=> Ember.TEMPLATES['blogPost'] - // OR - // Ember.TEMPLATES['blog_post'] - 'controller:post' //=> App.PostController - 'controller:posts.index' //=> App.PostsIndexController - 'controller:blog/post' //=> Blog.PostController - 'controller:basic' //=> Ember.Controller - 'route:post' //=> App.PostRoute - 'route:posts.index' //=> App.PostsIndexRoute - 'route:blog/post' //=> Blog.PostRoute - 'route:basic' //=> Ember.Route - 'view:post' //=> App.PostView - 'view:posts.index' //=> App.PostsIndexView - 'view:blog/post' //=> Blog.PostView - 'view:basic' //=> Ember.View - 'foo:post' //=> App.PostFoo - 'model:post' //=> App.Post - ``` - - @class DefaultResolver - @namespace Ember - @extends Ember.Object - */ - - __exports__["default"] = EmberObject.extend({ - /** - This will be set to the Application instance when it is - created. - - @property namespace - */ - namespace: null, - - normalize: function(fullName) { - var split = fullName.split(':', 2), - type = split[0], - name = split[1]; - - - if (type !== 'template') { - var result = name; - - if (result.indexOf('.') > -1) { - result = result.replace(/\.(.)/g, function(m) { return m.charAt(1).toUpperCase(); }); - } - - if (name.indexOf('_') > -1) { - result = result.replace(/_(.)/g, function(m) { return m.charAt(1).toUpperCase(); }); - } - - return type + ':' + result; - } else { - return fullName; - } - }, - - - /** - This method is called via the container's resolver method. - It parses the provided `fullName` and then looks up and - returns the appropriate template or class. - - @method resolve - @param {String} fullName the lookup string - @return {Object} the resolved factory - */ - resolve: function(fullName) { - var parsedName = this.parseName(fullName), - resolveMethodName = parsedName.resolveMethodName, - resolved; - - if (!(parsedName.name && parsedName.type)) { - throw new TypeError('Invalid fullName: `' + fullName + '`, must be of the form `type:name` '); - } - - if (this[resolveMethodName]) { - resolved = this[resolveMethodName](parsedName); - } - - if (!resolved) { - resolved = this.resolveOther(parsedName); - } - - if (parsedName.root && parsedName.root.LOG_RESOLVER) { - this._logLookup(resolved, parsedName); - } - - return resolved; - }, - /** - Convert the string name of the form 'type:name' to - a Javascript object with the parsed aspects of the name - broken out. - - @protected - @param {String} fullName the lookup string - @method parseName - */ - parseName: function(fullName) { - var nameParts = fullName.split(':'), - type = nameParts[0], fullNameWithoutType = nameParts[1], - name = fullNameWithoutType, - namespace = get(this, 'namespace'), - root = namespace; - - if (type !== 'template' && name.indexOf('/') !== -1) { - var parts = name.split('/'); - name = parts[parts.length - 1]; - var namespaceName = capitalize(parts.slice(0, -1).join('.')); - root = Namespace.byName(namespaceName); - - } - - return { - fullName: fullName, - type: type, - fullNameWithoutType: fullNameWithoutType, - name: name, - root: root, - resolveMethodName: 'resolve' + classify(type) - }; - }, - - /** - Returns a human-readable description for a fullName. Used by the - Application namespace in assertions to describe the - precise name of the class that Ember is looking for, rather than - container keys. - - @protected - @param {String} fullName the lookup string - @method lookupDescription - */ - lookupDescription: function(fullName) { - var parsedName = this.parseName(fullName); - - if (parsedName.type === 'template') { - return 'template at ' + parsedName.fullNameWithoutType.replace(/\./g, '/'); - } - - var description = parsedName.root + '.' + classify(parsedName.name); - if (parsedName.type !== 'model') { description += classify(parsedName.type); } - - return description; - }, - - makeToString: function(factory, fullName) { - return factory.toString(); - }, - /** - Given a parseName object (output from `parseName`), apply - the conventions expected by `Ember.Router` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method useRouterNaming - */ - useRouterNaming: function(parsedName) { - parsedName.name = parsedName.name.replace(/\./g, '_'); - if (parsedName.name === 'basic') { - parsedName.name = ''; - } - }, - /** - Look up the template in Ember.TEMPLATES - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveTemplate - */ - resolveTemplate: function(parsedName) { - var templateName = parsedName.fullNameWithoutType.replace(/\./g, '/'); - - if (Ember.TEMPLATES[templateName]) { - return Ember.TEMPLATES[templateName]; - } - - templateName = decamelize(templateName); - if (Ember.TEMPLATES[templateName]) { - return Ember.TEMPLATES[templateName]; - } - }, - /** - Lookup the view using `resolveOther` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveView - */ - resolveView: function(parsedName) { - this.useRouterNaming(parsedName); - return this.resolveOther(parsedName); - }, - /** - Lookup the controller using `resolveOther` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveController - */ - resolveController: function(parsedName) { - this.useRouterNaming(parsedName); - return this.resolveOther(parsedName); - }, - /** - Lookup the route using `resolveOther` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveRoute - */ - resolveRoute: function(parsedName) { - this.useRouterNaming(parsedName); - return this.resolveOther(parsedName); - }, - - /** - Lookup the model on the Application namespace - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveModel - */ - resolveModel: function(parsedName) { - var className = classify(parsedName.name); - var factory = get(parsedName.root, className); - - if (factory) { return factory; } - }, - /** - Look up the specified object (from parsedName) on the appropriate - namespace (usually on the Application) - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveHelper - */ - resolveHelper: function(parsedName) { - return this.resolveOther(parsedName) || EmberHandlebars.helpers[parsedName.fullNameWithoutType]; - }, - /** - Look up the specified object (from parsedName) on the appropriate - namespace (usually on the Application) - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveOther - */ - resolveOther: function(parsedName) { - var className = classify(parsedName.name) + classify(parsedName.type); - var factory = get(parsedName.root, className); - if (factory) { return factory; } - }, - - /** - @method _logLookup - @param {Boolean} found - @param {Object} parsedName - @private - */ - _logLookup: function(found, parsedName) { - var symbol, padding; - - if (found) { symbol = '[✓]'; } - else { symbol = '[ ]'; } - - if (parsedName.fullName.length > 60) { - padding = '.'; - } else { - padding = new Array(60 - parsedName.fullName.length).join('.'); - } - - Logger.info(symbol, parsedName.fullName, padding, this.lookupDescription(parsedName.fullName)); - } - }); - }); -define("ember-extension-support", - ["ember-metal/core","ember-extension-support/data_adapter","ember-extension-support/container_debug_adapter"], - function(__dependency1__, __dependency2__, __dependency3__) { - "use strict"; - /** - Ember Extension Support - - @module ember - @submodule ember-extension-support - @requires ember-application - */ - - var Ember = __dependency1__["default"]; - var DataAdapter = __dependency2__["default"]; - var ContainerDebugAdapter = __dependency3__["default"]; - - Ember.DataAdapter = DataAdapter; - Ember.ContainerDebugAdapter = ContainerDebugAdapter; - }); -define("ember-extension-support/container_debug_adapter", - ["ember-metal/core","ember-runtime/system/native_array","ember-metal/utils","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var emberA = __dependency2__.A; - var typeOf = __dependency3__.typeOf; - var dasherize = __dependency4__.dasherize; - var classify = __dependency4__.classify; - var Namespace = __dependency5__["default"]; - var EmberObject = __dependency6__["default"]; - - /** - @module ember - @submodule ember-extension-support - */ - - /** - The `ContainerDebugAdapter` helps the container and resolver interface - with tools that debug Ember such as the - [Ember Extension](https://github.com/tildeio/ember-extension) - for Chrome and Firefox. - - This class can be extended by a custom resolver implementer - to override some of the methods with library-specific code. - - The methods likely to be overridden are: - - * `canCatalogEntriesByType` - * `catalogEntriesByType` - - The adapter will need to be registered - in the application's container as `container-debug-adapter:main` - - Example: - - ```javascript - Application.initializer({ - name: "containerDebugAdapter", - - initialize: function(container, application) { - application.register('container-debug-adapter:main', require('app/container-debug-adapter')); - } - }); - ``` - - @class ContainerDebugAdapter - @namespace Ember - @extends EmberObject - @since 1.5.0 - */ - __exports__["default"] = EmberObject.extend({ - /** - The container of the application being debugged. - This property will be injected - on creation. - - @property container - @default null - */ - container: null, - - /** - The resolver instance of the application - being debugged. This property will be injected - on creation. - - @property resolver - @default null - */ - resolver: null, - - /** - Returns true if it is possible to catalog a list of available - classes in the resolver for a given type. - - @method canCatalogEntriesByType - @param {string} type The type. e.g. "model", "controller", "route" - @return {boolean} whether a list is available for this type. - */ - canCatalogEntriesByType: function(type) { - if (type === 'model' || type === 'template') return false; - return true; - }, - - /** - Returns the available classes a given type. - - @method catalogEntriesByType - @param {string} type The type. e.g. "model", "controller", "route" - @return {Array} An array of strings. - */ - catalogEntriesByType: function(type) { - var namespaces = emberA(Namespace.NAMESPACES), types = emberA(), self = this; - var typeSuffixRegex = new RegExp(classify(type) + "$"); - - namespaces.forEach(function(namespace) { - if (namespace !== Ember) { - for (var key in namespace) { - if (!namespace.hasOwnProperty(key)) { continue; } - if (typeSuffixRegex.test(key)) { - var klass = namespace[key]; - if (typeOf(klass) === 'class') { - types.push(dasherize(key.replace(typeSuffixRegex, ''))); - } - } - } - } - }); - return types; - } - }); - }); -define("ember-extension-support/data_adapter", - ["ember-metal/core","ember-metal/property_get","ember-metal/run_loop","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","ember-runtime/system/native_array","ember-application/system/application","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var get = __dependency2__.get; - var run = __dependency3__["default"]; - var dasherize = __dependency4__.dasherize; - var Namespace = __dependency5__["default"]; - var EmberObject = __dependency6__["default"]; - var emberA = __dependency7__.A; - var Application = __dependency8__["default"]; - - /** - @module ember - @submodule ember-extension-support - */ - - /** - The `DataAdapter` helps a data persistence library - interface with tools that debug Ember such - as the [Ember Extension](https://github.com/tildeio/ember-extension) - for Chrome and Firefox. - - This class will be extended by a persistence library - which will override some of the methods with - library-specific code. - - The methods likely to be overridden are: - - * `getFilters` - * `detect` - * `columnsForType` - * `getRecords` - * `getRecordColumnValues` - * `getRecordKeywords` - * `getRecordFilterValues` - * `getRecordColor` - * `observeRecord` - - The adapter will need to be registered - in the application's container as `dataAdapter:main` - - Example: - - ```javascript - Application.initializer({ - name: "data-adapter", - - initialize: function(container, application) { - application.register('data-adapter:main', DS.DataAdapter); - } - }); - ``` - - @class DataAdapter - @namespace Ember - @extends EmberObject - */ - __exports__["default"] = EmberObject.extend({ - init: function() { - this._super(); - this.releaseMethods = emberA(); - }, - - /** - The container of the application being debugged. - This property will be injected - on creation. - - @property container - @default null - @since 1.3.0 - */ - container: null, - - - /** - The container-debug-adapter which is used - to list all models. - - @property containerDebugAdapter - @default undefined - @since 1.5.0 - **/ - containerDebugAdapter: undefined, - - /** - Number of attributes to send - as columns. (Enough to make the record - identifiable). - - @private - @property attributeLimit - @default 3 - @since 1.3.0 - */ - attributeLimit: 3, - - /** - Stores all methods that clear observers. - These methods will be called on destruction. - - @private - @property releaseMethods - @since 1.3.0 - */ - releaseMethods: emberA(), - - /** - Specifies how records can be filtered. - Records returned will need to have a `filterValues` - property with a key for every name in the returned array. - - @public - @method getFilters - @return {Array} List of objects defining filters. - The object should have a `name` and `desc` property. - */ - getFilters: function() { - return emberA(); - }, - - /** - Fetch the model types and observe them for changes. - - @public - @method watchModelTypes - - @param {Function} typesAdded Callback to call to add types. - Takes an array of objects containing wrapped types (returned from `wrapModelType`). - - @param {Function} typesUpdated Callback to call when a type has changed. - Takes an array of objects containing wrapped types. - - @return {Function} Method to call to remove all observers - */ - watchModelTypes: function(typesAdded, typesUpdated) { - var modelTypes = this.getModelTypes(), - self = this, typesToSend, releaseMethods = emberA(); - - typesToSend = modelTypes.map(function(type) { - var klass = type.klass; - var wrapped = self.wrapModelType(klass, type.name); - releaseMethods.push(self.observeModelType(klass, typesUpdated)); - return wrapped; - }); - - typesAdded(typesToSend); - - var release = function() { - releaseMethods.forEach(function(fn) { fn(); }); - self.releaseMethods.removeObject(release); - }; - this.releaseMethods.pushObject(release); - return release; - }, - - _nameToClass: function(type) { - if (typeof type === 'string') { - type = this.container.lookupFactory('model:' + type); - } - return type; - }, - - /** - Fetch the records of a given type and observe them for changes. - - @public - @method watchRecords - - @param {Function} recordsAdded Callback to call to add records. - Takes an array of objects containing wrapped records. - The object should have the following properties: - columnValues: {Object} key and value of a table cell - object: {Object} the actual record object - - @param {Function} recordsUpdated Callback to call when a record has changed. - Takes an array of objects containing wrapped records. - - @param {Function} recordsRemoved Callback to call when a record has removed. - Takes the following parameters: - index: the array index where the records were removed - count: the number of records removed - - @return {Function} Method to call to remove all observers - */ - watchRecords: function(type, recordsAdded, recordsUpdated, recordsRemoved) { - var self = this, releaseMethods = emberA(), records = this.getRecords(type), release; - - var recordUpdated = function(updatedRecord) { - recordsUpdated([updatedRecord]); - }; - - var recordsToSend = records.map(function(record) { - releaseMethods.push(self.observeRecord(record, recordUpdated)); - return self.wrapRecord(record); - }); - - - var contentDidChange = function(array, idx, removedCount, addedCount) { - for (var i = idx; i < idx + addedCount; i++) { - var record = array.objectAt(i); - var wrapped = self.wrapRecord(record); - releaseMethods.push(self.observeRecord(record, recordUpdated)); - recordsAdded([wrapped]); - } - - if (removedCount) { - recordsRemoved(idx, removedCount); - } - }; - - var observer = { didChange: contentDidChange, willChange: Ember.K }; - records.addArrayObserver(self, observer); - - release = function() { - releaseMethods.forEach(function(fn) { fn(); }); - records.removeArrayObserver(self, observer); - self.releaseMethods.removeObject(release); - }; - - recordsAdded(recordsToSend); - - this.releaseMethods.pushObject(release); - return release; - }, - - /** - Clear all observers before destruction - @private - @method willDestroy - */ - willDestroy: function() { - this._super(); - this.releaseMethods.forEach(function(fn) { - fn(); - }); - }, - - /** - Detect whether a class is a model. - - Test that against the model class - of your persistence library - - @private - @method detect - @param {Class} klass The class to test - @return boolean Whether the class is a model class or not - */ - detect: function(klass) { - return false; - }, - - /** - Get the columns for a given model type. - - @private - @method columnsForType - @param {Class} type The model type - @return {Array} An array of columns of the following format: - name: {String} name of the column - desc: {String} Humanized description (what would show in a table column name) - */ - columnsForType: function(type) { - return emberA(); - }, - - /** - Adds observers to a model type class. - - @private - @method observeModelType - @param {Class} type The model type class - @param {Function} typesUpdated Called when a type is modified. - @return {Function} The function to call to remove observers - */ - - observeModelType: function(type, typesUpdated) { - var self = this, records = this.getRecords(type); - - var onChange = function() { - typesUpdated([self.wrapModelType(type)]); - }; - var observer = { - didChange: function() { - run.scheduleOnce('actions', this, onChange); - }, - willChange: Ember.K - }; - - records.addArrayObserver(this, observer); - - var release = function() { - records.removeArrayObserver(self, observer); - }; - - return release; - }, - - - /** - Wraps a given model type and observes changes to it. - - @private - @method wrapModelType - @param {Class} type A model class - @param {String} Optional name of the class - @return {Object} contains the wrapped type and the function to remove observers - Format: - type: {Object} the wrapped type - The wrapped type has the following format: - name: {String} name of the type - count: {Integer} number of records available - columns: {Columns} array of columns to describe the record - object: {Class} the actual Model type class - release: {Function} The function to remove observers - */ - wrapModelType: function(type, name) { - var release, records = this.getRecords(type), - typeToSend, self = this; - - typeToSend = { - name: name || type.toString(), - count: get(records, 'length'), - columns: this.columnsForType(type), - object: type - }; - - - return typeToSend; - }, - - - /** - Fetches all models defined in the application. - - @private - @method getModelTypes - @return {Array} Array of model types - */ - getModelTypes: function() { - var types, self = this, - containerDebugAdapter = this.get('containerDebugAdapter'); - - if (containerDebugAdapter.canCatalogEntriesByType('model')) { - types = containerDebugAdapter.catalogEntriesByType('model'); - } else { - types = this._getObjectsOnNamespaces(); - } - - // New adapters return strings instead of classes - types = emberA(types).map(function(name) { - return { - klass: self._nameToClass(name), - name: name - }; - }); - types = emberA(types).filter(function(type) { - return self.detect(type.klass); - }); - - return emberA(types); - }, - - /** - Loops over all namespaces and all objects - attached to them - - @private - @method _getObjectsOnNamespaces - @return {Array} Array of model type strings - */ - _getObjectsOnNamespaces: function() { - var namespaces = emberA(Namespace.NAMESPACES), - types = emberA(), - self = this; - - namespaces.forEach(function(namespace) { - for (var key in namespace) { - if (!namespace.hasOwnProperty(key)) { continue; } - // Even though we will filter again in `getModelTypes`, - // we should not call `lookupContainer` on non-models - // (especially when `Ember.MODEL_FACTORY_INJECTIONS` is `true`) - if (!self.detect(namespace[key])) { continue; } - var name = dasherize(key); - if (!(namespace instanceof Application) && namespace.toString()) { - name = namespace + '/' + name; - } - types.push(name); - } - }); - return types; - }, - - /** - Fetches all loaded records for a given type. - - @private - @method getRecords - @return {Array} An array of records. - This array will be observed for changes, - so it should update when new records are added/removed. - */ - getRecords: function(type) { - return emberA(); - }, - - /** - Wraps a record and observers changes to it. - - @private - @method wrapRecord - @param {Object} record The record instance. - @return {Object} The wrapped record. Format: - columnValues: {Array} - searchKeywords: {Array} - */ - wrapRecord: function(record) { - var recordToSend = { object: record }, columnValues = {}, self = this; - - recordToSend.columnValues = this.getRecordColumnValues(record); - recordToSend.searchKeywords = this.getRecordKeywords(record); - recordToSend.filterValues = this.getRecordFilterValues(record); - recordToSend.color = this.getRecordColor(record); - - return recordToSend; - }, - - /** - Gets the values for each column. - - @private - @method getRecordColumnValues - @return {Object} Keys should match column names defined - by the model type. - */ - getRecordColumnValues: function(record) { - return {}; - }, - - /** - Returns keywords to match when searching records. - - @private - @method getRecordKeywords - @return {Array} Relevant keywords for search. - */ - getRecordKeywords: function(record) { - return emberA(); - }, - - /** - Returns the values of filters defined by `getFilters`. - - @private - @method getRecordFilterValues - @param {Object} record The record instance - @return {Object} The filter values - */ - getRecordFilterValues: function(record) { - return {}; - }, - - /** - Each record can have a color that represents its state. - - @private - @method getRecordColor - @param {Object} record The record instance - @return {String} The record's color - Possible options: black, red, blue, green - */ - getRecordColor: function(record) { - return null; - }, - - /** - Observes all relevant properties and re-sends the wrapped record - when a change occurs. - - @private - @method observerRecord - @param {Object} record The record instance - @param {Function} recordUpdated The callback to call when a record is updated. - @return {Function} The function to call to remove all observers. - */ - observeRecord: function(record, recordUpdated) { - return function(){}; - } - }); - }); -define("ember-extension-support/initializers", - [], - function() { - "use strict"; - - }); -define("ember-handlebars-compiler", - ["ember-metal/core","exports"], - function(__dependency1__, __exports__) { - "use strict"; - /* global Handlebars:true */ - - /** - @module ember - @submodule ember-handlebars-compiler - */ - - var Ember = __dependency1__["default"]; - - // ES6Todo: you'll need to import debugger once debugger is es6'd. - if (typeof Ember.assert === 'undefined') { Ember.assert = function(){}; } - if (typeof Ember.FEATURES === 'undefined') { Ember.FEATURES = { isEnabled: function(){} }; } - - var objectCreate = Object.create || function(parent) { - function F() {} - F.prototype = parent; - return new F(); - }; - - // set up for circular references later - var View, Component; - - // ES6Todo: when ember-debug is es6'ed import this. - // var emberAssert = Ember.assert; - var Handlebars = (Ember.imports && Ember.imports.Handlebars) || (this && this.Handlebars); - if (!Handlebars && typeof require === 'function') { - Handlebars = require('handlebars'); - } - - - - /** - Prepares the Handlebars templating library for use inside Ember's view - system. - - The `Ember.Handlebars` object is the standard Handlebars library, extended to - use Ember's `get()` method instead of direct property access, which allows - computed properties to be used inside templates. - - To create an `Ember.Handlebars` template, call `Ember.Handlebars.compile()`. - This will return a function that can be used by `Ember.View` for rendering. - - @class Handlebars - @namespace Ember - */ - var EmberHandlebars = Ember.Handlebars = objectCreate(Handlebars); - - /** - Register a bound helper or custom view helper. - - ## Simple bound helper example - - ```javascript - Ember.Handlebars.helper('capitalize', function(value) { - return value.toUpperCase(); - }); - ``` - - The above bound helper can be used inside of templates as follows: - - ```handlebars - {{capitalize name}} - ``` - - In this case, when the `name` property of the template's context changes, - the rendered value of the helper will update to reflect this change. - - For more examples of bound helpers, see documentation for - `Ember.Handlebars.registerBoundHelper`. - - ## Custom view helper example - - Assuming a view subclass named `App.CalendarView` were defined, a helper - for rendering instances of this view could be registered as follows: - - ```javascript - Ember.Handlebars.helper('calendar', App.CalendarView): - ``` - - The above bound helper can be used inside of templates as follows: - - ```handlebars - {{calendar}} - ``` - - Which is functionally equivalent to: - - ```handlebars - {{view App.CalendarView}} - ``` - - Options in the helper will be passed to the view in exactly the same - manner as with the `view` helper. - - @method helper - @for Ember.Handlebars - @param {String} name - @param {Function|Ember.View} function or view class constructor - @param {String} dependentKeys* - */ - EmberHandlebars.helper = function(name, value) { - if (!View) { View = requireModule('ember-views/views/view')['default']; } // ES6TODO: stupid circular dep - if (!Component) { Component = requireModule('ember-views/views/component')['default']; } // ES6TODO: stupid circular dep - - - if (View.detect(value)) { - EmberHandlebars.registerHelper(name, EmberHandlebars.makeViewHelper(value)); - } else { - EmberHandlebars.registerBoundHelper.apply(null, arguments); - } - }; - - /** - Returns a helper function that renders the provided ViewClass. - - Used internally by Ember.Handlebars.helper and other methods - involving helper/component registration. - - @private - @method makeViewHelper - @for Ember.Handlebars - @param {Function} ViewClass view class constructor - @since 1.2.0 - */ - EmberHandlebars.makeViewHelper = function(ViewClass) { - return function(options) { - return EmberHandlebars.helpers.view.call(this, ViewClass, options); - }; - }; - - /** - @class helpers - @namespace Ember.Handlebars - */ - EmberHandlebars.helpers = objectCreate(Handlebars.helpers); - - /** - Override the the opcode compiler and JavaScript compiler for Handlebars. - - @class Compiler - @namespace Ember.Handlebars - @private - @constructor - */ - EmberHandlebars.Compiler = function() {}; - - // Handlebars.Compiler doesn't exist in runtime-only - if (Handlebars.Compiler) { - EmberHandlebars.Compiler.prototype = objectCreate(Handlebars.Compiler.prototype); - } - - EmberHandlebars.Compiler.prototype.compiler = EmberHandlebars.Compiler; - - /** - @class JavaScriptCompiler - @namespace Ember.Handlebars - @private - @constructor - */ - EmberHandlebars.JavaScriptCompiler = function() {}; - - // Handlebars.JavaScriptCompiler doesn't exist in runtime-only - if (Handlebars.JavaScriptCompiler) { - EmberHandlebars.JavaScriptCompiler.prototype = objectCreate(Handlebars.JavaScriptCompiler.prototype); - EmberHandlebars.JavaScriptCompiler.prototype.compiler = EmberHandlebars.JavaScriptCompiler; - } - - - EmberHandlebars.JavaScriptCompiler.prototype.namespace = "Ember.Handlebars"; - - EmberHandlebars.JavaScriptCompiler.prototype.initializeBuffer = function() { - return "''"; - }; - - /** - Override the default buffer for Ember Handlebars. By default, Handlebars - creates an empty String at the beginning of each invocation and appends to - it. Ember's Handlebars overrides this to append to a single shared buffer. - - @private - @method appendToBuffer - @param string {String} - */ - EmberHandlebars.JavaScriptCompiler.prototype.appendToBuffer = function(string) { - return "data.buffer.push("+string+");"; - }; - - // Hacks ahead: - // Handlebars presently has a bug where the `blockHelperMissing` hook - // doesn't get passed the name of the missing helper name, but rather - // gets passed the value of that missing helper evaluated on the current - // context, which is most likely `undefined` and totally useless. - // - // So we alter the compiled template function to pass the name of the helper - // instead, as expected. - // - // This can go away once the following is closed: - // https://github.com/wycats/handlebars.js/issues/634 - - var DOT_LOOKUP_REGEX = /helpers\.(.*?)\)/, - BRACKET_STRING_LOOKUP_REGEX = /helpers\['(.*?)'/, - INVOCATION_SPLITTING_REGEX = /(.*blockHelperMissing\.call\(.*)(stack[0-9]+)(,.*)/; - - EmberHandlebars.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation = function(source) { - var helperInvocation = source[source.length - 1], - helperName = (DOT_LOOKUP_REGEX.exec(helperInvocation) || BRACKET_STRING_LOOKUP_REGEX.exec(helperInvocation))[1], - matches = INVOCATION_SPLITTING_REGEX.exec(helperInvocation); - - source[source.length - 1] = matches[1] + "'" + helperName + "'" + matches[3]; - }; - - var stringifyBlockHelperMissing = EmberHandlebars.JavaScriptCompiler.stringifyLastBlockHelperMissingInvocation; - - var originalBlockValue = EmberHandlebars.JavaScriptCompiler.prototype.blockValue; - EmberHandlebars.JavaScriptCompiler.prototype.blockValue = function() { - originalBlockValue.apply(this, arguments); - stringifyBlockHelperMissing(this.source); - }; - - var originalAmbiguousBlockValue = EmberHandlebars.JavaScriptCompiler.prototype.ambiguousBlockValue; - EmberHandlebars.JavaScriptCompiler.prototype.ambiguousBlockValue = function() { - originalAmbiguousBlockValue.apply(this, arguments); - stringifyBlockHelperMissing(this.source); - }; - - /** - Rewrite simple mustaches from `{{foo}}` to `{{bind "foo"}}`. This means that - all simple mustaches in Ember's Handlebars will also set up an observer to - keep the DOM up to date when the underlying property changes. - - @private - @method mustache - @for Ember.Handlebars.Compiler - @param mustache - */ - EmberHandlebars.Compiler.prototype.mustache = function(mustache) { - if (!(mustache.params.length || mustache.hash)) { - var id = new Handlebars.AST.IdNode([{ part: '_triageMustache' }]); - - // Update the mustache node to include a hash value indicating whether the original node - // was escaped. This will allow us to properly escape values when the underlying value - // changes and we need to re-render the value. - if (!mustache.escaped) { - mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]); - mustache.hash.pairs.push(["unescaped", new Handlebars.AST.StringNode("true")]); - } - mustache = new Handlebars.AST.MustacheNode([id].concat([mustache.id]), mustache.hash, !mustache.escaped); - } - - return Handlebars.Compiler.prototype.mustache.call(this, mustache); - }; - - /** - Used for precompilation of Ember Handlebars templates. This will not be used - during normal app execution. - - @method precompile - @for Ember.Handlebars - @static - @param {String} string The template to precompile - @param {Boolean} asObject optional parameter, defaulting to true, of whether or not the - compiled template should be returned as an Object or a String - */ - EmberHandlebars.precompile = function(string, asObject) { - var ast = Handlebars.parse(string); - - var options = { - knownHelpers: { - action: true, - unbound: true, - 'bind-attr': true, - template: true, - view: true, - _triageMustache: true - }, - data: true, - stringParams: true - }; - - asObject = asObject === undefined ? true : asObject; - - var environment = new EmberHandlebars.Compiler().compile(ast, options); - return new EmberHandlebars.JavaScriptCompiler().compile(environment, options, undefined, asObject); - }; - - // We don't support this for Handlebars runtime-only - if (Handlebars.compile) { - /** - The entry point for Ember Handlebars. This replaces the default - `Handlebars.compile` and turns on template-local data and String - parameters. - - @method compile - @for Ember.Handlebars - @static - @param {String} string The template to compile - @return {Function} - */ - EmberHandlebars.compile = function(string) { - var ast = Handlebars.parse(string); - var options = { data: true, stringParams: true }; - var environment = new EmberHandlebars.Compiler().compile(ast, options); - var templateSpec = new EmberHandlebars.JavaScriptCompiler().compile(environment, options, undefined, true); - - var template = EmberHandlebars.template(templateSpec); - template.isMethod = false; //Make sure we don't wrap templates with ._super - - return template; - }; - } - - __exports__["default"] = EmberHandlebars; - }); -define("ember-handlebars", - ["ember-handlebars-compiler","ember-metal/core","ember-runtime/system/lazy_load","ember-handlebars/loader","ember-handlebars/ext","ember-handlebars/string","ember-handlebars/helpers/shared","ember-handlebars/helpers/binding","ember-handlebars/helpers/collection","ember-handlebars/helpers/view","ember-handlebars/helpers/unbound","ember-handlebars/helpers/debug","ember-handlebars/helpers/each","ember-handlebars/helpers/template","ember-handlebars/helpers/partial","ember-handlebars/helpers/yield","ember-handlebars/helpers/loc","ember-handlebars/controls/checkbox","ember-handlebars/controls/select","ember-handlebars/controls/text_area","ember-handlebars/controls/text_field","ember-handlebars/controls/text_support","ember-handlebars/controls","ember-handlebars/component_lookup","ember-handlebars/views/handlebars_bound_view","ember-handlebars/views/metamorph_view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __exports__) { - "use strict"; - var EmberHandlebars = __dependency1__["default"]; - var Ember = __dependency2__["default"]; - // to add to globals - - var runLoadHooks = __dependency3__.runLoadHooks; - var bootstrap = __dependency4__["default"]; - - var normalizePath = __dependency5__.normalizePath; - var template = __dependency5__.template; - var makeBoundHelper = __dependency5__.makeBoundHelper; - var registerBoundHelper = __dependency5__.registerBoundHelper; - var resolveHash = __dependency5__.resolveHash; - var resolveParams = __dependency5__.resolveParams; - var getEscaped = __dependency5__.getEscaped; - var handlebarsGet = __dependency5__.handlebarsGet; - var evaluateUnboundHelper = __dependency5__.evaluateUnboundHelper; - var helperMissingHelper = __dependency5__.helperMissingHelper; - var blockHelperMissingHelper = __dependency5__.blockHelperMissingHelper; - - - // side effect of extending StringUtils of htmlSafe - - var resolvePaths = __dependency7__["default"]; - var bind = __dependency8__.bind; - var _triageMustacheHelper = __dependency8__._triageMustacheHelper; - var resolveHelper = __dependency8__.resolveHelper; - var bindHelper = __dependency8__.bindHelper; - var boundIfHelper = __dependency8__.boundIfHelper; - var unboundIfHelper = __dependency8__.unboundIfHelper; - var withHelper = __dependency8__.withHelper; - var ifHelper = __dependency8__.ifHelper; - var unlessHelper = __dependency8__.unlessHelper; - var bindAttrHelper = __dependency8__.bindAttrHelper; - var bindAttrHelperDeprecated = __dependency8__.bindAttrHelperDeprecated; - var bindClasses = __dependency8__.bindClasses; - - var collectionHelper = __dependency9__["default"]; - var ViewHelper = __dependency10__.ViewHelper; - var viewHelper = __dependency10__.viewHelper; - var unboundHelper = __dependency11__["default"]; - var logHelper = __dependency12__.logHelper; - var debuggerHelper = __dependency12__.debuggerHelper; - var EachView = __dependency13__.EachView; - var GroupedEach = __dependency13__.GroupedEach; - var eachHelper = __dependency13__.eachHelper; - var templateHelper = __dependency14__["default"]; - var partialHelper = __dependency15__["default"]; - var yieldHelper = __dependency16__["default"]; - var locHelper = __dependency17__["default"]; - - - var Checkbox = __dependency18__["default"]; - var Select = __dependency19__.Select; - var SelectOption = __dependency19__.SelectOption; - var SelectOptgroup = __dependency19__.SelectOptgroup; - var TextArea = __dependency20__["default"]; - var TextField = __dependency21__["default"]; - var TextSupport = __dependency22__["default"]; - var inputHelper = __dependency23__.inputHelper; - var textareaHelper = __dependency23__.textareaHelper; - - - var ComponentLookup = __dependency24__["default"]; - var _HandlebarsBoundView = __dependency25__._HandlebarsBoundView; - var SimpleHandlebarsView = __dependency25__.SimpleHandlebarsView; - var _wrapMap = __dependency26__._wrapMap; - var _SimpleMetamorphView = __dependency26__._SimpleMetamorphView; - var _MetamorphView = __dependency26__._MetamorphView; - var _Metamorph = __dependency26__._Metamorph; - - - /** - Ember Handlebars - - @module ember - @submodule ember-handlebars - @requires ember-views - */ - - // Ember.Handlebars.Globals - EmberHandlebars.bootstrap = bootstrap; - EmberHandlebars.template = template; - EmberHandlebars.makeBoundHelper = makeBoundHelper; - EmberHandlebars.registerBoundHelper = registerBoundHelper; - EmberHandlebars.resolveHash = resolveHash; - EmberHandlebars.resolveParams = resolveParams; - EmberHandlebars.resolveHelper = resolveHelper; - EmberHandlebars.get = handlebarsGet; - EmberHandlebars.getEscaped = getEscaped; - EmberHandlebars.evaluateUnboundHelper = evaluateUnboundHelper; - EmberHandlebars.bind = bind; - EmberHandlebars.bindClasses = bindClasses; - EmberHandlebars.EachView = EachView; - EmberHandlebars.GroupedEach = GroupedEach; - EmberHandlebars.resolvePaths = resolvePaths; - EmberHandlebars.ViewHelper = ViewHelper; - EmberHandlebars.normalizePath = normalizePath; - - - // Ember Globals - Ember.Handlebars = EmberHandlebars; - Ember.ComponentLookup = ComponentLookup; - Ember._SimpleHandlebarsView = SimpleHandlebarsView; - Ember._HandlebarsBoundView = _HandlebarsBoundView; - Ember._SimpleMetamorphView = _SimpleMetamorphView; - Ember._MetamorphView = _MetamorphView; - Ember._Metamorph = _Metamorph; - Ember._metamorphWrapMap = _wrapMap; - Ember.TextSupport = TextSupport; - Ember.Checkbox = Checkbox; - Ember.Select = Select; - Ember.SelectOption = SelectOption; - Ember.SelectOptgroup = SelectOptgroup; - Ember.TextArea = TextArea; - Ember.TextField = TextField; - Ember.TextSupport = TextSupport; - - // register helpers - EmberHandlebars.registerHelper('helperMissing', helperMissingHelper); - EmberHandlebars.registerHelper('blockHelperMissing', blockHelperMissingHelper); - EmberHandlebars.registerHelper('bind', bindHelper); - EmberHandlebars.registerHelper('boundIf', boundIfHelper); - EmberHandlebars.registerHelper('_triageMustache', _triageMustacheHelper); - EmberHandlebars.registerHelper('unboundIf', unboundIfHelper); - EmberHandlebars.registerHelper('with', withHelper); - EmberHandlebars.registerHelper('if', ifHelper); - EmberHandlebars.registerHelper('unless', unlessHelper); - EmberHandlebars.registerHelper('bind-attr', bindAttrHelper); - EmberHandlebars.registerHelper('bindAttr', bindAttrHelperDeprecated); - EmberHandlebars.registerHelper('collection', collectionHelper); - EmberHandlebars.registerHelper("log", logHelper); - EmberHandlebars.registerHelper("debugger", debuggerHelper); - EmberHandlebars.registerHelper("each", eachHelper); - EmberHandlebars.registerHelper("loc", locHelper); - EmberHandlebars.registerHelper("partial", partialHelper); - EmberHandlebars.registerHelper("template", templateHelper); - EmberHandlebars.registerHelper("yield", yieldHelper); - EmberHandlebars.registerHelper("view", viewHelper); - EmberHandlebars.registerHelper("unbound", unboundHelper); - EmberHandlebars.registerHelper("input", inputHelper); - EmberHandlebars.registerHelper("textarea", textareaHelper); - - // run load hooks - runLoadHooks('Ember.Handlebars', EmberHandlebars); - - __exports__["default"] = EmberHandlebars; - }); -define("ember-handlebars/component_lookup", - ["ember-runtime/system/object","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var EmberObject = __dependency1__["default"]; - - var ComponentLookup = EmberObject.extend({ - lookupFactory: function(name, container) { - - container = container || this.container; - - var fullName = 'component:' + name, - templateFullName = 'template:components/' + name, - templateRegistered = container && container.has(templateFullName); - - if (templateRegistered) { - container.injection(fullName, 'layout', templateFullName); - } - - var Component = container.lookupFactory(fullName); - - // Only treat as a component if either the component - // or a template has been registered. - if (templateRegistered || Component) { - if (!Component) { - container.register(fullName, Ember.Component); - Component = container.lookupFactory(fullName); - } - return Component; - } - } - }); - - __exports__["default"] = ComponentLookup; - }); -define("ember-handlebars/controls", - ["ember-handlebars/controls/checkbox","ember-handlebars/controls/text_field","ember-handlebars/controls/text_area","ember-metal/core","ember-handlebars-compiler","ember-handlebars/ext","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) { - "use strict"; - var Checkbox = __dependency1__["default"]; - var TextField = __dependency2__["default"]; - var TextArea = __dependency3__["default"]; - - var Ember = __dependency4__["default"]; - // Ember.assert - // var emberAssert = Ember.assert; - - var EmberHandlebars = __dependency5__["default"]; - var handlebarsGet = __dependency6__.handlebarsGet; - var helpers = EmberHandlebars.helpers; - /** - @module ember - @submodule ember-handlebars-compiler - */ - - function _resolveOption(context, options, key) { - if (options.hashTypes[key] === "ID") { - return handlebarsGet(context, options.hash[key], options); - } else { - return options.hash[key]; - } - } - - /** - - The `{{input}}` helper inserts an HTML `` tag into the template, - with a `type` value of either `text` or `checkbox`. If no `type` is provided, - `text` will be the default value applied. The attributes of `{{input}}` - match those of the native HTML tag as closely as possible for these two types. - - ## Use as text field - An `{{input}}` with no `type` or a `type` of `text` will render an HTML text input. - The following HTML attributes can be set via the helper: - - - - - - - - - - - - -
`readonly``required``autofocus`
`value``placeholder``disabled`
`size``tabindex``maxlength`
`name``min``max`
`pattern``accept``autocomplete`
`autosave``formaction``formenctype`
`formmethod``formnovalidate``formtarget`
`height``inputmode``multiple`
`step``width``form`
`selectionDirection``spellcheck` 
- - - When set to a quoted string, these values will be directly applied to the HTML - element. When left unquoted, these values will be bound to a property on the - template's current rendering context (most typically a controller instance). - - ## Unbound: - - ```handlebars - {{input value="http://www.facebook.com"}} - ``` - - - ```html - - ``` - - ## Bound: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - firstName: "Stanley", - entryNotAllowed: true - }); - ``` - - - ```handlebars - {{input type="text" value=firstName disabled=entryNotAllowed size="50"}} - ``` - - - ```html - - ``` - - ## Actions - - The helper can send multiple actions based on user events. - - The action property defines the action which is send when - the user presses the return key. - - ```handlebars - {{input action="submit"}} - ``` - - The helper allows some user events to send actions. - - * `enter` - * `insert-newline` - * `escape-press` - * `focus-in` - * `focus-out` - * `key-press` - - For example, if you desire an action to be sent when the input is blurred, - you only need to setup the action name to the event name property. - - ```handlebars - {{input focus-in="alertMessage"}} - ``` - - See more about [Text Support Actions](/api/classes/Ember.TextField.html) - - ## Extension - - Internally, `{{input type="text"}}` creates an instance of `Ember.TextField`, passing - arguments from the helper to `Ember.TextField`'s `create` method. You can extend the - capabilities of text inputs in your applications by reopening this class. For example, - if you are building a Bootstrap project where `data-*` attributes are used, you - can add one to the `TextField`'s `attributeBindings` property: - - - ```javascript - Ember.TextField.reopen({ - attributeBindings: ['data-error'] - }); - ``` - - Keep in mind when writing `Ember.TextField` subclasses that `Ember.TextField` - itself extends `Ember.Component`, meaning that it does NOT inherit - the `controller` of the parent view. - - See more about [Ember components](/api/classes/Ember.Component.html) - - - ## Use as checkbox - - An `{{input}}` with a `type` of `checkbox` will render an HTML checkbox input. - The following HTML attributes can be set via the helper: - - * `checked` - * `disabled` - * `tabindex` - * `indeterminate` - * `name` - * `autofocus` - * `form` - - - When set to a quoted string, these values will be directly applied to the HTML - element. When left unquoted, these values will be bound to a property on the - template's current rendering context (most typically a controller instance). - - ## Unbound: - - ```handlebars - {{input type="checkbox" name="isAdmin"}} - ``` - - ```html - - ``` - - ## Bound: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - isAdmin: true - }); - ``` - - - ```handlebars - {{input type="checkbox" checked=isAdmin }} - ``` - - - ```html - - ``` - - ## Extension - - Internally, `{{input type="checkbox"}}` creates an instance of `Ember.Checkbox`, passing - arguments from the helper to `Ember.Checkbox`'s `create` method. You can extend the - capablilties of checkbox inputs in your applications by reopening this class. For example, - if you wanted to add a css class to all checkboxes in your application: - - - ```javascript - Ember.Checkbox.reopen({ - classNames: ['my-app-checkbox'] - }); - ``` - - - @method input - @for Ember.Handlebars.helpers - @param {Hash} options - */ - function inputHelper(options) { - - var hash = options.hash, - types = options.hashTypes, - inputType = _resolveOption(this, options, 'type'), - onEvent = hash.on; - - delete hash.type; - delete hash.on; - - if (inputType === 'checkbox') { - return helpers.view.call(this, Checkbox, options); - } else { - if (inputType) { hash.type = inputType; } - hash.onEvent = onEvent || 'enter'; - return helpers.view.call(this, TextField, options); - } - } - - __exports__.inputHelper = inputHelper;/** - `{{textarea}}` inserts a new instance of ` - ``` - - Bound: - - In the following example, the `writtenWords` property on `App.ApplicationController` - will be updated live as the user types 'Lots of text that IS bound' into - the text area of their browser's window. - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - writtenWords: "Lots of text that IS bound" - }); - ``` - - ```handlebars - {{textarea value=writtenWords}} - ``` - - Would result in the following HTML: - - ```html - - ``` - - If you wanted a one way binding between the text area and a div tag - somewhere else on your screen, you could use `Ember.computed.oneWay`: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - writtenWords: "Lots of text that IS bound", - outputWrittenWords: Ember.computed.oneWay("writtenWords") - }); - ``` - - ```handlebars - {{textarea value=writtenWords}} - -
- {{outputWrittenWords}} -
- ``` - - Would result in the following HTML: - - ```html - - - <-- the following div will be updated in real time as you type --> - -
- Lots of text that IS bound -
- ``` - - Finally, this example really shows the power and ease of Ember when two - properties are bound to eachother via `Ember.computed.alias`. Type into - either text area box and they'll both stay in sync. Note that - `Ember.computed.alias` costs more in terms of performance, so only use it when - your really binding in both directions: - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - writtenWords: "Lots of text that IS bound", - twoWayWrittenWords: Ember.computed.alias("writtenWords") - }); - ``` - - ```handlebars - {{textarea value=writtenWords}} - {{textarea value=twoWayWrittenWords}} - ``` - - ```html - - - <-- both updated in real time --> - - - ``` - - ## Actions - - The helper can send multiple actions based on user events. - - The action property defines the action which is send when - the user presses the return key. - - ```handlebars - {{input action="submit"}} - ``` - - The helper allows some user events to send actions. - - * `enter` - * `insert-newline` - * `escape-press` - * `focus-in` - * `focus-out` - * `key-press` - - For example, if you desire an action to be sent when the input is blurred, - you only need to setup the action name to the event name property. - - ```handlebars - {{textarea focus-in="alertMessage"}} - ``` - - See more about [Text Support Actions](/api/classes/Ember.TextArea.html) - - ## Extension - - Internally, `{{textarea}}` creates an instance of `Ember.TextArea`, passing - arguments from the helper to `Ember.TextArea`'s `create` method. You can - extend the capabilities of text areas in your application by reopening this - class. For example, if you are building a Bootstrap project where `data-*` - attributes are used, you can globally add support for a `data-*` attribute - on all `{{textarea}}`s' in your app by reopening `Ember.TextArea` or - `Ember.TextSupport` and adding it to the `attributeBindings` concatenated - property: - - ```javascript - Ember.TextArea.reopen({ - attributeBindings: ['data-error'] - }); - ``` - - Keep in mind when writing `Ember.TextArea` subclasses that `Ember.TextArea` - itself extends `Ember.Component`, meaning that it does NOT inherit - the `controller` of the parent view. - - See more about [Ember components](/api/classes/Ember.Component.html) - - @method textarea - @for Ember.Handlebars.helpers - @param {Hash} options - */ - function textareaHelper(options) { - - var hash = options.hash, - types = options.hashTypes; - - return helpers.view.call(this, TextArea, options); - } - - __exports__.textareaHelper = textareaHelper; - }); -define("ember-handlebars/controls/checkbox", - ["ember-metal/property_get","ember-metal/property_set","ember-views/views/view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var set = __dependency2__.set; - var View = __dependency3__["default"]; - - /** - @module ember - @submodule ember-handlebars - */ - - /** - The internal class used to create text inputs when the `{{input}}` - helper is used with `type` of `checkbox`. - - See [handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input) for usage details. - - ## Direct manipulation of `checked` - - The `checked` attribute of an `Ember.Checkbox` object should always be set - through the Ember object or by interacting with its rendered element - representation via the mouse, keyboard, or touch. Updating the value of the - checkbox via jQuery will result in the checked value of the object and its - element losing synchronization. - - ## Layout and LayoutName properties - - Because HTML `input` elements are self closing `layout` and `layoutName` - properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s - layout section for more information. - - @class Checkbox - @namespace Ember - @extends Ember.View - */ - __exports__["default"] = View.extend({ - instrumentDisplay: '{{input type="checkbox"}}', - - classNames: ['ember-checkbox'], - - tagName: 'input', - - attributeBindings: [ - 'type', - 'checked', - 'indeterminate', - 'disabled', - 'tabindex', - 'name', - 'autofocus', - 'required', - 'form' - ], - - type: 'checkbox', - checked: false, - disabled: false, - indeterminate: false, - - init: function() { - this._super(); - this.on('change', this, this._updateElementValue); - }, - - didInsertElement: function() { - this._super(); - get(this, 'element').indeterminate = !!get(this, 'indeterminate'); - }, - - _updateElementValue: function() { - set(this, 'checked', this.$().prop('checked')); - } - }); - }); -define("ember-handlebars/controls/select", - ["ember-handlebars-compiler","ember-metal/enumerable_utils","ember-metal/property_get","ember-metal/property_set","ember-views/views/view","ember-views/views/collection_view","ember-metal/utils","ember-metal/is_none","ember-metal/computed","ember-runtime/system/native_array","ember-metal/mixin","ember-metal/properties","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var EmberHandlebars = __dependency1__["default"]; - - var forEach = __dependency2__.forEach; - var indexOf = __dependency2__.indexOf; - var indexesOf = __dependency2__.indexesOf; - var replace = __dependency2__.replace; - - var get = __dependency3__.get; - var set = __dependency4__.set; - var View = __dependency5__["default"]; - var CollectionView = __dependency6__["default"]; - var isArray = __dependency7__.isArray; - var isNone = __dependency8__["default"]; - var computed = __dependency9__.computed; - var emberA = __dependency10__.A; - var observer = __dependency11__.observer; - var defineProperty = __dependency12__.defineProperty; - - var precompileTemplate = EmberHandlebars.compile; - - var SelectOption = View.extend({ - instrumentDisplay: 'Ember.SelectOption', - - tagName: 'option', - attributeBindings: ['value', 'selected'], - - defaultTemplate: function(context, options) { - options = { data: options.data, hash: {} }; - EmberHandlebars.helpers.bind.call(context, "view.label", options); - }, - - init: function() { - this.labelPathDidChange(); - this.valuePathDidChange(); - - this._super(); - }, - - selected: computed(function() { - var content = get(this, 'content'), - selection = get(this, 'parentView.selection'); - if (get(this, 'parentView.multiple')) { - return selection && indexOf(selection, content.valueOf()) > -1; - } else { - // Primitives get passed through bindings as objects... since - // `new Number(4) !== 4`, we use `==` below - return content == selection; // jshint ignore:line - } - }).property('content', 'parentView.selection'), - - labelPathDidChange: observer('parentView.optionLabelPath', function() { - var labelPath = get(this, 'parentView.optionLabelPath'); - - if (!labelPath) { return; } - - defineProperty(this, 'label', computed(function() { - return get(this, labelPath); - }).property(labelPath)); - }), - - valuePathDidChange: observer('parentView.optionValuePath', function() { - var valuePath = get(this, 'parentView.optionValuePath'); - - if (!valuePath) { return; } - - defineProperty(this, 'value', computed(function() { - return get(this, valuePath); - }).property(valuePath)); - }) - }); - - var SelectOptgroup = CollectionView.extend({ - instrumentDisplay: 'Ember.SelectOptgroup', - - tagName: 'optgroup', - attributeBindings: ['label'], - - selectionBinding: 'parentView.selection', - multipleBinding: 'parentView.multiple', - optionLabelPathBinding: 'parentView.optionLabelPath', - optionValuePathBinding: 'parentView.optionValuePath', - - itemViewClassBinding: 'parentView.optionView' - }); - - /** - The `Ember.Select` view class renders a - [select](https://developer.mozilla.org/en/HTML/Element/select) HTML element, - allowing the user to choose from a list of options. - - The text and `value` property of each ` - - - ``` - - The `value` attribute of the selected `"); - return buffer; - } - - function program3(depth0,data) { - - var stack1; - stack1 = helpers.each.call(depth0, "view.groupedContent", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(4, program4, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - else { data.buffer.push(''); } - } - function program4(depth0,data) { - - - data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.groupView", {hash:{ - 'content': ("content"), - 'label': ("label") - },hashTypes:{'content': "ID",'label': "ID"},hashContexts:{'content': depth0,'label': depth0},contexts:[depth0],types:["ID"],data:data}))); - } - - function program6(depth0,data) { - - var stack1; - stack1 = helpers.each.call(depth0, "view.content", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(7, program7, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - else { data.buffer.push(''); } - } - function program7(depth0,data) { - - - data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.optionView", {hash:{ - 'content': ("") - },hashTypes:{'content': "ID"},hashContexts:{'content': depth0},contexts:[depth0],types:["ID"],data:data}))); - } - - stack1 = helpers['if'].call(depth0, "view.prompt", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - stack1 = helpers['if'].call(depth0, "view.optionGroupPath", {hash:{},hashTypes:{},hashContexts:{},inverse:self.program(6, program6, data),fn:self.program(3, program3, data),contexts:[depth0],types:["ID"],data:data}); - if(stack1 || stack1 === 0) { data.buffer.push(stack1); } - return buffer; - - }), - attributeBindings: ['multiple', 'disabled', 'tabindex', 'name', 'required', 'autofocus', - 'form', 'size'], - - /** - The `multiple` attribute of the select element. Indicates whether multiple - options can be selected. - - @property multiple - @type Boolean - @default false - */ - multiple: false, - - /** - The `disabled` attribute of the select element. Indicates whether - the element is disabled from interactions. - - @property disabled - @type Boolean - @default false - */ - disabled: false, - - /** - The `required` attribute of the select element. Indicates whether - a selected option is required for form validation. - - @property required - @type Boolean - @default false - @since 1.5.0 - */ - required: false, - - /** - The list of options. - - If `optionLabelPath` and `optionValuePath` are not overridden, this should - be a list of strings, which will serve simultaneously as labels and values. - - Otherwise, this should be a list of objects. For instance: - - ```javascript - Ember.Select.create({ - content: Ember.A([ - { id: 1, firstName: 'Yehuda' }, - { id: 2, firstName: 'Tom' } - ]), - optionLabelPath: 'content.firstName', - optionValuePath: 'content.id' - }); - ``` - - @property content - @type Array - @default null - */ - content: null, - - /** - When `multiple` is `false`, the element of `content` that is currently - selected, if any. - - When `multiple` is `true`, an array of such elements. - - @property selection - @type Object or Array - @default null - */ - selection: null, - - /** - In single selection mode (when `multiple` is `false`), value can be used to - get the current selection's value or set the selection by it's value. - - It is not currently supported in multiple selection mode. - - @property value - @type String - @default null - */ - value: computed(function(key, value) { - if (arguments.length === 2) { return value; } - var valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''); - return valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection'); - }).property('selection'), - - /** - If given, a top-most dummy option will be rendered to serve as a user - prompt. - - @property prompt - @type String - @default null - */ - prompt: null, - - /** - The path of the option labels. See [content](/api/classes/Ember.Select.html#property_content). - - @property optionLabelPath - @type String - @default 'content' - */ - optionLabelPath: 'content', - - /** - The path of the option values. See [content](/api/classes/Ember.Select.html#property_content). - - @property optionValuePath - @type String - @default 'content' - */ - optionValuePath: 'content', - - /** - The path of the option group. - When this property is used, `content` should be sorted by `optionGroupPath`. - - @property optionGroupPath - @type String - @default null - */ - optionGroupPath: null, - - /** - The view class for optgroup. - - @property groupView - @type Ember.View - @default Ember.SelectOptgroup - */ - groupView: SelectOptgroup, - - groupedContent: computed(function() { - var groupPath = get(this, 'optionGroupPath'); - var groupedContent = emberA(); - var content = get(this, 'content') || []; - - forEach(content, function(item) { - var label = get(item, groupPath); - - if (get(groupedContent, 'lastObject.label') !== label) { - groupedContent.pushObject({ - label: label, - content: emberA() - }); - } - - get(groupedContent, 'lastObject.content').push(item); - }); - - return groupedContent; - }).property('optionGroupPath', 'content.@each'), - - /** - The view class for option. - - @property optionView - @type Ember.View - @default Ember.SelectOption - */ - optionView: SelectOption, - - _change: function() { - if (get(this, 'multiple')) { - this._changeMultiple(); - } else { - this._changeSingle(); - } - }, - - selectionDidChange: observer('selection.@each', function() { - var selection = get(this, 'selection'); - if (get(this, 'multiple')) { - if (!isArray(selection)) { - set(this, 'selection', emberA([selection])); - return; - } - this._selectionDidChangeMultiple(); - } else { - this._selectionDidChangeSingle(); - } - }), - - valueDidChange: observer('value', function() { - var content = get(this, 'content'), - value = get(this, 'value'), - valuePath = get(this, 'optionValuePath').replace(/^content\.?/, ''), - selectedValue = (valuePath ? get(this, 'selection.' + valuePath) : get(this, 'selection')), - selection; - - if (value !== selectedValue) { - selection = content ? content.find(function(obj) { - return value === (valuePath ? get(obj, valuePath) : obj); - }) : null; - - this.set('selection', selection); - } - }), - - - _triggerChange: function() { - var selection = get(this, 'selection'); - var value = get(this, 'value'); - - if (!isNone(selection)) { this.selectionDidChange(); } - if (!isNone(value)) { this.valueDidChange(); } - - this._change(); - }, - - _changeSingle: function() { - var selectedIndex = this.$()[0].selectedIndex, - content = get(this, 'content'), - prompt = get(this, 'prompt'); - - if (!content || !get(content, 'length')) { return; } - if (prompt && selectedIndex === 0) { set(this, 'selection', null); return; } - - if (prompt) { selectedIndex -= 1; } - set(this, 'selection', content.objectAt(selectedIndex)); - }, - - - _changeMultiple: function() { - var options = this.$('option:selected'), - prompt = get(this, 'prompt'), - offset = prompt ? 1 : 0, - content = get(this, 'content'), - selection = get(this, 'selection'); - - if (!content) { return; } - if (options) { - var selectedIndexes = options.map(function() { - return this.index - offset; - }).toArray(); - var newSelection = content.objectsAt(selectedIndexes); - - if (isArray(selection)) { - replace(selection, 0, get(selection, 'length'), newSelection); - } else { - set(this, 'selection', newSelection); - } - } - }, - - _selectionDidChangeSingle: function() { - var el = this.get('element'); - if (!el) { return; } - - var content = get(this, 'content'), - selection = get(this, 'selection'), - selectionIndex = content ? indexOf(content, selection) : -1, - prompt = get(this, 'prompt'); - - if (prompt) { selectionIndex += 1; } - if (el) { el.selectedIndex = selectionIndex; } - }, - - _selectionDidChangeMultiple: function() { - var content = get(this, 'content'), - selection = get(this, 'selection'), - selectedIndexes = content ? indexesOf(content, selection) : [-1], - prompt = get(this, 'prompt'), - offset = prompt ? 1 : 0, - options = this.$('option'), - adjusted; - - if (options) { - options.each(function() { - adjusted = this.index > -1 ? this.index - offset : -1; - this.selected = indexOf(selectedIndexes, adjusted) > -1; - }); - } - }, - - init: function() { - this._super(); - this.on("didInsertElement", this, this._triggerChange); - this.on("change", this, this._change); - } - }); - - __exports__["default"] = Select; - __exports__.Select = Select; - __exports__.SelectOption = SelectOption; - __exports__.SelectOptgroup = SelectOptgroup; - }); -define("ember-handlebars/controls/text_area", - ["ember-metal/property_get","ember-views/views/component","ember-handlebars/controls/text_support","ember-metal/mixin","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - - /** - @module ember - @submodule ember-handlebars - */ - var get = __dependency1__.get; - var Component = __dependency2__["default"]; - var TextSupport = __dependency3__["default"]; - var observer = __dependency4__.observer; - - /** - The internal class used to create textarea element when the `{{textarea}}` - helper is used. - - See [handlebars.helpers.textarea](/api/classes/Ember.Handlebars.helpers.html#method_textarea) for usage details. - - ## Layout and LayoutName properties - - Because HTML `textarea` elements do not contain inner HTML the `layout` and - `layoutName` properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s - layout section for more information. - - @class TextArea - @namespace Ember - @extends Ember.Component - @uses Ember.TextSupport - */ - __exports__["default"] = Component.extend(TextSupport, { - instrumentDisplay: '{{textarea}}', - - classNames: ['ember-text-area'], - - tagName: "textarea", - attributeBindings: ['rows', 'cols', 'name', 'selectionEnd', 'selectionStart', 'wrap'], - rows: null, - cols: null, - - _updateElementValue: observer('value', function() { - // We do this check so cursor position doesn't get affected in IE - var value = get(this, 'value'), - $el = this.$(); - if ($el && value !== $el.val()) { - $el.val(value); - } - }), - - init: function() { - this._super(); - this.on("didInsertElement", this, this._updateElementValue); - } - }); - }); -define("ember-handlebars/controls/text_field", - ["ember-metal/property_get","ember-metal/property_set","ember-views/views/component","ember-handlebars/controls/text_support","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var get = __dependency1__.get; - var set = __dependency2__.set; - var Component = __dependency3__["default"]; - var TextSupport = __dependency4__["default"]; - - /** - - The internal class used to create text inputs when the `{{input}}` - helper is used with `type` of `text`. - - See [Handlebars.helpers.input](/api/classes/Ember.Handlebars.helpers.html#method_input) for usage details. - - ## Layout and LayoutName properties - - Because HTML `input` elements are self closing `layout` and `layoutName` - properties will not be applied. See [Ember.View](/api/classes/Ember.View.html)'s - layout section for more information. - - @class TextField - @namespace Ember - @extends Ember.Component - @uses Ember.TextSupport - */ - __exports__["default"] = Component.extend(TextSupport, { - instrumentDisplay: '{{input type="text"}}', - - classNames: ['ember-text-field'], - tagName: "input", - attributeBindings: ['type', 'value', 'size', 'pattern', 'name', 'min', 'max', - 'accept', 'autocomplete', 'autosave', 'formaction', - 'formenctype', 'formmethod', 'formnovalidate', 'formtarget', - 'height', 'inputmode', 'list', 'multiple', 'step', - 'width'], - - /** - The `value` attribute of the input element. As the user inputs text, this - property is updated live. - - @property value - @type String - @default "" - */ - value: "", - - /** - The `type` attribute of the input element. - - @property type - @type String - @default "text" - */ - type: "text", - - /** - The `size` of the text field in characters. - - @property size - @type String - @default null - */ - size: null, - - /** - The `pattern` attribute of input element. - - @property pattern - @type String - @default null - */ - pattern: null, - - /** - The `min` attribute of input element used with `type="number"` or `type="range"`. - - @property min - @type String - @default null - @since 1.4.0 - */ - min: null, - - /** - The `max` attribute of input element used with `type="number"` or `type="range"`. - - @property max - @type String - @default null - @since 1.4.0 - */ - max: null - }); - }); -define("ember-handlebars/controls/text_support", - ["ember-metal/property_get","ember-metal/property_set","ember-metal/mixin","ember-runtime/mixins/target_action_support","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var get = __dependency1__.get; - var set = __dependency2__.set; - var Mixin = __dependency3__.Mixin; - var TargetActionSupport = __dependency4__["default"]; - - /** - Shared mixin used by `Ember.TextField` and `Ember.TextArea`. - - @class TextSupport - @namespace Ember - @uses Ember.TargetActionSupport - @extends Ember.Mixin - @private - */ - var TextSupport = Mixin.create(TargetActionSupport, { - value: "", - - attributeBindings: ['placeholder', 'disabled', 'maxlength', 'tabindex', 'readonly', - 'autofocus', 'form', 'selectionDirection', 'spellcheck', 'required', - 'title', 'autocapitalize', 'autocorrect'], - placeholder: null, - disabled: false, - maxlength: null, - - init: function() { - this._super(); - this.on("focusOut", this, this._elementValueDidChange); - this.on("change", this, this._elementValueDidChange); - this.on("paste", this, this._elementValueDidChange); - this.on("cut", this, this._elementValueDidChange); - this.on("input", this, this._elementValueDidChange); - this.on("keyUp", this, this.interpretKeyEvents); - }, - - /** - The action to be sent when the user presses the return key. - - This is similar to the `{{action}}` helper, but is fired when - the user presses the return key when editing a text field, and sends - the value of the field as the context. - - @property action - @type String - @default null - */ - action: null, - - /** - The event that should send the action. - - Options are: - - * `enter`: the user pressed enter - * `keyPress`: the user pressed a key - - @property onEvent - @type String - @default enter - */ - onEvent: 'enter', - - /** - Whether they `keyUp` event that triggers an `action` to be sent continues - propagating to other views. - - By default, when the user presses the return key on their keyboard and - the text field has an `action` set, the action will be sent to the view's - controller and the key event will stop propagating. - - If you would like parent views to receive the `keyUp` event even after an - action has been dispatched, set `bubbles` to true. - - @property bubbles - @type Boolean - @default false - */ - bubbles: false, - - interpretKeyEvents: function(event) { - var map = TextSupport.KEY_EVENTS; - var method = map[event.keyCode]; - - this._elementValueDidChange(); - if (method) { return this[method](event); } - }, - - _elementValueDidChange: function() { - set(this, 'value', this.$().val()); - }, - - /** - Called when the user inserts a new line. - - Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 13. - Uses sendAction to send the `enter` action. - - @method insertNewline - @param {Event} event - */ - insertNewline: function(event) { - sendAction('enter', this, event); - sendAction('insert-newline', this, event); - }, - - /** - Called when the user hits escape. - - Called by the `Ember.TextSupport` mixin on keyUp if keycode matches 27. - Uses sendAction to send the `escape-press` action. - - @method cancel - @param {Event} event - */ - cancel: function(event) { - sendAction('escape-press', this, event); - }, - - /** - Called when the text area is focused. - - Uses sendAction to send the `focus-in` action. - - @method focusIn - @param {Event} event - */ - focusIn: function(event) { - sendAction('focus-in', this, event); - }, - - /** - Called when the text area is blurred. - - Uses sendAction to send the `focus-out` action. - - @method focusOut - @param {Event} event - */ - focusOut: function(event) { - sendAction('focus-out', this, event); - }, - - /** - Called when the user presses a key. Enabled by setting - the `onEvent` property to `keyPress`. - - Uses sendAction to send the `key-press` action. - - @method keyPress - @param {Event} event - */ - keyPress: function(event) { - sendAction('key-press', this, event); - } - - }); - - TextSupport.KEY_EVENTS = { - 13: 'insertNewline', - 27: 'cancel' - }; - - // In principle, this shouldn't be necessary, but the legacy - // sendAction semantics for TextField are different from - // the component semantics so this method normalizes them. - function sendAction(eventName, view, event) { - var action = get(view, eventName), - on = get(view, 'onEvent'), - value = get(view, 'value'); - - // back-compat support for keyPress as an event name even though - // it's also a method name that consumes the event (and therefore - // incompatible with sendAction semantics). - if (on === eventName || (on === 'keyPress' && eventName === 'key-press')) { - view.sendAction('action', value); - } - - view.sendAction(eventName, value); - - if (action || on === eventName) { - if(!get(view, 'bubbles')) { - event.stopPropagation(); - } - } - } - - __exports__["default"] = TextSupport; - }); -define("ember-handlebars/ext", - ["ember-metal/core","ember-runtime/system/string","ember-handlebars-compiler","ember-metal/property_get","ember-metal/binding","ember-metal/error","ember-metal/mixin","ember-metal/is_empty","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.FEATURES, Ember.assert, Ember.Handlebars, Ember.lookup - // var emberAssert = Ember.assert; - - var fmt = __dependency2__.fmt; - - var EmberHandlebars = __dependency3__["default"]; - var helpers = EmberHandlebars.helpers; - - var get = __dependency4__.get; - var isGlobalPath = __dependency5__.isGlobalPath; - var EmberError = __dependency6__["default"]; - var IS_BINDING = __dependency7__.IS_BINDING; - - // late bound via requireModule because of circular dependencies. - var resolveHelper, - SimpleHandlebarsView; - - var isEmpty = __dependency8__["default"]; - - var slice = [].slice, originalTemplate = EmberHandlebars.template; - - /** - If a path starts with a reserved keyword, returns the root - that should be used. - - @private - @method normalizePath - @for Ember - @param root {Object} - @param path {String} - @param data {Hash} - */ - function normalizePath(root, path, data) { - var keywords = (data && data.keywords) || {}, - keyword, isKeyword; - - // Get the first segment of the path. For example, if the - // path is "foo.bar.baz", returns "foo". - keyword = path.split('.', 1)[0]; - - // Test to see if the first path is a keyword that has been - // passed along in the view's data hash. If so, we will treat - // that object as the new root. - if (keywords.hasOwnProperty(keyword)) { - // Look up the value in the template's data hash. - root = keywords[keyword]; - isKeyword = true; - - // Handle cases where the entire path is the reserved - // word. In that case, return the object itself. - if (path === keyword) { - path = ''; - } else { - // Strip the keyword from the path and look up - // the remainder from the newly found root. - path = path.substr(keyword.length+1); - } - } - - return { root: root, path: path, isKeyword: isKeyword }; - } - - - /** - Lookup both on root and on window. If the path starts with - a keyword, the corresponding object will be looked up in the - template's data hash and used to resolve the path. - - @method get - @for Ember.Handlebars - @param {Object} root The object to look up the property on - @param {String} path The path to be lookedup - @param {Object} options The template's option hash - */ - function handlebarsGet(root, path, options) { - var data = options && options.data, - normalizedPath = normalizePath(root, path, data), - value; - - - root = normalizedPath.root; - path = normalizedPath.path; - - value = get(root, path); - - if (value === undefined && root !== Ember.lookup && isGlobalPath(path)) { - value = get(Ember.lookup, path); - } - - - return value; - } - - /** - This method uses `Ember.Handlebars.get` to lookup a value, then ensures - that the value is escaped properly. - - If `unescaped` is a truthy value then the escaping will not be performed. - - @method getEscaped - @for Ember.Handlebars - @param {Object} root The object to look up the property on - @param {String} path The path to be lookedup - @param {Object} options The template's option hash - @since 1.4.0 - */ - function getEscaped(root, path, options) { - var result = handlebarsGet(root, path, options); - - if (result === null || result === undefined) { - result = ""; - } else if (!(result instanceof Handlebars.SafeString)) { - result = String(result); - } - if (!options.hash.unescaped){ - result = Handlebars.Utils.escapeExpression(result); - } - - return result; - } - - __exports__.getEscaped = getEscaped;function resolveParams(context, params, options) { - var resolvedParams = [], types = options.types, param, type; - - for (var i=0, l=params.length; i{{user.name}} - -
-
{{user.role.label}}
- {{user.role.id}} - -

{{user.role.description}}

-
- ``` - - `{{with}}` can be our best friend in these cases, - instead of writing `user.role.*` over and over, we use `{{#with user.role}}`. - Now the context within the `{{#with}} .. {{/with}}` block is `user.role` so you can do the following: - - ```handlebars -
{{user.name}}
- -
- {{#with user.role}} -
{{label}}
- {{id}} - -

{{description}}

- {{/with}} -
- ``` - - ### `as` operator - - This operator aliases the scope to a new name. It's helpful for semantic clarity and to retain - default scope or to reference from another `{{with}}` block. - - ```handlebars - // posts might not be - {{#with user.posts as blogPosts}} -
- There are {{blogPosts.length}} blog posts written by {{user.name}}. -
- - {{#each post in blogPosts}} -
  • {{post.title}}
  • - {{/each}} - {{/with}} - ``` - - Without the `as` operator, it would be impossible to reference `user.name` in the example above. - - NOTE: The alias should not reuse a name from the bound property path. - For example: `{{#with foo.bar as foo}}` is not supported because it attempts to alias using - the first part of the property path, `foo`. Instead, use `{{#with foo.bar as baz}}`. - - ### `controller` option - - Adding `controller='something'` instructs the `{{with}}` helper to create and use an instance of - the specified controller with the new context as its content. - - This is very similar to using an `itemController` option with the `{{each}}` helper. - - ```handlebars - {{#with users.posts controller='userBlogPosts'}} - {{!- The current context is wrapped in our controller instance }} - {{/with}} - ``` - - In the above example, the template provided to the `{{with}}` block is now wrapped in the - `userBlogPost` controller, which provides a very elegant way to decorate the context with custom - functions/properties. - - @method with - @for Ember.Handlebars.helpers - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function withHelper(context, options) { - var bindContext, preserveContext, controller, helperName = 'with'; - - if (arguments.length === 4) { - var keywordName, path, rootPath, normalized, contextPath; - - options = arguments[3]; - keywordName = arguments[2]; - path = arguments[0]; - - if (path) { - helperName += ' ' + path + ' as ' + keywordName; - } - - - var localizedOptions = o_create(options); - localizedOptions.data = o_create(options.data); - localizedOptions.data.keywords = o_create(options.data.keywords || {}); - - if (isGlobalPath(path)) { - contextPath = path; - } else { - normalized = normalizePath(this, path, options.data); - path = normalized.path; - rootPath = normalized.root; - - // This is a workaround for the fact that you cannot bind separate objects - // together. When we implement that functionality, we should use it here. - var contextKey = jQuery.expando + guidFor(rootPath); - localizedOptions.data.keywords[contextKey] = rootPath; - // if the path is '' ("this"), just bind directly to the current context - contextPath = path ? contextKey + '.' + path : contextKey; - } - - localizedOptions.hash.keywordName = keywordName; - localizedOptions.hash.keywordPath = contextPath; - - bindContext = this; - context = contextPath; - options = localizedOptions; - preserveContext = true; - } else { - - helperName += ' ' + context; - bindContext = options.contexts[0]; - preserveContext = false; - } - - options.helperName = helperName; - options.isWithHelper = true; - - return bind.call(bindContext, context, options, preserveContext, exists); - } - /** - See [boundIf](/api/classes/Ember.Handlebars.helpers.html#method_boundIf) - and [unboundIf](/api/classes/Ember.Handlebars.helpers.html#method_unboundIf) - - @method if - @for Ember.Handlebars.helpers - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function ifHelper(context, options) { - - options.helperName = options.helperName || ('if ' + context); - - if (options.data.isUnbound) { - return helpers.unboundIf.call(options.contexts[0], context, options); - } else { - return helpers.boundIf.call(options.contexts[0], context, options); - } - } - - /** - @method unless - @for Ember.Handlebars.helpers - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function unlessHelper(context, options) { - - var fn = options.fn, inverse = options.inverse, helperName = 'unless'; - - if (context) { - helperName += ' ' + context; - } - - options.fn = inverse; - options.inverse = fn; - - options.helperName = options.helperName || helperName; - - if (options.data.isUnbound) { - return helpers.unboundIf.call(options.contexts[0], context, options); - } else { - return helpers.boundIf.call(options.contexts[0], context, options); - } - } - - /** - `bind-attr` allows you to create a binding between DOM element attributes and - Ember objects. For example: - - ```handlebars - imageTitle - ``` - - The above handlebars template will fill the ``'s `src` attribute with - the value of the property referenced with `"imageUrl"` and its `alt` - attribute with the value of the property referenced with `"imageTitle"`. - - If the rendering context of this template is the following object: - - ```javascript - { - imageUrl: 'http://lolcats.info/haz-a-funny', - imageTitle: 'A humorous image of a cat' - } - ``` - - The resulting HTML output will be: - - ```html - A humorous image of a cat - ``` - - `bind-attr` cannot redeclare existing DOM element attributes. The use of `src` - in the following `bind-attr` example will be ignored and the hard coded value - of `src="/failwhale.gif"` will take precedence: - - ```handlebars - imageTitle - ``` - - ### `bind-attr` and the `class` attribute - - `bind-attr` supports a special syntax for handling a number of cases unique - to the `class` DOM element attribute. The `class` attribute combines - multiple discrete values into a single attribute as a space-delimited - list of strings. Each string can be: - - * a string return value of an object's property. - * a boolean return value of an object's property - * a hard-coded value - - A string return value works identically to other uses of `bind-attr`. The - return value of the property will become the value of the attribute. For - example, the following view and template: - - ```javascript - AView = View.extend({ - someProperty: function() { - return "aValue"; - }.property() - }) - ``` - - ```handlebars - - ``` - - A boolean return value will insert a specified class name if the property - returns `true` and remove the class name if the property returns `false`. - - A class name is provided via the syntax - `somePropertyName:class-name-if-true`. - - ```javascript - AView = View.extend({ - someBool: true - }) - ``` - - ```handlebars - - ``` - - Result in the following rendered output: - - ```html - - ``` - - An additional section of the binding can be provided if you want to - replace the existing class instead of removing it when the boolean - value changes: - - ```handlebars - - ``` - - A hard-coded value can be used by prepending `:` to the desired - class name: `:class-name-to-always-apply`. - - ```handlebars - - ``` - - Results in the following rendered output: - - ```html - - ``` - - All three strategies - string return value, boolean return value, and - hard-coded value – can be combined in a single declaration: - - ```handlebars - - ``` - - @method bind-attr - @for Ember.Handlebars.helpers - @param {Hash} options - @return {String} HTML string - */ - function bindAttrHelper(options) { - var attrs = options.hash; - - - var view = options.data.view; - var ret = []; - - // we relied on the behavior of calling without - // context to mean this === window, but when running - // "use strict", it's possible for this to === undefined; - var ctx = this || window; - - // Generate a unique id for this element. This will be added as a - // data attribute to the element so it can be looked up when - // the bound property changes. - var dataId = uuid(); - - // Handle classes differently, as we can bind multiple classes - var classBindings = attrs['class']; - if (classBindings != null) { - var classResults = bindClasses(ctx, classBindings, view, dataId, options); - - ret.push('class="' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '"'); - delete attrs['class']; - } - - var attrKeys = keys(attrs); - - // For each attribute passed, create an observer and emit the - // current value of the property as an attribute. - forEach.call(attrKeys, function(attr) { - var path = attrs[attr], - normalized; - - - normalized = normalizePath(ctx, path, options.data); - - var value = (path === 'this') ? normalized.root : handlebarsGet(ctx, path, options), - type = typeOf(value); - - - var observer; - - observer = function observer() { - var result = handlebarsGet(ctx, path, options); - - - var elem = view.$("[data-bindattr-" + dataId + "='" + dataId + "']"); - - // If we aren't able to find the element, it means the element - // to which we were bound has been removed from the view. - // In that case, we can assume the template has been re-rendered - // and we need to clean up the observer. - if (!elem || elem.length === 0) { - removeObserver(normalized.root, normalized.path, observer); - return; - } - - View.applyAttributeBindings(elem, attr, result); - }; - - // Add an observer to the view for when the property changes. - // When the observer fires, find the element using the - // unique data id and update the attribute to the new value. - // Note: don't add observer when path is 'this' or path - // is whole keyword e.g. {{#each x in list}} ... {{bind-attr attr="x"}} - if (path !== 'this' && !(normalized.isKeyword && normalized.path === '' )) { - view.registerObserver(normalized.root, normalized.path, observer); - } - - // if this changes, also change the logic in ember-views/lib/views/view.js - if ((type === 'string' || (type === 'number' && !isNaN(value)))) { - ret.push(attr + '="' + Handlebars.Utils.escapeExpression(value) + '"'); - } else if (value && type === 'boolean') { - // The developer controls the attr name, so it should always be safe - ret.push(attr + '="' + attr + '"'); - } - }, this); - - // Add the unique identifier - // NOTE: We use all lower-case since Firefox has problems with mixed case in SVG - ret.push('data-bindattr-' + dataId + '="' + dataId + '"'); - return new SafeString(ret.join(' ')); - } - - /** - See `bind-attr` - - @method bindAttr - @for Ember.Handlebars.helpers - @deprecated - @param {Function} context - @param {Hash} options - @return {String} HTML string - */ - function bindAttrHelperDeprecated() { - return helpers['bind-attr'].apply(this, arguments); - } - - /** - Helper that, given a space-separated string of property paths and a context, - returns an array of class names. Calling this method also has the side - effect of setting up observers at those property paths, such that if they - change, the correct class name will be reapplied to the DOM element. - - For example, if you pass the string "fooBar", it will first look up the - "fooBar" value of the context. If that value is true, it will add the - "foo-bar" class to the current element (i.e., the dasherized form of - "fooBar"). If the value is a string, it will add that string as the class. - Otherwise, it will not add any new class name. - - @private - @method bindClasses - @for Ember.Handlebars - @param {Ember.Object} context The context from which to lookup properties - @param {String} classBindings A string, space-separated, of class bindings - to use - @param {View} view The view in which observers should look for the - element to update - @param {Srting} bindAttrId Optional bindAttr id used to lookup elements - @return {Array} An array of class names to add - */ - function bindClasses(context, classBindings, view, bindAttrId, options) { - var ret = [], newClass, value, elem; - - // Helper method to retrieve the property from the context and - // determine which class string to return, based on whether it is - // a Boolean or not. - var classStringForPath = function(root, parsedPath, options) { - var val, - path = parsedPath.path; - - if (path === 'this') { - val = root; - } else if (path === '') { - val = true; - } else { - val = handlebarsGet(root, path, options); - } - - return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName); - }; - - // For each property passed, loop through and setup - // an observer. - forEach.call(classBindings.split(' '), function(binding) { - - // Variable in which the old class value is saved. The observer function - // closes over this variable, so it knows which string to remove when - // the property changes. - var oldClass; - - var observer; - - var parsedPath = View._parsePropertyPath(binding), - path = parsedPath.path, - pathRoot = context, - normalized; - - if (path !== '' && path !== 'this') { - normalized = normalizePath(context, path, options.data); - - pathRoot = normalized.root; - path = normalized.path; - } - - // Set up an observer on the context. If the property changes, toggle the - // class name. - observer = function() { - // Get the current value of the property - newClass = classStringForPath(context, parsedPath, options); - elem = bindAttrId ? view.$("[data-bindattr-" + bindAttrId + "='" + bindAttrId + "']") : view.$(); - - // If we can't find the element anymore, a parent template has been - // re-rendered and we've been nuked. Remove the observer. - if (!elem || elem.length === 0) { - removeObserver(pathRoot, path, observer); - } else { - // If we had previously added a class to the element, remove it. - if (oldClass) { - elem.removeClass(oldClass); - } - - // If necessary, add a new class. Make sure we keep track of it so - // it can be removed in the future. - if (newClass) { - elem.addClass(newClass); - oldClass = newClass; - } else { - oldClass = null; - } - } - }; - - if (path !== '' && path !== 'this') { - view.registerObserver(pathRoot, path, observer); - } - - // We've already setup the observer; now we just need to figure out the - // correct behavior right now on the first pass through. - value = classStringForPath(context, parsedPath, options); - - if (value) { - ret.push(value); - - // Make sure we save the current value so that it can be removed if the - // observer fires. - oldClass = value; - } - }); - - return ret; - } - - __exports__.bind = bind; - __exports__._triageMustacheHelper = _triageMustacheHelper; - __exports__.resolveHelper = resolveHelper; - __exports__.bindHelper = bindHelper; - __exports__.boundIfHelper = boundIfHelper; - __exports__.unboundIfHelper = unboundIfHelper; - __exports__.withHelper = withHelper; - __exports__.ifHelper = ifHelper; - __exports__.unlessHelper = unlessHelper; - __exports__.bindAttrHelper = bindAttrHelper; - __exports__.bindAttrHelperDeprecated = bindAttrHelperDeprecated; - __exports__.bindClasses = bindClasses; - }); -define("ember-handlebars/helpers/collection", - ["ember-metal/core","ember-metal/utils","ember-handlebars-compiler","ember-runtime/system/string","ember-metal/property_get","ember-handlebars/ext","ember-handlebars/helpers/view","ember-metal/computed","ember-views/views/collection_view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-handlebars - */ - - var Ember = __dependency1__["default"]; - // Ember.assert, Ember.deprecate - var inspect = __dependency2__.inspect; - - // var emberAssert = Ember.assert; - // emberDeprecate = Ember.deprecate; - - var EmberHandlebars = __dependency3__["default"]; - var helpers = EmberHandlebars.helpers; - - var fmt = __dependency4__.fmt; - var get = __dependency5__.get; - var handlebarsGet = __dependency6__.handlebarsGet; - var ViewHelper = __dependency7__.ViewHelper; - var computed = __dependency8__.computed; - var CollectionView = __dependency9__["default"]; - - var alias = computed.alias; - /** - `{{collection}}` is a `Ember.Handlebars` helper for adding instances of - `Ember.CollectionView` to a template. See [Ember.CollectionView](/api/classes/Ember.CollectionView.html) - for additional information on how a `CollectionView` functions. - - `{{collection}}`'s primary use is as a block helper with a `contentBinding` - option pointing towards an `Ember.Array`-compatible object. An `Ember.View` - instance will be created for each item in its `content` property. Each view - will have its own `content` property set to the appropriate item in the - collection. - - The provided block will be applied as the template for each item's view. - - Given an empty `` the following template: - - ```handlebars - {{#collection contentBinding="App.items"}} - Hi {{view.content.name}} - {{/collection}} - ``` - - And the following application code - - ```javascript - App = Ember.Application.create() - App.items = [ - Ember.Object.create({name: 'Dave'}), - Ember.Object.create({name: 'Mary'}), - Ember.Object.create({name: 'Sara'}) - ] - ``` - - Will result in the HTML structure below - - ```html -
    -
    Hi Dave
    -
    Hi Mary
    -
    Hi Sara
    -
    - ``` - - ### Blockless use in a collection - - If you provide an `itemViewClass` option that has its own `template` you can - omit the block. - - The following template: - - ```handlebars - {{collection contentBinding="App.items" itemViewClass="App.AnItemView"}} - ``` - - And application code - - ```javascript - App = Ember.Application.create(); - App.items = [ - Ember.Object.create({name: 'Dave'}), - Ember.Object.create({name: 'Mary'}), - Ember.Object.create({name: 'Sara'}) - ]; - - App.AnItemView = Ember.View.extend({ - template: Ember.Handlebars.compile("Greetings {{view.content.name}}") - }); - ``` - - Will result in the HTML structure below - - ```html -
    -
    Greetings Dave
    -
    Greetings Mary
    -
    Greetings Sara
    -
    - ``` - - ### Specifying a CollectionView subclass - - By default the `{{collection}}` helper will create an instance of - `Ember.CollectionView`. You can supply a `Ember.CollectionView` subclass to - the helper by passing it as the first argument: - - ```handlebars - {{#collection App.MyCustomCollectionClass contentBinding="App.items"}} - Hi {{view.content.name}} - {{/collection}} - ``` - - ### Forwarded `item.*`-named Options - - As with the `{{view}}`, helper options passed to the `{{collection}}` will be - set on the resulting `Ember.CollectionView` as properties. Additionally, - options prefixed with `item` will be applied to the views rendered for each - item (note the camelcasing): - - ```handlebars - {{#collection contentBinding="App.items" - itemTagName="p" - itemClassNames="greeting"}} - Howdy {{view.content.name}} - {{/collection}} - ``` - - Will result in the following HTML structure: - - ```html -
    -

    Howdy Dave

    -

    Howdy Mary

    -

    Howdy Sara

    -
    - ``` - - @method collection - @for Ember.Handlebars.helpers - @param {String} path - @param {Hash} options - @return {String} HTML string - @deprecated Use `{{each}}` helper instead. - */ - function collectionHelper(path, options) { - - // If no path is provided, treat path param as options. - if (path && path.data && path.data.isRenderData) { - options = path; - path = undefined; - } else { - } - - var fn = options.fn; - var data = options.data; - var inverse = options.inverse; - var view = options.data.view; - - - var controller, container; - // If passed a path string, convert that into an object. - // Otherwise, just default to the standard class. - var collectionClass; - if (path) { - controller = data.keywords.controller; - container = controller && controller.container; - collectionClass = handlebarsGet(this, path, options) || container.lookupFactory('view:' + path); - } - else { - collectionClass = CollectionView; - } - - var hash = options.hash, itemHash = {}, match; - - // Extract item view class if provided else default to the standard class - var collectionPrototype = collectionClass.proto(), itemViewClass; - - if (hash.itemView) { - controller = data.keywords.controller; - container = controller.container; - itemViewClass = container.lookupFactory('view:' + hash.itemView); - } else if (hash.itemViewClass) { - itemViewClass = handlebarsGet(collectionPrototype, hash.itemViewClass, options); - } else { - itemViewClass = collectionPrototype.itemViewClass; - } - - - delete hash.itemViewClass; - delete hash.itemView; - - // Go through options passed to the {{collection}} helper and extract options - // that configure item views instead of the collection itself. - for (var prop in hash) { - if (hash.hasOwnProperty(prop)) { - match = prop.match(/^item(.)(.*)$/); - - if (match && prop !== 'itemController') { - // Convert itemShouldFoo -> shouldFoo - itemHash[match[1].toLowerCase() + match[2]] = hash[prop]; - // Delete from hash as this will end up getting passed to the - // {{view}} helper method. - delete hash[prop]; - } - } - } - - if (fn) { - itemHash.template = fn; - delete options.fn; - } - - var emptyViewClass; - if (inverse && inverse !== EmberHandlebars.VM.noop) { - emptyViewClass = get(collectionPrototype, 'emptyViewClass'); - emptyViewClass = emptyViewClass.extend({ - template: inverse, - tagName: itemHash.tagName - }); - } else if (hash.emptyViewClass) { - emptyViewClass = handlebarsGet(this, hash.emptyViewClass, options); - } - if (emptyViewClass) { hash.emptyView = emptyViewClass; } - - if (hash.keyword) { - itemHash._context = this; - } else { - itemHash._context = alias('content'); - } - - var viewOptions = ViewHelper.propertiesFromHTMLOptions({ data: data, hash: itemHash }, this); - hash.itemViewClass = itemViewClass.extend(viewOptions); - - options.helperName = options.helperName || 'collection'; - - return helpers.view.call(this, collectionClass, options); - } - - __exports__["default"] = collectionHelper; - }); -define("ember-handlebars/helpers/debug", - ["ember-metal/core","ember-metal/utils","ember-metal/logger","ember-metal/property_get","ember-handlebars/ext","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { - "use strict"; - /*jshint debug:true*/ - - /** - @module ember - @submodule ember-handlebars - */ - var Ember = __dependency1__["default"]; - // Ember.FEATURES, - var inspect = __dependency2__.inspect; - var Logger = __dependency3__["default"]; - - var get = __dependency4__.get; - var normalizePath = __dependency5__.normalizePath; - var handlebarsGet = __dependency5__.handlebarsGet; - - var a_slice = [].slice; - - /** - `log` allows you to output the value of variables in the current rendering - context. `log` also accepts primitive types such as strings or numbers. - - ```handlebars - {{log "myVariable:" myVariable }} - ``` - - @method log - @for Ember.Handlebars.helpers - @param {String} property - */ - function logHelper() { - var params = a_slice.call(arguments, 0, -1), - options = arguments[arguments.length - 1], - logger = Logger.log, - values = [], - allowPrimitives = true; - - for (var i = 0; i < params.length; i++) { - var type = options.types[i]; - - if (type === 'ID' || !allowPrimitives) { - var context = (options.contexts && options.contexts[i]) || this, - normalized = normalizePath(context, params[i], options.data); - - if (normalized.path === 'this') { - values.push(normalized.root); - } else { - values.push(handlebarsGet(normalized.root, normalized.path, options)); - } - } else { - values.push(params[i]); - } - } - - logger.apply(logger, values); - } - - /** - Execute the `debugger` statement in the current context. - - ```handlebars - {{debugger}} - ``` - - Before invoking the `debugger` statement, there - are a few helpful variables defined in the - body of this helper that you can inspect while - debugging that describe how and where this - helper was invoked: - - - templateContext: this is most likely a controller - from which this template looks up / displays properties - - typeOfTemplateContext: a string description of - what the templateContext is - - For example, if you're wondering why a value `{{foo}}` - isn't rendering as expected within a template, you - could place a `{{debugger}}` statement, and when - the `debugger;` breakpoint is hit, you can inspect - `templateContext`, determine if it's the object you - expect, and/or evaluate expressions in the console - to perform property lookups on the `templateContext`: - - ``` - > templateContext.get('foo') // -> "" - ``` - - @method debugger - @for Ember.Handlebars.helpers - @param {String} property - */ - function debuggerHelper(options) { - - // These are helpful values you can inspect while debugging. - var templateContext = this; - var typeOfTemplateContext = inspect(templateContext); - - debugger; - } - - __exports__.logHelper = logHelper; - __exports__.debuggerHelper = debuggerHelper; - }); -define("ember-handlebars/helpers/each", - ["ember-metal/core","ember-handlebars-compiler","ember-runtime/system/string","ember-metal/property_get","ember-metal/property_set","ember-views/views/collection_view","ember-metal/binding","ember-runtime/mixins/controller","ember-runtime/controllers/array_controller","ember-runtime/mixins/array","ember-runtime/copy","ember-metal/run_loop","ember-metal/events","ember-handlebars/ext","ember-metal/computed","ember-metal/observer","ember-handlebars/views/metamorph_view","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) { - "use strict"; - - /** - @module ember - @submodule ember-handlebars - */ - var Ember = __dependency1__["default"]; - // Ember.assert;, Ember.K - // var emberAssert = Ember.assert, - var K = Ember.K; - - var EmberHandlebars = __dependency2__["default"]; - var helpers = EmberHandlebars.helpers; - - var fmt = __dependency3__.fmt; - var get = __dependency4__.get; - var set = __dependency5__.set; - var CollectionView = __dependency6__["default"]; - var Binding = __dependency7__.Binding; - var ControllerMixin = __dependency8__["default"]; - var ArrayController = __dependency9__["default"]; - var EmberArray = __dependency10__["default"]; - var copy = __dependency11__["default"]; - var run = __dependency12__["default"]; - var on = __dependency13__.on; - var handlebarsGet = __dependency14__.handlebarsGet; - var computed = __dependency15__.computed; - - var addObserver = __dependency16__.addObserver; - var removeObserver = __dependency16__.removeObserver; - var addBeforeObserver = __dependency16__.addBeforeObserver; - var removeBeforeObserver = __dependency16__.removeBeforeObserver; - - var _Metamorph = __dependency17__._Metamorph; - var _MetamorphView = __dependency17__._MetamorphView; - - var EachView = CollectionView.extend(_Metamorph, { - - init: function() { - var itemController = get(this, 'itemController'); - var binding; - - if (itemController) { - var controller = get(this, 'controller.container').lookupFactory('controller:array').create({ - _isVirtual: true, - parentController: get(this, 'controller'), - itemController: itemController, - target: get(this, 'controller'), - _eachView: this - }); - - this.disableContentObservers(function() { - set(this, 'content', controller); - binding = new Binding('content', '_eachView.dataSource').oneWay(); - binding.connect(controller); - }); - - set(this, '_arrayController', controller); - } else { - this.disableContentObservers(function() { - binding = new Binding('content', 'dataSource').oneWay(); - binding.connect(this); - }); - } - - return this._super(); - }, - - _assertArrayLike: function(content) { - }, - - disableContentObservers: function(callback) { - removeBeforeObserver(this, 'content', null, '_contentWillChange'); - removeObserver(this, 'content', null, '_contentDidChange'); - - callback.call(this); - - addBeforeObserver(this, 'content', null, '_contentWillChange'); - addObserver(this, 'content', null, '_contentDidChange'); - }, - - itemViewClass: _MetamorphView, - emptyViewClass: _MetamorphView, - - createChildView: function(view, attrs) { - view = this._super(view, attrs); - - // At the moment, if a container view subclass wants - // to insert keywords, it is responsible for cloning - // the keywords hash. This will be fixed momentarily. - var keyword = get(this, 'keyword'); - var content = get(view, 'content'); - - if (keyword) { - var data = get(view, 'templateData'); - - data = copy(data); - data.keywords = view.cloneKeywords(); - set(view, 'templateData', data); - - // In this case, we do not bind, because the `content` of - // a #each item cannot change. - data.keywords[keyword] = content; - } - - // If {{#each}} is looping over an array of controllers, - // point each child view at their respective controller. - if (content && content.isController) { - set(view, 'controller', content); - } - - return view; - }, - - destroy: function() { - if (!this._super()) { return; } - - var arrayController = get(this, '_arrayController'); - - if (arrayController) { - arrayController.destroy(); - } - - return this; - } - }); - - // Defeatureify doesn't seem to like nested functions that need to be removed - function _addMetamorphCheck() { - EachView.reopen({ - _checkMetamorph: on('didInsertElement', function() { - }) - }); - } - - // until ember-debug is es6ed - var runInDebug = function(f){ f(); }; - - var GroupedEach = EmberHandlebars.GroupedEach = function(context, path, options) { - var self = this, - normalized = EmberHandlebars.normalizePath(context, path, options.data); - - this.context = context; - this.path = path; - this.options = options; - this.template = options.fn; - this.containingView = options.data.view; - this.normalizedRoot = normalized.root; - this.normalizedPath = normalized.path; - this.content = this.lookupContent(); - - this.addContentObservers(); - this.addArrayObservers(); - - this.containingView.on('willClearRender', function() { - self.destroy(); - }); - }; - - GroupedEach.prototype = { - contentWillChange: function() { - this.removeArrayObservers(); - }, - - contentDidChange: function() { - this.content = this.lookupContent(); - this.addArrayObservers(); - this.rerenderContainingView(); - }, - - contentArrayWillChange: K, - - contentArrayDidChange: function() { - this.rerenderContainingView(); - }, - - lookupContent: function() { - return handlebarsGet(this.normalizedRoot, this.normalizedPath, this.options); - }, - - addArrayObservers: function() { - if (!this.content) { return; } - - this.content.addArrayObserver(this, { - willChange: 'contentArrayWillChange', - didChange: 'contentArrayDidChange' - }); - }, - - removeArrayObservers: function() { - if (!this.content) { return; } - - this.content.removeArrayObserver(this, { - willChange: 'contentArrayWillChange', - didChange: 'contentArrayDidChange' - }); - }, - - addContentObservers: function() { - addBeforeObserver(this.normalizedRoot, this.normalizedPath, this, this.contentWillChange); - addObserver(this.normalizedRoot, this.normalizedPath, this, this.contentDidChange); - }, - - removeContentObservers: function() { - removeBeforeObserver(this.normalizedRoot, this.normalizedPath, this.contentWillChange); - removeObserver(this.normalizedRoot, this.normalizedPath, this.contentDidChange); - }, - - render: function() { - if (!this.content) { return; } - - var content = this.content, - contentLength = get(content, 'length'), - options = this.options, - data = options.data, - template = this.template; - - data.insideEach = true; - for (var i = 0; i < contentLength; i++) { - var context = content.objectAt(i); - options.data.keywords[options.hash.keyword] = context; - template(context, { data: data }); - } - }, - - rerenderContainingView: function() { - var self = this; - run.scheduleOnce('render', this, function() { - // It's possible it's been destroyed after we enqueued a re-render call. - if (!self.destroyed) { - self.containingView.rerender(); - } - }); - }, - - destroy: function() { - this.removeContentObservers(); - if (this.content) { - this.removeArrayObservers(); - } - this.destroyed = true; - } - }; - - /** - The `{{#each}}` helper loops over elements in a collection, rendering its - block once for each item. It is an extension of the base Handlebars `{{#each}}` - helper: - - ```javascript - Developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}]; - ``` - - ```handlebars - {{#each Developers}} - {{name}} - {{/each}} - ``` - - `{{each}}` supports an alternative syntax with element naming: - - ```handlebars - {{#each person in Developers}} - {{person.name}} - {{/each}} - ``` - - When looping over objects that do not have properties, `{{this}}` can be used - to render the object: - - ```javascript - DeveloperNames = ['Yehuda', 'Tom', 'Paul'] - ``` - - ```handlebars - {{#each DeveloperNames}} - {{this}} - {{/each}} - ``` - ### {{else}} condition - `{{#each}}` can have a matching `{{else}}`. The contents of this block will render - if the collection is empty. - - ``` - {{#each person in Developers}} - {{person.name}} - {{else}} -

    Sorry, nobody is available for this task.

    - {{/each}} - ``` - ### Specifying a View class for items - If you provide an `itemViewClass` option that references a view class - with its own `template` you can omit the block. - - The following template: - - ```handlebars - {{#view App.MyView }} - {{each view.items itemViewClass="App.AnItemView"}} - {{/view}} - ``` - - And application code - - ```javascript - App = Ember.Application.create({ - MyView: Ember.View.extend({ - items: [ - Ember.Object.create({name: 'Dave'}), - Ember.Object.create({name: 'Mary'}), - Ember.Object.create({name: 'Sara'}) - ] - }) - }); - - App.AnItemView = Ember.View.extend({ - template: Ember.Handlebars.compile("Greetings {{name}}") - }); - ``` - - Will result in the HTML structure below - - ```html -
    -
    Greetings Dave
    -
    Greetings Mary
    -
    Greetings Sara
    -
    - ``` - - If an `itemViewClass` is defined on the helper, and therefore the helper is not - being used as a block, an `emptyViewClass` can also be provided optionally. - The `emptyViewClass` will match the behavior of the `{{else}}` condition - described above. That is, the `emptyViewClass` will render if the collection - is empty. - - ### Representing each item with a Controller. - By default the controller lookup within an `{{#each}}` block will be - the controller of the template where the `{{#each}}` was used. If each - item needs to be presented by a custom controller you can provide a - `itemController` option which references a controller by lookup name. - Each item in the loop will be wrapped in an instance of this controller - and the item itself will be set to the `model` property of that controller. - - This is useful in cases where properties of model objects need transformation - or synthesis for display: - - ```javascript - App.DeveloperController = Ember.ObjectController.extend({ - isAvailableForHire: function() { - return !this.get('model.isEmployed') && this.get('model.isSeekingWork'); - }.property('isEmployed', 'isSeekingWork') - }) - ``` - - ```handlebars - {{#each person in developers itemController="developer"}} - {{person.name}} {{#if person.isAvailableForHire}}Hire me!{{/if}} - {{/each}} - ``` - - Each itemController will receive a reference to the current controller as - a `parentController` property. - - ### (Experimental) Grouped Each - - When used in conjunction with the experimental [group helper](https://github.com/emberjs/group-helper), - you can inform Handlebars to re-render an entire group of items instead of - re-rendering them one at a time (in the event that they are changed en masse - or an item is added/removed). - - ```handlebars - {{#group}} - {{#each people}} - {{firstName}} {{lastName}} - {{/each}} - {{/group}} - ``` - - This can be faster than the normal way that Handlebars re-renders items - in some cases. - - If for some reason you have a group with more than one `#each`, you can make - one of the collections be updated in normal (non-grouped) fashion by setting - the option `groupedRows=true` (counter-intuitive, I know). - - For example, - - ```handlebars - {{dealershipName}} - - {{#group}} - {{#each dealers}} - {{firstName}} {{lastName}} - {{/each}} - - {{#each car in cars groupedRows=true}} - {{car.make}} {{car.model}} {{car.color}} - {{/each}} - {{/group}} - ``` - Any change to `dealershipName` or the `dealers` collection will cause the - entire group to be re-rendered. However, changes to the `cars` collection - will be re-rendered individually (as normal). - - Note that `group` behavior is also disabled by specifying an `itemViewClass`. - - @method each - @for Ember.Handlebars.helpers - @param [name] {String} name for item (used with `in`) - @param [path] {String} path - @param [options] {Object} Handlebars key/value pairs of options - @param [options.itemViewClass] {String} a path to a view class used for each item - @param [options.itemController] {String} name of a controller to be created for each item - @param [options.groupedRows] {boolean} enable normal item-by-item rendering when inside a `#group` helper - */ - function eachHelper(path, options) { - var ctx, helperName = 'each'; - - if (arguments.length === 4) { - - var keywordName = arguments[0]; - - - options = arguments[3]; - path = arguments[2]; - - helperName += ' ' + keywordName + ' in ' + path; - - if (path === '') { path = "this"; } - - options.hash.keyword = keywordName; - - } else if (arguments.length === 1) { - options = path; - path = 'this'; - } else { - helperName += ' ' + path; - } - - options.hash.dataSourceBinding = path; - // Set up emptyView as a metamorph with no tag - //options.hash.emptyViewClass = Ember._MetamorphView; - - // can't rely on this default behavior when use strict - ctx = this || window; - - options.helperName = options.helperName || helperName; - - if (options.data.insideGroup && !options.hash.groupedRows && !options.hash.itemViewClass) { - new GroupedEach(ctx, path, options).render(); - } else { - // ES6TODO: figure out how to do this without global lookup. - return helpers.collection.call(ctx, 'Ember.Handlebars.EachView', options); - } - } - - __exports__.EachView = EachView; - __exports__.GroupedEach = GroupedEach; - __exports__.eachHelper = eachHelper; - }); -define("ember-handlebars/helpers/loc", - ["ember-runtime/system/string","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var loc = __dependency1__.loc; - - /** - @module ember - @submodule ember-handlebars - */ - - // ES6TODO: - // Pretty sure this can be expressed as - // var locHelper EmberStringUtils.loc ? - - /** - Calls [Ember.String.loc](/api/classes/Ember.String.html#method_loc) with the - provided string. - - This is a convenient way to localize text. For example: - - ```html - - ``` - - Take note that `"welcome"` is a string and not an object - reference. - - See [Ember.String.loc](/api/classes/Ember.String.html#method_loc) for how to - set up localized string references. - - @method loc - @for Ember.Handlebars.helpers - @param {String} str The string to format - @see {Ember.String#loc} - */ - __exports__["default"] = function locHelper(str) { - return loc(str); - } - }); -define("ember-handlebars/helpers/partial", - ["ember-metal/core","ember-metal/is_none","ember-handlebars/ext","ember-handlebars/helpers/binding","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert - // var emberAssert = Ember.assert; - - var isNone = __dependency2__.isNone; - var handlebarsGet = __dependency3__.handlebarsGet; - var bind = __dependency4__.bind; - - /** - @module ember - @submodule ember-handlebars - */ - - /** - The `partial` helper renders another template without - changing the template context: - - ```handlebars - {{foo}} - {{partial "nav"}} - ``` - - The above example template will render a template named - "_nav", which has the same context as the parent template - it's rendered into, so if the "_nav" template also referenced - `{{foo}}`, it would print the same thing as the `{{foo}}` - in the above example. - - If a "_nav" template isn't found, the `partial` helper will - fall back to a template named "nav". - - ## Bound template names - - The parameter supplied to `partial` can also be a path - to a property containing a template name, e.g.: - - ```handlebars - {{partial someTemplateName}} - ``` - - The above example will look up the value of `someTemplateName` - on the template context (e.g. a controller) and use that - value as the name of the template to render. If the resolved - value is falsy, nothing will be rendered. If `someTemplateName` - changes, the partial will be re-rendered using the new template - name. - - ## Setting the partial's context with `with` - - The `partial` helper can be used in conjunction with the `with` - helper to set a context that will be used by the partial: - - ```handlebars - {{#with currentUser}} - {{partial "user_info"}} - {{/with}} - ``` - - @method partial - @for Ember.Handlebars.helpers - @param {String} partialName the name of the template to render minus the leading underscore - */ - - __exports__["default"] = function partialHelper(name, options) { - - var context = (options.contexts && options.contexts.length) ? options.contexts[0] : this; - - options.helperName = options.helperName || 'partial'; - - if (options.types[0] === "ID") { - // Helper was passed a property path; we need to - // create a binding that will re-render whenever - // this property changes. - options.fn = function(context, fnOptions) { - var partialName = handlebarsGet(context, name, fnOptions); - renderPartial(context, partialName, fnOptions); - }; - - return bind.call(context, name, options, true, exists); - } else { - // Render the partial right into parent template. - renderPartial(context, name, options); - } - } - - function exists(value) { - return !isNone(value); - } - - function renderPartial(context, name, options) { - var nameParts = name.split("/"); - var lastPart = nameParts[nameParts.length - 1]; - - nameParts[nameParts.length - 1] = "_" + lastPart; - - var view = options.data.view; - var underscoredName = nameParts.join("/"); - var template = view.templateForName(underscoredName); - var deprecatedTemplate = !template && view.templateForName(name); - - - template = template || deprecatedTemplate; - - template(context, { data: options.data }); - } - }); -define("ember-handlebars/helpers/shared", - ["ember-handlebars/ext","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var handlebarsGet = __dependency1__.handlebarsGet; - - __exports__["default"] = function resolvePaths(options) { - var ret = [], - contexts = options.contexts, - roots = options.roots, - data = options.data; - - for (var i=0, l=contexts.length; i - {{#with loggedInUser}} - Last Login: {{lastLogin}} - User Info: {{template "user_info"}} - {{/with}} - - ``` - - ```html - - ``` - - ```handlebars - {{#if isUser}} - {{template "user_info"}} - {{else}} - {{template "unlogged_user_info"}} - {{/if}} - ``` - - This helper looks for templates in the global `Ember.TEMPLATES` hash. If you - add `"; - return testEl.firstChild.innerHTML === ''; - })(); - - // IE 8 (and likely earlier) likes to move whitespace preceeding - // a script tag to appear after it. This means that we can - // accidentally remove whitespace when updating a morph. - var movesWhitespace = typeof document !== 'undefined' && (function() { - var testEl = document.createElement('div'); - testEl.innerHTML = "Test: Value"; - return testEl.childNodes[0].nodeValue === 'Test:' && - testEl.childNodes[2].nodeValue === ' Value'; - })(); - - // Use this to find children by ID instead of using jQuery - var findChildById = function(element, id) { - if (element.getAttribute('id') === id) { return element; } - - var len = element.childNodes.length, idx, node, found; - for (idx=0; idx 0) { - var len = matches.length, idx; - for (idx=0; idxTest'); - canSet = el.options.length === 1; - } - - innerHTMLTags[tagName] = canSet; - - return canSet; - }; - - function setInnerHTML(element, html) { - var tagName = element.tagName; - - if (canSetInnerHTML(tagName)) { - setInnerHTMLWithoutFix(element, html); - } else { - // Firefox versions < 11 do not have support for element.outerHTML. - var outerHTML = element.outerHTML || new XMLSerializer().serializeToString(element); - - var startTag = outerHTML.match(new RegExp("<"+tagName+"([^>]*)>", 'i'))[0], - endTag = ''; - - var wrapper = document.createElement('div'); - setInnerHTMLWithoutFix(wrapper, startTag + html + endTag); - element = wrapper.firstChild; - while (element.tagName !== tagName) { - element = element.nextSibling; - } - } - - return element; - } - - __exports__.setInnerHTML = setInnerHTML;function isSimpleClick(event) { - var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey, - secondaryClick = event.which > 1; // IE9 may return undefined - - return !modifier && !secondaryClick; - } - - __exports__.isSimpleClick = isSimpleClick; - }); -define("ember-views/views/collection_view", - ["ember-metal/core","ember-metal/platform","ember-metal/binding","ember-metal/merge","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/string","ember-views/views/container_view","ember-views/views/core_view","ember-views/views/view","ember-metal/mixin","ember-runtime/mixins/array","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) { - "use strict"; - - /** - @module ember - @submodule ember-views - */ - - var Ember = __dependency1__["default"]; - // Ember.assert - var create = __dependency2__.create; - var isGlobalPath = __dependency3__.isGlobalPath; - var merge = __dependency4__["default"]; - var get = __dependency5__.get; - var set = __dependency6__.set; - var fmt = __dependency7__.fmt; - var ContainerView = __dependency8__["default"]; - var CoreView = __dependency9__["default"]; - var View = __dependency10__["default"]; - var observer = __dependency11__.observer; - var beforeObserver = __dependency11__.beforeObserver; - var EmberArray = __dependency12__["default"]; - - /** - `Ember.CollectionView` is an `Ember.View` descendent responsible for managing - a collection (an array or array-like object) by maintaining a child view object - and associated DOM representation for each item in the array and ensuring - that child views and their associated rendered HTML are updated when items in - the array are added, removed, or replaced. - - ## Setting content - - The managed collection of objects is referenced as the `Ember.CollectionView` - instance's `content` property. - - ```javascript - someItemsView = Ember.CollectionView.create({ - content: ['A', 'B','C'] - }) - ``` - - The view for each item in the collection will have its `content` property set - to the item. - - ## Specifying itemViewClass - - By default the view class for each item in the managed collection will be an - instance of `Ember.View`. You can supply a different class by setting the - `CollectionView`'s `itemViewClass` property. - - Given an empty `` and the following code: - - ```javascript - someItemsView = Ember.CollectionView.create({ - classNames: ['a-collection'], - content: ['A','B','C'], - itemViewClass: Ember.View.extend({ - template: Ember.Handlebars.compile("the letter: {{view.content}}") - }) - }); - - someItemsView.appendTo('body'); - ``` - - Will result in the following HTML structure - - ```html -
    -
    the letter: A
    -
    the letter: B
    -
    the letter: C
    -
    - ``` - - ## Automatic matching of parent/child tagNames - - Setting the `tagName` property of a `CollectionView` to any of - "ul", "ol", "table", "thead", "tbody", "tfoot", "tr", or "select" will result - in the item views receiving an appropriately matched `tagName` property. - - Given an empty `` and the following code: - - ```javascript - anUnorderedListView = Ember.CollectionView.create({ - tagName: 'ul', - content: ['A','B','C'], - itemViewClass: Ember.View.extend({ - template: Ember.Handlebars.compile("the letter: {{view.content}}") - }) - }); - - anUnorderedListView.appendTo('body'); - ``` - - Will result in the following HTML structure - - ```html -
      -
    • the letter: A
    • -
    • the letter: B
    • -
    • the letter: C
    • -
    - ``` - - Additional `tagName` pairs can be provided by adding to - `Ember.CollectionView.CONTAINER_MAP ` - - ```javascript - Ember.CollectionView.CONTAINER_MAP['article'] = 'section' - ``` - - ## Programmatic creation of child views - - For cases where additional customization beyond the use of a single - `itemViewClass` or `tagName` matching is required CollectionView's - `createChildView` method can be overidden: - - ```javascript - CustomCollectionView = Ember.CollectionView.extend({ - createChildView: function(viewClass, attrs) { - if (attrs.content.kind == 'album') { - viewClass = App.AlbumView; - } else { - viewClass = App.SongView; - } - return this._super(viewClass, attrs); - } - }); - ``` - - ## Empty View - - You can provide an `Ember.View` subclass to the `Ember.CollectionView` - instance as its `emptyView` property. If the `content` property of a - `CollectionView` is set to `null` or an empty array, an instance of this view - will be the `CollectionView`s only child. - - ```javascript - aListWithNothing = Ember.CollectionView.create({ - classNames: ['nothing'] - content: null, - emptyView: Ember.View.extend({ - template: Ember.Handlebars.compile("The collection is empty") - }) - }); - - aListWithNothing.appendTo('body'); - ``` - - Will result in the following HTML structure - - ```html -
    -
    - The collection is empty -
    -
    - ``` - - ## Adding and Removing items - - The `childViews` property of a `CollectionView` should not be directly - manipulated. Instead, add, remove, replace items from its `content` property. - This will trigger appropriate changes to its rendered HTML. - - - @class CollectionView - @namespace Ember - @extends Ember.ContainerView - @since Ember 0.9 - */ - var CollectionView = ContainerView.extend({ - - /** - A list of items to be displayed by the `Ember.CollectionView`. - - @property content - @type Ember.Array - @default null - */ - content: null, - - /** - This provides metadata about what kind of empty view class this - collection would like if it is being instantiated from another - system (like Handlebars) - - @private - @property emptyViewClass - */ - emptyViewClass: View, - - /** - An optional view to display if content is set to an empty array. - - @property emptyView - @type Ember.View - @default null - */ - emptyView: null, - - /** - @property itemViewClass - @type Ember.View - @default Ember.View - */ - itemViewClass: View, - - /** - Setup a CollectionView - - @method init - */ - init: function() { - var ret = this._super(); - this._contentDidChange(); - return ret; - }, - - /** - Invoked when the content property is about to change. Notifies observers that the - entire array content will change. - - @private - @method _contentWillChange - */ - _contentWillChange: beforeObserver('content', function() { - var content = this.get('content'); - - if (content) { content.removeArrayObserver(this); } - var len = content ? get(content, 'length') : 0; - this.arrayWillChange(content, 0, len); - }), - - /** - Check to make sure that the content has changed, and if so, - update the children directly. This is always scheduled - asynchronously, to allow the element to be created before - bindings have synchronized and vice versa. - - @private - @method _contentDidChange - */ - _contentDidChange: observer('content', function() { - var content = get(this, 'content'); - - if (content) { - this._assertArrayLike(content); - content.addArrayObserver(this); - } - - var len = content ? get(content, 'length') : 0; - this.arrayDidChange(content, 0, null, len); - }), - - /** - Ensure that the content implements Ember.Array - - @private - @method _assertArrayLike - */ - _assertArrayLike: function(content) { - }, - - /** - Removes the content and content observers. - - @method destroy - */ - destroy: function() { - if (!this._super()) { return; } - - var content = get(this, 'content'); - if (content) { content.removeArrayObserver(this); } - - if (this._createdEmptyView) { - this._createdEmptyView.destroy(); - } - - return this; - }, - - /** - Called when a mutation to the underlying content array will occur. - - This method will remove any views that are no longer in the underlying - content array. - - Invokes whenever the content array itself will change. - - @method arrayWillChange - @param {Array} content the managed collection of objects - @param {Number} start the index at which the changes will occurr - @param {Number} removed number of object to be removed from content - */ - arrayWillChange: function(content, start, removedCount) { - // If the contents were empty before and this template collection has an - // empty view remove it now. - var emptyView = get(this, 'emptyView'); - if (emptyView && emptyView instanceof View) { - emptyView.removeFromParent(); - } - - // Loop through child views that correspond with the removed items. - // Note that we loop from the end of the array to the beginning because - // we are mutating it as we go. - var childViews = this._childViews, childView, idx, len; - - len = this._childViews.length; - - var removingAll = removedCount === len; - - if (removingAll) { - this.currentState.empty(this); - this.invokeRecursively(function(view) { - view.removedFromDOM = true; - }, false); - } - - for (idx = start + removedCount - 1; idx >= start; idx--) { - childView = childViews[idx]; - childView.destroy(); - } - }, - - /** - Called when a mutation to the underlying content array occurs. - - This method will replay that mutation against the views that compose the - `Ember.CollectionView`, ensuring that the view reflects the model. - - This array observer is added in `contentDidChange`. - - @method arrayDidChange - @param {Array} content the managed collection of objects - @param {Number} start the index at which the changes occurred - @param {Number} removed number of object removed from content - @param {Number} added number of object added to content - */ - arrayDidChange: function(content, start, removed, added) { - var addedViews = [], view, item, idx, len, itemViewClass, - emptyView; - - len = content ? get(content, 'length') : 0; - - if (len) { - itemViewClass = get(this, 'itemViewClass'); - - if ('string' === typeof itemViewClass && isGlobalPath(itemViewClass)) { - itemViewClass = get(itemViewClass) || itemViewClass; - } - - - for (idx = start; idx < start+added; idx++) { - item = content.objectAt(idx); - - view = this.createChildView(itemViewClass, { - content: item, - contentIndex: idx - }); - - addedViews.push(view); - } - } else { - emptyView = get(this, 'emptyView'); - - if (!emptyView) { return; } - - if ('string' === typeof emptyView && isGlobalPath(emptyView)) { - emptyView = get(emptyView) || emptyView; - } - - emptyView = this.createChildView(emptyView); - addedViews.push(emptyView); - set(this, 'emptyView', emptyView); - - if (CoreView.detect(emptyView)) { - this._createdEmptyView = emptyView; - } - } - - this.replace(start, 0, addedViews); - }, - - /** - Instantiates a view to be added to the childViews array during view - initialization. You generally will not call this method directly unless - you are overriding `createChildViews()`. Note that this method will - automatically configure the correct settings on the new view instance to - act as a child of the parent. - - The tag name for the view will be set to the tagName of the viewClass - passed in. - - @method createChildView - @param {Class} viewClass - @param {Hash} [attrs] Attributes to add - @return {Ember.View} new instance - */ - createChildView: function(view, attrs) { - view = this._super(view, attrs); - - var itemTagName = get(view, 'tagName'); - - if (itemTagName === null || itemTagName === undefined) { - itemTagName = CollectionView.CONTAINER_MAP[get(this, 'tagName')]; - set(view, 'tagName', itemTagName); - } - - return view; - } - }); - - /** - A map of parent tags to their default child tags. You can add - additional parent tags if you want collection views that use - a particular parent tag to default to a child tag. - - @property CONTAINER_MAP - @type Hash - @static - @final - */ - CollectionView.CONTAINER_MAP = { - ul: 'li', - ol: 'li', - table: 'tr', - thead: 'tr', - tbody: 'tr', - tfoot: 'tr', - tr: 'td', - select: 'option' - }; - - __exports__["default"] = CollectionView; - }); -define("ember-views/views/component", - ["ember-metal/core","ember-views/mixins/component_template_deprecation","ember-runtime/mixins/target_action_support","ember-views/views/view","ember-metal/property_get","ember-metal/property_set","ember-metal/is_none","ember-metal/computed","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert, Ember.Handlebars - - var ComponentTemplateDeprecation = __dependency2__["default"]; - var TargetActionSupport = __dependency3__["default"]; - var View = __dependency4__["default"]; - - var get = __dependency5__.get; - var set = __dependency6__.set; - var isNone = __dependency7__.isNone; - - var computed = __dependency8__.computed; - - var a_slice = Array.prototype.slice; - - /** - @module ember - @submodule ember-views - */ - - /** - An `Ember.Component` is a view that is completely - isolated. Property access in its templates go - to the view object and actions are targeted at - the view object. There is no access to the - surrounding context or outer controller; all - contextual information must be passed in. - - The easiest way to create an `Ember.Component` is via - a template. If you name a template - `components/my-foo`, you will be able to use - `{{my-foo}}` in other templates, which will make - an instance of the isolated component. - - ```handlebars - {{app-profile person=currentUser}} - ``` - - ```handlebars - -

    {{person.title}}

    - -

    {{person.signature}}

    - ``` - - You can use `yield` inside a template to - include the **contents** of any block attached to - the component. The block will be executed in the - context of the surrounding context or outer controller: - - ```handlebars - {{#app-profile person=currentUser}} -

    Admin mode

    - {{! Executed in the controller's context. }} - {{/app-profile}} - ``` - - ```handlebars - -

    {{person.title}}

    - {{! Executed in the components context. }} - {{yield}} {{! block contents }} - ``` - - If you want to customize the component, in order to - handle events or actions, you implement a subclass - of `Ember.Component` named after the name of the - component. Note that `Component` needs to be appended to the name of - your subclass like `AppProfileComponent`. - - For example, you could implement the action - `hello` for the `app-profile` component: - - ```javascript - App.AppProfileComponent = Ember.Component.extend({ - actions: { - hello: function(name) { - console.log("Hello", name); - } - } - }); - ``` - - And then use it in the component's template: - - ```handlebars - - -

    {{person.title}}

    - {{yield}} - - - ``` - - Components must have a `-` in their name to avoid - conflicts with built-in controls that wrap HTML - elements. This is consistent with the same - requirement in web components. - - @class Component - @namespace Ember - @extends Ember.View - */ - var Component = View.extend(TargetActionSupport, ComponentTemplateDeprecation, { - instrumentName: 'component', - instrumentDisplay: computed(function() { - if (this._debugContainerKey) { - return '{{' + this._debugContainerKey.split(':')[1] + '}}'; - } - }), - - init: function() { - this._super(); - set(this, 'origContext', get(this, 'context')); - set(this, 'context', this); - set(this, 'controller', this); - }, - - defaultLayout: function(context, options){ - Ember.Handlebars.helpers['yield'].call(context, options); - }, - - /** - A components template property is set by passing a block - during its invocation. It is executed within the parent context. - - Example: - - ```handlebars - {{#my-component}} - // something that is run in the context - // of the parent context - {{/my-component}} - ``` - - Specifying a template directly to a component is deprecated without - also specifying the layout property. - - @deprecated - @property template - */ - template: computed(function(key, value) { - if (value !== undefined) { return value; } - - var templateName = get(this, 'templateName'), - template = this.templateForName(templateName, 'template'); - - - return template || get(this, 'defaultTemplate'); - }).property('templateName'), - - /** - Specifying a components `templateName` is deprecated without also - providing the `layout` or `layoutName` properties. - - @deprecated - @property templateName - */ - templateName: null, - - // during render, isolate keywords - cloneKeywords: function() { - return { - view: this, - controller: this - }; - }, - - _yield: function(context, options) { - var view = options.data.view, - parentView = this._parentView, - template = get(this, 'template'); - - if (template) { - - view.appendChild(View, { - isVirtual: true, - tagName: '', - _contextView: parentView, - template: template, - context: options.data.insideGroup ? get(this, 'origContext') : get(parentView, 'context'), - controller: get(parentView, 'controller'), - templateData: { keywords: parentView.cloneKeywords(), insideGroup: options.data.insideGroup } - }); - } - }, - - /** - If the component is currently inserted into the DOM of a parent view, this - property will point to the controller of the parent view. - - @property targetObject - @type Ember.Controller - @default null - */ - targetObject: computed(function(key) { - var parentView = get(this, '_parentView'); - return parentView ? get(parentView, 'controller') : null; - }).property('_parentView'), - - /** - Triggers a named action on the controller context where the component is used if - this controller has registered for notifications of the action. - - For example a component for playing or pausing music may translate click events - into action notifications of "play" or "stop" depending on some internal state - of the component: - - - ```javascript - App.PlayButtonComponent = Ember.Component.extend({ - click: function(){ - if (this.get('isPlaying')) { - this.sendAction('play'); - } else { - this.sendAction('stop'); - } - } - }); - ``` - - When used inside a template these component actions are configured to - trigger actions in the outer application context: - - ```handlebars - {{! application.hbs }} - {{play-button play="musicStarted" stop="musicStopped"}} - ``` - - When the component receives a browser `click` event it translate this - interaction into application-specific semantics ("play" or "stop") and - triggers the specified action name on the controller for the template - where the component is used: - - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - actions: { - musicStarted: function(){ - // called when the play button is clicked - // and the music started playing - }, - musicStopped: function(){ - // called when the play button is clicked - // and the music stopped playing - } - } - }); - ``` - - If no action name is passed to `sendAction` a default name of "action" - is assumed. - - ```javascript - App.NextButtonComponent = Ember.Component.extend({ - click: function(){ - this.sendAction(); - } - }); - ``` - - ```handlebars - {{! application.hbs }} - {{next-button action="playNextSongInAlbum"}} - ``` - - ```javascript - App.ApplicationController = Ember.Controller.extend({ - actions: { - playNextSongInAlbum: function(){ - ... - } - } - }); - ``` - - @method sendAction - @param [action] {String} the action to trigger - @param [context] {*} a context to send with the action - */ - sendAction: function(action) { - var actionName, - contexts = a_slice.call(arguments, 1); - - // Send the default action - if (action === undefined) { - actionName = get(this, 'action'); - } else { - actionName = get(this, action); - } - - // If no action name for that action could be found, just abort. - if (actionName === undefined) { return; } - - this.triggerAction({ - action: actionName, - actionContext: contexts - }); - } - }); - - __exports__["default"] = Component; - }); -define("ember-views/views/container_view", - ["ember-metal/core","ember-metal/merge","ember-runtime/mixins/mutable_array","ember-metal/property_get","ember-metal/property_set","ember-views/views/view","ember-views/views/view_collection","ember-views/views/states","ember-metal/error","ember-metal/enumerable_utils","ember-metal/computed","ember-metal/run_loop","ember-metal/properties","ember-views/system/render_buffer","ember-metal/mixin","ember-runtime/system/native_array","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - // Ember.assert, Ember.K - - var merge = __dependency2__["default"]; - var MutableArray = __dependency3__["default"]; - var get = __dependency4__.get; - var set = __dependency5__.set; - - var View = __dependency6__["default"]; - var ViewCollection = __dependency7__["default"]; - - var cloneStates = __dependency8__.cloneStates; - var EmberViewStates = __dependency8__.states; - - var EmberError = __dependency9__["default"]; - - var forEach = __dependency10__.forEach; - - var computed = __dependency11__.computed; - var run = __dependency12__["default"]; - var defineProperty = __dependency13__.defineProperty; - var renderBuffer = __dependency14__["default"]; - var observer = __dependency15__.observer; - var beforeObserver = __dependency15__.beforeObserver; - var emberA = __dependency16__.A; - - /** - @module ember - @submodule ember-views - */ - - var states = cloneStates(EmberViewStates); - - /** - A `ContainerView` is an `Ember.View` subclass that implements `Ember.MutableArray` - allowing programmatic management of its child views. - - ## Setting Initial Child Views - - The initial array of child views can be set in one of two ways. You can - provide a `childViews` property at creation time that contains instance of - `Ember.View`: - - ```javascript - aContainer = Ember.ContainerView.create({ - childViews: [Ember.View.create(), Ember.View.create()] - }); - ``` - - You can also provide a list of property names whose values are instances of - `Ember.View`: - - ```javascript - aContainer = Ember.ContainerView.create({ - childViews: ['aView', 'bView', 'cView'], - aView: Ember.View.create(), - bView: Ember.View.create(), - cView: Ember.View.create() - }); - ``` - - The two strategies can be combined: - - ```javascript - aContainer = Ember.ContainerView.create({ - childViews: ['aView', Ember.View.create()], - aView: Ember.View.create() - }); - ``` - - Each child view's rendering will be inserted into the container's rendered - HTML in the same order as its position in the `childViews` property. - - ## Adding and Removing Child Views - - The container view implements `Ember.MutableArray` allowing programmatic management of its child views. - - To remove a view, pass that view into a `removeObject` call on the container view. - - Given an empty `` the following code - - ```javascript - aContainer = Ember.ContainerView.create({ - classNames: ['the-container'], - childViews: ['aView', 'bView'], - aView: Ember.View.create({ - template: Ember.Handlebars.compile("A") - }), - bView: Ember.View.create({ - template: Ember.Handlebars.compile("B") - }) - }); - - aContainer.appendTo('body'); - ``` - - Results in the HTML - - ```html -
    -
    A
    -
    B
    -
    - ``` - - Removing a view - - ```javascript - aContainer.toArray(); // [aContainer.aView, aContainer.bView] - aContainer.removeObject(aContainer.get('bView')); - aContainer.toArray(); // [aContainer.aView] - ``` - - Will result in the following HTML - - ```html -
    -
    A
    -
    - ``` - - Similarly, adding a child view is accomplished by adding `Ember.View` instances to the - container view. - - Given an empty `` the following code - - ```javascript - aContainer = Ember.ContainerView.create({ - classNames: ['the-container'], - childViews: ['aView', 'bView'], - aView: Ember.View.create({ - template: Ember.Handlebars.compile("A") - }), - bView: Ember.View.create({ - template: Ember.Handlebars.compile("B") - }) - }); - - aContainer.appendTo('body'); - ``` - - Results in the HTML - - ```html -
    -
    A
    -
    B
    -
    - ``` - - Adding a view - - ```javascript - AnotherViewClass = Ember.View.extend({ - template: Ember.Handlebars.compile("Another view") - }); - - aContainer.toArray(); // [aContainer.aView, aContainer.bView] - aContainer.pushObject(AnotherViewClass.create()); - aContainer.toArray(); // [aContainer.aView, aContainer.bView, ] - ``` - - Will result in the following HTML - - ```html -
    -
    A
    -
    B
    -
    Another view
    -
    - ``` - - ## Templates and Layout - - A `template`, `templateName`, `defaultTemplate`, `layout`, `layoutName` or - `defaultLayout` property on a container view will not result in the template - or layout being rendered. The HTML contents of a `Ember.ContainerView`'s DOM - representation will only be the rendered HTML of its child views. - - @class ContainerView - @namespace Ember - @extends Ember.View - */ - var ContainerView = View.extend(MutableArray, { - _states: states, - - willWatchProperty: function(prop){ - }, - - init: function() { - this._super(); - - var childViews = get(this, 'childViews'); - - // redefine view's childViews property that was obliterated - defineProperty(this, 'childViews', View.childViewsProperty); - - var _childViews = this._childViews; - - forEach(childViews, function(viewName, idx) { - var view; - - if ('string' === typeof viewName) { - view = get(this, viewName); - view = this.createChildView(view); - set(this, viewName, view); - } else { - view = this.createChildView(viewName); - } - - _childViews[idx] = view; - }, this); - - var currentView = get(this, 'currentView'); - if (currentView) { - if (!_childViews.length) { _childViews = this._childViews = this._childViews.slice(); } - _childViews.push(this.createChildView(currentView)); - } - }, - - replace: function(idx, removedCount, addedViews) { - var addedCount = addedViews ? get(addedViews, 'length') : 0; - var self = this; - - this.arrayContentWillChange(idx, removedCount, addedCount); - this.childViewsWillChange(this._childViews, idx, removedCount); - - if (addedCount === 0) { - this._childViews.splice(idx, removedCount) ; - } else { - var args = [idx, removedCount].concat(addedViews); - if (addedViews.length && !this._childViews.length) { this._childViews = this._childViews.slice(); } - this._childViews.splice.apply(this._childViews, args); - } - - this.arrayContentDidChange(idx, removedCount, addedCount); - this.childViewsDidChange(this._childViews, idx, removedCount, addedCount); - - return this; - }, - - objectAt: function(idx) { - return this._childViews[idx]; - }, - - length: computed(function () { - return this._childViews.length; - })["volatile"](), - - /** - Instructs each child view to render to the passed render buffer. - - @private - @method render - @param {Ember.RenderBuffer} buffer the buffer to render to - */ - render: function(buffer) { - this.forEachChildView(function(view) { - view.renderToBuffer(buffer); - }); - }, - - instrumentName: 'container', - - /** - When a child view is removed, destroy its element so that - it is removed from the DOM. - - The array observer that triggers this action is set up in the - `renderToBuffer` method. - - @private - @method childViewsWillChange - @param {Ember.Array} views the child views array before mutation - @param {Number} start the start position of the mutation - @param {Number} removed the number of child views removed - **/ - childViewsWillChange: function(views, start, removed) { - this.propertyWillChange('childViews'); - - if (removed > 0) { - var changedViews = views.slice(start, start+removed); - // transition to preRender before clearing parentView - this.currentState.childViewsWillChange(this, views, start, removed); - this.initializeViews(changedViews, null, null); - } - }, - - removeChild: function(child) { - this.removeObject(child); - return this; - }, - - /** - When a child view is added, make sure the DOM gets updated appropriately. - - If the view has already rendered an element, we tell the child view to - create an element and insert it into the DOM. If the enclosing container - view has already written to a buffer, but not yet converted that buffer - into an element, we insert the string representation of the child into the - appropriate place in the buffer. - - @private - @method childViewsDidChange - @param {Ember.Array} views the array of child views after the mutation has occurred - @param {Number} start the start position of the mutation - @param {Number} removed the number of child views removed - @param {Number} added the number of child views added - */ - childViewsDidChange: function(views, start, removed, added) { - if (added > 0) { - var changedViews = views.slice(start, start+added); - this.initializeViews(changedViews, this, get(this, 'templateData')); - this.currentState.childViewsDidChange(this, views, start, added); - } - this.propertyDidChange('childViews'); - }, - - initializeViews: function(views, parentView, templateData) { - forEach(views, function(view) { - set(view, '_parentView', parentView); - - if (!view.container && parentView) { - set(view, 'container', parentView.container); - } - - if (!get(view, 'templateData')) { - set(view, 'templateData', templateData); - } - }); - }, - - currentView: null, - - _currentViewWillChange: beforeObserver('currentView', function() { - var currentView = get(this, 'currentView'); - if (currentView) { - currentView.destroy(); - } - }), - - _currentViewDidChange: observer('currentView', function() { - var currentView = get(this, 'currentView'); - if (currentView) { - this.pushObject(currentView); - } - }), - - _ensureChildrenAreInDOM: function () { - this.currentState.ensureChildrenAreInDOM(this); - } - }); - - merge(states._default, { - childViewsWillChange: Ember.K, - childViewsDidChange: Ember.K, - ensureChildrenAreInDOM: Ember.K - }); - - merge(states.inBuffer, { - childViewsDidChange: function(parentView, views, start, added) { - throw new EmberError('You cannot modify child views while in the inBuffer state'); - } - }); - - merge(states.hasElement, { - childViewsWillChange: function(view, views, start, removed) { - for (var i=start; i - ``` - - ## HTML `class` Attribute - - The HTML `class` attribute of a view's tag can be set by providing a - `classNames` property that is set to an array of strings: - - ```javascript - MyView = Ember.View.extend({ - classNames: ['my-class', 'my-other-class'] - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    - ``` - - `class` attribute values can also be set by providing a `classNameBindings` - property set to an array of properties names for the view. The return value - of these properties will be added as part of the value for the view's `class` - attribute. These properties can be computed properties: - - ```javascript - MyView = Ember.View.extend({ - classNameBindings: ['propertyA', 'propertyB'], - propertyA: 'from-a', - propertyB: function() { - if (someLogic) { return 'from-b'; } - }.property() - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    - ``` - - If the value of a class name binding returns a boolean the property name - itself will be used as the class name if the property is true. The class name - will not be added if the value is `false` or `undefined`. - - ```javascript - MyView = Ember.View.extend({ - classNameBindings: ['hovered'], - hovered: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    - ``` - - When using boolean class name bindings you can supply a string value other - than the property name for use as the `class` HTML attribute by appending the - preferred value after a ":" character when defining the binding: - - ```javascript - MyView = Ember.View.extend({ - classNameBindings: ['awesome:so-very-cool'], - awesome: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    - ``` - - Boolean value class name bindings whose property names are in a - camelCase-style format will be converted to a dasherized format: - - ```javascript - MyView = Ember.View.extend({ - classNameBindings: ['isUrgent'], - isUrgent: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    - ``` - - Class name bindings can also refer to object values that are found by - traversing a path relative to the view itself: - - ```javascript - MyView = Ember.View.extend({ - classNameBindings: ['messages.empty'] - messages: Ember.Object.create({ - empty: true - }) - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    - ``` - - If you want to add a class name for a property which evaluates to true and - and a different class name if it evaluates to false, you can pass a binding - like this: - - ```javascript - // Applies 'enabled' class when isEnabled is true and 'disabled' when isEnabled is false - Ember.View.extend({ - classNameBindings: ['isEnabled:enabled:disabled'] - isEnabled: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    - ``` - - When isEnabled is `false`, the resulting HTML reprensentation looks like - this: - - ```html -
    - ``` - - This syntax offers the convenience to add a class if a property is `false`: - - ```javascript - // Applies no class when isEnabled is true and class 'disabled' when isEnabled is false - Ember.View.extend({ - classNameBindings: ['isEnabled::disabled'] - isEnabled: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    - ``` - - When the `isEnabled` property on the view is set to `false`, it will result - in view instances with an HTML representation of: - - ```html -
    - ``` - - Updates to the the value of a class name binding will result in automatic - update of the HTML `class` attribute in the view's rendered HTML - representation. If the value becomes `false` or `undefined` the class name - will be removed. - - Both `classNames` and `classNameBindings` are concatenated properties. See - [Ember.Object](/api/classes/Ember.Object.html) documentation for more - information about concatenated properties. - - ## HTML Attributes - - The HTML attribute section of a view's tag can be set by providing an - `attributeBindings` property set to an array of property names on the view. - The return value of these properties will be used as the value of the view's - HTML associated attribute: - - ```javascript - AnchorView = Ember.View.extend({ - tagName: 'a', - attributeBindings: ['href'], - href: 'http://google.com' - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html - - ``` - - One property can be mapped on to another by placing a ":" between - the source property and the destination property: - - ```javascript - AnchorView = Ember.View.extend({ - tagName: 'a', - attributeBindings: ['url:href'], - url: 'http://google.com' - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html - - ``` - - If the return value of an `attributeBindings` monitored property is a boolean - the property will follow HTML's pattern of repeating the attribute's name as - its value: - - ```javascript - MyTextInput = Ember.View.extend({ - tagName: 'input', - attributeBindings: ['disabled'], - disabled: true - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html - - ``` - - `attributeBindings` can refer to computed properties: - - ```javascript - MyTextInput = Ember.View.extend({ - tagName: 'input', - attributeBindings: ['disabled'], - disabled: function() { - if (someLogic) { - return true; - } else { - return false; - } - }.property() - }); - ``` - - Updates to the the property of an attribute binding will result in automatic - update of the HTML attribute in the view's rendered HTML representation. - - `attributeBindings` is a concatenated property. See [Ember.Object](/api/classes/Ember.Object.html) - documentation for more information about concatenated properties. - - ## Templates - - The HTML contents of a view's rendered representation are determined by its - template. Templates can be any function that accepts an optional context - parameter and returns a string of HTML that will be inserted within the - view's tag. Most typically in Ember this function will be a compiled - `Ember.Handlebars` template. - - ```javascript - AView = Ember.View.extend({ - template: Ember.Handlebars.compile('I am the template') - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    I am the template
    - ``` - - Within an Ember application is more common to define a Handlebars templates as - part of a page: - - ```html - - ``` - - And associate it by name using a view's `templateName` property: - - ```javascript - AView = Ember.View.extend({ - templateName: 'some-template' - }); - ``` - - If you have nested resources, your Handlebars template will look like this: - - ```html - - ``` - - And `templateName` property: - - ```javascript - AView = Ember.View.extend({ - templateName: 'posts/new' - }); - ``` - - Using a value for `templateName` that does not have a Handlebars template - with a matching `data-template-name` attribute will throw an error. - - For views classes that may have a template later defined (e.g. as the block - portion of a `{{view}}` Handlebars helper call in another template or in - a subclass), you can provide a `defaultTemplate` property set to compiled - template function. If a template is not later provided for the view instance - the `defaultTemplate` value will be used: - - ```javascript - AView = Ember.View.extend({ - defaultTemplate: Ember.Handlebars.compile('I was the default'), - template: null, - templateName: null - }); - ``` - - Will result in instances with an HTML representation of: - - ```html -
    I was the default
    - ``` - - If a `template` or `templateName` is provided it will take precedence over - `defaultTemplate`: - - ```javascript - AView = Ember.View.extend({ - defaultTemplate: Ember.Handlebars.compile('I was the default') - }); - - aView = AView.create({ - template: Ember.Handlebars.compile('I was the template, not default') - }); - ``` - - Will result in the following HTML representation when rendered: - - ```html -
    I was the template, not default
    - ``` - - ## View Context - - The default context of the compiled template is the view's controller: - - ```javascript - AView = Ember.View.extend({ - template: Ember.Handlebars.compile('Hello {{excitedGreeting}}') - }); - - aController = Ember.Object.create({ - firstName: 'Barry', - excitedGreeting: function() { - return this.get("content.firstName") + "!!!" - }.property() - }); - - aView = AView.create({ - controller: aController - }); - ``` - - Will result in an HTML representation of: - - ```html -
    Hello Barry!!!
    - ``` - - A context can also be explicitly supplied through the view's `context` - property. If the view has neither `context` nor `controller` properties, the - `parentView`'s context will be used. - - ## Layouts - - Views can have a secondary template that wraps their main template. Like - primary templates, layouts can be any function that accepts an optional - context parameter and returns a string of HTML that will be inserted inside - view's tag. Views whose HTML element is self closing (e.g. ``) - cannot have a layout and this property will be ignored. - - Most typically in Ember a layout will be a compiled `Ember.Handlebars` - template. - - A view's layout can be set directly with the `layout` property or reference - an existing Handlebars template by name with the `layoutName` property. - - A template used as a layout must contain a single use of the Handlebars - `{{yield}}` helper. The HTML contents of a view's rendered `template` will be - inserted at this location: - - ```javascript - AViewWithLayout = Ember.View.extend({ - layout: Ember.Handlebars.compile("
    {{yield}}
    "), - template: Ember.Handlebars.compile("I got wrapped") - }); - ``` - - Will result in view instances with an HTML representation of: - - ```html -
    -
    - I got wrapped -
    -
    - ``` - - See [Ember.Handlebars.helpers.yield](/api/classes/Ember.Handlebars.helpers.html#method_yield) - for more information. - - ## Responding to Browser Events - - Views can respond to user-initiated events in one of three ways: method - implementation, through an event manager, and through `{{action}}` helper use - in their template or layout. - - ### Method Implementation - - Views can respond to user-initiated events by implementing a method that - matches the event name. A `jQuery.Event` object will be passed as the - argument to this method. - - ```javascript - AView = Ember.View.extend({ - click: function(event) { - // will be called when when an instance's - // rendered element is clicked - } - }); - ``` - - ### Event Managers - - Views can define an object as their `eventManager` property. This object can - then implement methods that match the desired event names. Matching events - that occur on the view's rendered HTML or the rendered HTML of any of its DOM - descendants will trigger this method. A `jQuery.Event` object will be passed - as the first argument to the method and an `Ember.View` object as the - second. The `Ember.View` will be the view whose rendered HTML was interacted - with. This may be the view with the `eventManager` property or one of its - descendent views. - - ```javascript - AView = Ember.View.extend({ - eventManager: Ember.Object.create({ - doubleClick: function(event, view) { - // will be called when when an instance's - // rendered element or any rendering - // of this views's descendent - // elements is clicked - } - }) - }); - ``` - - An event defined for an event manager takes precedence over events of the - same name handled through methods on the view. - - ```javascript - AView = Ember.View.extend({ - mouseEnter: function(event) { - // will never trigger. - }, - eventManager: Ember.Object.create({ - mouseEnter: function(event, view) { - // takes precedence over AView#mouseEnter - } - }) - }); - ``` - - Similarly a view's event manager will take precedence for events of any views - rendered as a descendent. A method name that matches an event name will not - be called if the view instance was rendered inside the HTML representation of - a view that has an `eventManager` property defined that handles events of the - name. Events not handled by the event manager will still trigger method calls - on the descendent. - - ```javascript - OuterView = Ember.View.extend({ - template: Ember.Handlebars.compile("outer {{#view InnerView}}inner{{/view}} outer"), - eventManager: Ember.Object.create({ - mouseEnter: function(event, view) { - // view might be instance of either - // OuterView or InnerView depending on - // where on the page the user interaction occured - } - }) - }); - - InnerView = Ember.View.extend({ - click: function(event) { - // will be called if rendered inside - // an OuterView because OuterView's - // eventManager doesn't handle click events - }, - mouseEnter: function(event) { - // will never be called if rendered inside - // an OuterView. - } - }); - ``` - - ### Handlebars `{{action}}` Helper - - See [Handlebars.helpers.action](/api/classes/Ember.Handlebars.helpers.html#method_action). - - ### Event Names - - All of the event handling approaches described above respond to the same set - of events. The names of the built-in events are listed below. (The hash of - built-in events exists in `Ember.EventDispatcher`.) Additional, custom events - can be registered by using `Ember.Application.customEvents`. - - Touch events: - - * `touchStart` - * `touchMove` - * `touchEnd` - * `touchCancel` - - Keyboard events - - * `keyDown` - * `keyUp` - * `keyPress` - - Mouse events - - * `mouseDown` - * `mouseUp` - * `contextMenu` - * `click` - * `doubleClick` - * `mouseMove` - * `focusIn` - * `focusOut` - * `mouseEnter` - * `mouseLeave` - - Form events: - - * `submit` - * `change` - * `focusIn` - * `focusOut` - * `input` - - HTML5 drag and drop events: - - * `dragStart` - * `drag` - * `dragEnter` - * `dragLeave` - * `dragOver` - * `dragEnd` - * `drop` - - ## Handlebars `{{view}}` Helper - - Other `Ember.View` instances can be included as part of a view's template by - using the `{{view}}` Handlebars helper. See [Ember.Handlebars.helpers.view](/api/classes/Ember.Handlebars.helpers.html#method_view) - for additional information. - - @class View - @namespace Ember - @extends Ember.CoreView - */ - var View = CoreView.extend({ - - concatenatedProperties: ['classNames', 'classNameBindings', 'attributeBindings'], - - /** - @property isView - @type Boolean - @default true - @static - */ - isView: true, - - // .......................................................... - // TEMPLATE SUPPORT - // - - /** - The name of the template to lookup if no template is provided. - - By default `Ember.View` will lookup a template with this name in - `Ember.TEMPLATES` (a shared global object). - - @property templateName - @type String - @default null - */ - templateName: null, - - /** - The name of the layout to lookup if no layout is provided. - - By default `Ember.View` will lookup a template with this name in - `Ember.TEMPLATES` (a shared global object). - - @property layoutName - @type String - @default null - */ - layoutName: null, - - /** - Used to identify this view during debugging - - @property instrumentDisplay - @type String - */ - instrumentDisplay: computed(function() { - if (this.helperName) { - return '{{' + this.helperName + '}}'; - } - }), - - /** - The template used to render the view. This should be a function that - accepts an optional context parameter and returns a string of HTML that - will be inserted into the DOM relative to its parent view. - - In general, you should set the `templateName` property instead of setting - the template yourself. - - @property template - @type Function - */ - template: computed('templateName', function(key, value) { - if (value !== undefined) { return value; } - - var templateName = get(this, 'templateName'), - template = this.templateForName(templateName, 'template'); - - - return template || get(this, 'defaultTemplate'); - }), - - /** - The controller managing this view. If this property is set, it will be - made available for use by the template. - - @property controller - @type Object - */ - controller: computed('_parentView', function(key) { - var parentView = get(this, '_parentView'); - return parentView ? get(parentView, 'controller') : null; - }), - - /** - A view may contain a layout. A layout is a regular template but - supersedes the `template` property during rendering. It is the - responsibility of the layout template to retrieve the `template` - property from the view (or alternatively, call `Handlebars.helpers.yield`, - `{{yield}}`) to render it in the correct location. - - This is useful for a view that has a shared wrapper, but which delegates - the rendering of the contents of the wrapper to the `template` property - on a subclass. - - @property layout - @type Function - */ - layout: computed(function(key) { - var layoutName = get(this, 'layoutName'), - layout = this.templateForName(layoutName, 'layout'); - - - return layout || get(this, 'defaultLayout'); - }).property('layoutName'), - - _yield: function(context, options) { - var template = get(this, 'template'); - if (template) { template(context, options); } - }, - - templateForName: function(name, type) { - if (!name) { return; } - - if (!this.container) { - throw new EmberError('Container was not found when looking up a views template. ' + - 'This is most likely due to manually instantiating an Ember.View. ' + - 'See: http://git.io/EKPpnA'); - } - - return this.container.lookup('template:' + name); - }, - - /** - The object from which templates should access properties. - - This object will be passed to the template function each time the render - method is called, but it is up to the individual function to decide what - to do with it. - - By default, this will be the view's controller. - - @property context - @type Object - */ - context: computed(function(key, value) { - if (arguments.length === 2) { - set(this, '_context', value); - return value; - } else { - return get(this, '_context'); - } - })["volatile"](), - - /** - Private copy of the view's template context. This can be set directly - by Handlebars without triggering the observer that causes the view - to be re-rendered. - - The context of a view is looked up as follows: - - 1. Supplied context (usually by Handlebars) - 2. Specified controller - 3. `parentView`'s context (for a child of a ContainerView) - - The code in Handlebars that overrides the `_context` property first - checks to see whether the view has a specified controller. This is - something of a hack and should be revisited. - - @property _context - @private - */ - _context: computed(function(key) { - var parentView, controller; - - if (controller = get(this, 'controller')) { - return controller; - } - - parentView = this._parentView; - if (parentView) { - return get(parentView, '_context'); - } - - return null; - }), - - /** - If a value that affects template rendering changes, the view should be - re-rendered to reflect the new value. - - @method _contextDidChange - @private - */ - _contextDidChange: observer('context', function() { - this.rerender(); - }), - - /** - If `false`, the view will appear hidden in DOM. - - @property isVisible - @type Boolean - @default null - */ - isVisible: true, - - /** - Array of child views. You should never edit this array directly. - Instead, use `appendChild` and `removeFromParent`. - - @property childViews - @type Array - @default [] - @private - */ - childViews: childViewsProperty, - - _childViews: EMPTY_ARRAY, - - // When it's a virtual view, we need to notify the parent that their - // childViews will change. - _childViewsWillChange: beforeObserver('childViews', function() { - if (this.isVirtual) { - var parentView = get(this, 'parentView'); - if (parentView) { propertyWillChange(parentView, 'childViews'); } - } - }), - - // When it's a virtual view, we need to notify the parent that their - // childViews did change. - _childViewsDidChange: observer('childViews', function() { - if (this.isVirtual) { - var parentView = get(this, 'parentView'); - if (parentView) { propertyDidChange(parentView, 'childViews'); } - } - }), - - /** - Return the nearest ancestor that is an instance of the provided - class. - - @method nearestInstanceOf - @param {Class} klass Subclass of Ember.View (or Ember.View itself) - @return Ember.View - @deprecated - */ - nearestInstanceOf: function(klass) { - var view = get(this, 'parentView'); - - while (view) { - if (view instanceof klass) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - Return the nearest ancestor that is an instance of the provided - class or mixin. - - @method nearestOfType - @param {Class,Mixin} klass Subclass of Ember.View (or Ember.View itself), - or an instance of Ember.Mixin. - @return Ember.View - */ - nearestOfType: function(klass) { - var view = get(this, 'parentView'), - isOfType = klass instanceof Mixin ? - function(view) { return klass.detect(view); } : - function(view) { return klass.detect(view.constructor); }; - - while (view) { - if (isOfType(view)) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - Return the nearest ancestor that has a given property. - - @method nearestWithProperty - @param {String} property A property name - @return Ember.View - */ - nearestWithProperty: function(property) { - var view = get(this, 'parentView'); - - while (view) { - if (property in view) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - Return the nearest ancestor whose parent is an instance of - `klass`. - - @method nearestChildOf - @param {Class} klass Subclass of Ember.View (or Ember.View itself) - @return Ember.View - */ - nearestChildOf: function(klass) { - var view = get(this, 'parentView'); - - while (view) { - if (get(view, 'parentView') instanceof klass) { return view; } - view = get(view, 'parentView'); - } - }, - - /** - When the parent view changes, recursively invalidate `controller` - - @method _parentViewDidChange - @private - */ - _parentViewDidChange: observer('_parentView', function() { - if (this.isDestroying) { return; } - - this.trigger('parentViewDidChange'); - - if (get(this, 'parentView.controller') && !get(this, 'controller')) { - this.notifyPropertyChange('controller'); - } - }), - - _controllerDidChange: observer('controller', function() { - if (this.isDestroying) { return; } - - this.rerender(); - - this.forEachChildView(function(view) { - view.propertyDidChange('controller'); - }); - }), - - cloneKeywords: function() { - var templateData = get(this, 'templateData'); - - var keywords = templateData ? copy(templateData.keywords) : {}; - set(keywords, 'view', this.isVirtual ? keywords.view : this); - set(keywords, '_view', this); - set(keywords, 'controller', get(this, 'controller')); - - return keywords; - }, - - /** - Called on your view when it should push strings of HTML into a - `Ember.RenderBuffer`. Most users will want to override the `template` - or `templateName` properties instead of this method. - - By default, `Ember.View` will look for a function in the `template` - property and invoke it with the value of `context`. The value of - `context` will be the view's controller unless you override it. - - @method render - @param {Ember.RenderBuffer} buffer The render buffer - */ - render: function(buffer) { - // If this view has a layout, it is the responsibility of the - // the layout to render the view's template. Otherwise, render the template - // directly. - var template = get(this, 'layout') || get(this, 'template'); - - if (template) { - var context = get(this, 'context'); - var keywords = this.cloneKeywords(); - var output; - - var data = { - view: this, - buffer: buffer, - isRenderData: true, - keywords: keywords, - insideGroup: get(this, 'templateData.insideGroup') - }; - - // Invoke the template with the provided template context, which - // is the view's controller by default. A hash of data is also passed that provides - // the template with access to the view and render buffer. - - // The template should write directly to the render buffer instead - // of returning a string. - output = template(context, { data: data }); - - // If the template returned a string instead of writing to the buffer, - // push the string onto the buffer. - if (output !== undefined) { buffer.push(output); } - } - }, - - /** - Renders the view again. This will work regardless of whether the - view is already in the DOM or not. If the view is in the DOM, the - rendering process will be deferred to give bindings a chance - to synchronize. - - If children were added during the rendering process using `appendChild`, - `rerender` will remove them, because they will be added again - if needed by the next `render`. - - In general, if the display of your view changes, you should modify - the DOM element directly instead of manually calling `rerender`, which can - be slow. - - @method rerender - */ - rerender: function() { - return this.currentState.rerender(this); - }, - - clearRenderedChildren: function() { - var lengthBefore = this.lengthBeforeRender, - lengthAfter = this.lengthAfterRender; - - // If there were child views created during the last call to render(), - // remove them under the assumption that they will be re-created when - // we re-render. - - // VIEW-TODO: Unit test this path. - var childViews = this._childViews; - for (var i=lengthAfter-1; i>=lengthBefore; i--) { - if (childViews[i]) { childViews[i].destroy(); } - } - }, - - /** - Iterates over the view's `classNameBindings` array, inserts the value - of the specified property into the `classNames` array, then creates an - observer to update the view's element if the bound property ever changes - in the future. - - @method _applyClassNameBindings - @private - */ - _applyClassNameBindings: function(classBindings) { - var classNames = this.classNames, - elem, newClass, dasherizedClass; - - // Loop through all of the configured bindings. These will be either - // property names ('isUrgent') or property paths relative to the view - // ('content.isUrgent') - forEach(classBindings, function(binding) { - - - // Variable in which the old class value is saved. The observer function - // closes over this variable, so it knows which string to remove when - // the property changes. - var oldClass; - // Extract just the property name from bindings like 'foo:bar' - var parsedPath = View._parsePropertyPath(binding); - - // Set up an observer on the context. If the property changes, toggle the - // class name. - var observer = function() { - // Get the current value of the property - newClass = this._classStringForProperty(binding); - elem = this.$(); - - // If we had previously added a class to the element, remove it. - if (oldClass) { - elem.removeClass(oldClass); - // Also remove from classNames so that if the view gets rerendered, - // the class doesn't get added back to the DOM. - classNames.removeObject(oldClass); - } - - // If necessary, add a new class. Make sure we keep track of it so - // it can be removed in the future. - if (newClass) { - elem.addClass(newClass); - oldClass = newClass; - } else { - oldClass = null; - } - }; - - // Get the class name for the property at its current value - dasherizedClass = this._classStringForProperty(binding); - - if (dasherizedClass) { - // Ensure that it gets into the classNames array - // so it is displayed when we render. - addObject(classNames, dasherizedClass); - - // Save a reference to the class name so we can remove it - // if the observer fires. Remember that this variable has - // been closed over by the observer. - oldClass = dasherizedClass; - } - - this.registerObserver(this, parsedPath.path, observer); - // Remove className so when the view is rerendered, - // the className is added based on binding reevaluation - this.one('willClearRender', function() { - if (oldClass) { - classNames.removeObject(oldClass); - oldClass = null; - } - }); - - }, this); - }, - - _unspecifiedAttributeBindings: null, - - /** - Iterates through the view's attribute bindings, sets up observers for each, - then applies the current value of the attributes to the passed render buffer. - - @method _applyAttributeBindings - @param {Ember.RenderBuffer} buffer - @private - */ - _applyAttributeBindings: function(buffer, attributeBindings) { - var attributeValue, - unspecifiedAttributeBindings = this._unspecifiedAttributeBindings = this._unspecifiedAttributeBindings || {}; - - forEach(attributeBindings, function(binding) { - var split = binding.split(':'), - property = split[0], - attributeName = split[1] || property; - - if (property in this) { - this._setupAttributeBindingObservation(property, attributeName); - - // Determine the current value and add it to the render buffer - // if necessary. - attributeValue = get(this, property); - View.applyAttributeBindings(buffer, attributeName, attributeValue); - } else { - unspecifiedAttributeBindings[property] = attributeName; - } - }, this); - - // Lazily setup setUnknownProperty after attributeBindings are initially applied - this.setUnknownProperty = this._setUnknownProperty; - }, - - _setupAttributeBindingObservation: function(property, attributeName) { - var attributeValue, elem; - - // Create an observer to add/remove/change the attribute if the - // JavaScript property changes. - var observer = function() { - elem = this.$(); - - attributeValue = get(this, property); - - View.applyAttributeBindings(elem, attributeName, attributeValue); - }; - - this.registerObserver(this, property, observer); - }, - - /** - We're using setUnknownProperty as a hook to setup attributeBinding observers for - properties that aren't defined on a view at initialization time. - - Note: setUnknownProperty will only be called once for each property. - - @method setUnknownProperty - @param key - @param value - @private - */ - setUnknownProperty: null, // Gets defined after initialization by _applyAttributeBindings - - _setUnknownProperty: function(key, value) { - var attributeName = this._unspecifiedAttributeBindings && this._unspecifiedAttributeBindings[key]; - if (attributeName) { - this._setupAttributeBindingObservation(key, attributeName); - } - - defineProperty(this, key); - return set(this, key, value); - }, - - /** - Given a property name, returns a dasherized version of that - property name if the property evaluates to a non-falsy value. - - For example, if the view has property `isUrgent` that evaluates to true, - passing `isUrgent` to this method will return `"is-urgent"`. - - @method _classStringForProperty - @param property - @private - */ - _classStringForProperty: function(property) { - var parsedPath = View._parsePropertyPath(property); - var path = parsedPath.path; - - var val = get(this, path); - if (val === undefined && isGlobalPath(path)) { - val = get(Ember.lookup, path); - } - - return View._classStringForValue(path, val, parsedPath.className, parsedPath.falsyClassName); - }, - - // .......................................................... - // ELEMENT SUPPORT - // - - /** - Returns the current DOM element for the view. - - @property element - @type DOMElement - */ - element: computed('_parentView', function(key, value) { - if (value !== undefined) { - return this.currentState.setElement(this, value); - } else { - return this.currentState.getElement(this); - } - }), - - /** - Returns a jQuery object for this view's element. If you pass in a selector - string, this method will return a jQuery object, using the current element - as its buffer. - - For example, calling `view.$('li')` will return a jQuery object containing - all of the `li` elements inside the DOM element of this view. - - @method $ - @param {String} [selector] a jQuery-compatible selector string - @return {jQuery} the jQuery object for the DOM node - */ - $: function(sel) { - return this.currentState.$(this, sel); - }, - - mutateChildViews: function(callback) { - var childViews = this._childViews, - idx = childViews.length, - view; - - while(--idx >= 0) { - view = childViews[idx]; - callback(this, view, idx); - } - - return this; - }, - - forEachChildView: function(callback) { - var childViews = this._childViews; - - if (!childViews) { return this; } - - var len = childViews.length, - view, idx; - - for (idx = 0; idx < len; idx++) { - view = childViews[idx]; - callback(view); - } - - return this; - }, - - /** - Appends the view's element to the specified parent element. - - If the view does not have an HTML representation yet, `createElement()` - will be called automatically. - - Note that this method just schedules the view to be appended; the DOM - element will not be appended to the given element until all bindings have - finished synchronizing. - - This is not typically a function that you will need to call directly when - building your application. You might consider using `Ember.ContainerView` - instead. If you do need to use `appendTo`, be sure that the target element - you are providing is associated with an `Ember.Application` and does not - have an ancestor element that is associated with an Ember view. - - @method appendTo - @param {String|DOMElement|jQuery} A selector, element, HTML string, or jQuery object - @return {Ember.View} receiver - */ - appendTo: function(target) { - // Schedule the DOM element to be created and appended to the given - // element after bindings have synchronized. - this._insertElementLater(function() { - this.$().appendTo(target); - }); - - return this; - }, - - /** - Replaces the content of the specified parent element with this view's - element. If the view does not have an HTML representation yet, - `createElement()` will be called automatically. - - Note that this method just schedules the view to be appended; the DOM - element will not be appended to the given element until all bindings have - finished synchronizing - - @method replaceIn - @param {String|DOMElement|jQuery} target A selector, element, HTML string, or jQuery object - @return {Ember.View} received - */ - replaceIn: function(target) { - - this._insertElementLater(function() { - jQuery(target).empty(); - this.$().appendTo(target); - }); - - return this; - }, - - /** - Schedules a DOM operation to occur during the next render phase. This - ensures that all bindings have finished synchronizing before the view is - rendered. - - To use, pass a function that performs a DOM operation. - - Before your function is called, this view and all child views will receive - the `willInsertElement` event. After your function is invoked, this view - and all of its child views will receive the `didInsertElement` event. - - ```javascript - view._insertElementLater(function() { - this.createElement(); - this.$().appendTo('body'); - }); - ``` - - @method _insertElementLater - @param {Function} fn the function that inserts the element into the DOM - @private - */ - _insertElementLater: function(fn) { - this._scheduledInsert = run.scheduleOnce('render', this, '_insertElement', fn); - }, - - _insertElement: function (fn) { - this._scheduledInsert = null; - this.currentState.insertElement(this, fn); - }, - - /** - Appends the view's element to the document body. If the view does - not have an HTML representation yet, `createElement()` will be called - automatically. - - If your application uses the `rootElement` property, you must append - the view within that element. Rendering views outside of the `rootElement` - is not supported. - - Note that this method just schedules the view to be appended; the DOM - element will not be appended to the document body until all bindings have - finished synchronizing. - - @method append - @return {Ember.View} receiver - */ - append: function() { - return this.appendTo(document.body); - }, - - /** - Removes the view's element from the element to which it is attached. - - @method remove - @return {Ember.View} receiver - */ - remove: function() { - // What we should really do here is wait until the end of the run loop - // to determine if the element has been re-appended to a different - // element. - // In the interim, we will just re-render if that happens. It is more - // important than elements get garbage collected. - if (!this.removedFromDOM) { this.destroyElement(); } - this.invokeRecursively(function(view) { - if (view.clearRenderedChildren) { view.clearRenderedChildren(); } - }); - }, - - elementId: null, - - /** - Attempts to discover the element in the parent element. The default - implementation looks for an element with an ID of `elementId` (or the - view's guid if `elementId` is null). You can override this method to - provide your own form of lookup. For example, if you want to discover your - element using a CSS class name instead of an ID. - - @method findElementInParentElement - @param {DOMElement} parentElement The parent's DOM element - @return {DOMElement} The discovered element - */ - findElementInParentElement: function(parentElem) { - var id = "#" + this.elementId; - return jQuery(id)[0] || jQuery(id, parentElem)[0]; - }, - - /** - Creates a DOM representation of the view and all of its - child views by recursively calling the `render()` method. - - After the element has been created, `didInsertElement` will - be called on this view and all of its child views. - - @method createElement - @return {Ember.View} receiver - */ - createElement: function() { - if (get(this, 'element')) { return this; } - - var buffer = this.renderToBuffer(); - set(this, 'element', buffer.element()); - - return this; - }, - - /** - Called when a view is going to insert an element into the DOM. - - @event willInsertElement - */ - willInsertElement: Ember.K, - - /** - Called when the element of the view has been inserted into the DOM - or after the view was re-rendered. Override this function to do any - set up that requires an element in the document body. - - @event didInsertElement - */ - didInsertElement: Ember.K, - - /** - Called when the view is about to rerender, but before anything has - been torn down. This is a good opportunity to tear down any manual - observers you have installed based on the DOM state - - @event willClearRender - */ - willClearRender: Ember.K, - - /** - Run this callback on the current view (unless includeSelf is false) and recursively on child views. - - @method invokeRecursively - @param fn {Function} - @param includeSelf {Boolean} Includes itself if true. - @private - */ - invokeRecursively: function(fn, includeSelf) { - var childViews = (includeSelf === false) ? this._childViews : [this]; - var currentViews, view, currentChildViews; - - while (childViews.length) { - currentViews = childViews.slice(); - childViews = []; - - for (var i=0, l=currentViews.length; i` tag for views. - - @property tagName - @type String - @default null - */ - - // We leave this null by default so we can tell the difference between - // the default case and a user-specified tag. - tagName: null, - - /** - The WAI-ARIA role of the control represented by this view. For example, a - button may have a role of type 'button', or a pane may have a role of - type 'alertdialog'. This property is used by assistive software to help - visually challenged users navigate rich web applications. - - The full list of valid WAI-ARIA roles is available at: - [http://www.w3.org/TR/wai-aria/roles#roles_categorization](http://www.w3.org/TR/wai-aria/roles#roles_categorization) - - @property ariaRole - @type String - @default null - */ - ariaRole: null, - - /** - Standard CSS class names to apply to the view's outer element. This - property automatically inherits any class names defined by the view's - superclasses as well. - - @property classNames - @type Array - @default ['ember-view'] - */ - classNames: ['ember-view'], - - /** - A list of properties of the view to apply as class names. If the property - is a string value, the value of that string will be applied as a class - name. - - ```javascript - // Applies the 'high' class to the view element - Ember.View.extend({ - classNameBindings: ['priority'] - priority: 'high' - }); - ``` - - If the value of the property is a Boolean, the name of that property is - added as a dasherized class name. - - ```javascript - // Applies the 'is-urgent' class to the view element - Ember.View.extend({ - classNameBindings: ['isUrgent'] - isUrgent: true - }); - ``` - - If you would prefer to use a custom value instead of the dasherized - property name, you can pass a binding like this: - - ```javascript - // Applies the 'urgent' class to the view element - Ember.View.extend({ - classNameBindings: ['isUrgent:urgent'] - isUrgent: true - }); - ``` - - This list of properties is inherited from the view's superclasses as well. - - @property classNameBindings - @type Array - @default [] - */ - classNameBindings: EMPTY_ARRAY, - - /** - A list of properties of the view to apply as attributes. If the property is - a string value, the value of that string will be applied as the attribute. - - ```javascript - // Applies the type attribute to the element - // with the value "button", like
    - Ember.View.extend({ - attributeBindings: ['type'], - type: 'button' - }); - ``` - - If the value of the property is a Boolean, the name of that property is - added as an attribute. - - ```javascript - // Renders something like
    - Ember.View.extend({ - attributeBindings: ['enabled'], - enabled: true - }); - ``` - - @property attributeBindings - */ - attributeBindings: EMPTY_ARRAY, - - // ....................................................... - // CORE DISPLAY METHODS - // - - /** - Setup a view, but do not finish waking it up. - - * configure `childViews` - * register the view with the global views hash, which is used for event - dispatch - - @method init - @private - */ - init: function() { - this.elementId = this.elementId || guidFor(this); - - this._super(); - - // setup child views. be sure to clone the child views array first - this._childViews = this._childViews.slice(); - - this.classNameBindings = emberA(this.classNameBindings.slice()); - - this.classNames = emberA(this.classNames.slice()); - }, - - appendChild: function(view, options) { - return this.currentState.appendChild(this, view, options); - }, - - /** - Removes the child view from the parent view. - - @method removeChild - @param {Ember.View} view - @return {Ember.View} receiver - */ - removeChild: function(view) { - // If we're destroying, the entire subtree will be - // freed, and the DOM will be handled separately, - // so no need to mess with childViews. - if (this.isDestroying) { return; } - - // update parent node - set(view, '_parentView', null); - - // remove view from childViews array. - var childViews = this._childViews; - - removeObject(childViews, view); - - this.propertyDidChange('childViews'); // HUH?! what happened to will change? - - return this; - }, - - /** - Removes all children from the `parentView`. - - @method removeAllChildren - @return {Ember.View} receiver - */ - removeAllChildren: function() { - return this.mutateChildViews(function(parentView, view) { - parentView.removeChild(view); - }); - }, - - destroyAllChildren: function() { - return this.mutateChildViews(function(parentView, view) { - view.destroy(); - }); - }, - - /** - Removes the view from its `parentView`, if one is found. Otherwise - does nothing. - - @method removeFromParent - @return {Ember.View} receiver - */ - removeFromParent: function() { - var parent = this._parentView; - - // Remove DOM element from parent - this.remove(); - - if (parent) { parent.removeChild(this); } - return this; - }, - - /** - You must call `destroy` on a view to destroy the view (and all of its - child views). This will remove the view from any parent node, then make - sure that the DOM element managed by the view can be released by the - memory manager. - - @method destroy - */ - destroy: function() { - var childViews = this._childViews, - // get parentView before calling super because it'll be destroyed - nonVirtualParentView = get(this, 'parentView'), - viewName = this.viewName, - childLen, i; - - if (!this._super()) { return; } - - childLen = childViews.length; - for (i=childLen-1; i>=0; i--) { - childViews[i].removedFromDOM = true; - } - - // remove from non-virtual parent view if viewName was specified - if (viewName && nonVirtualParentView) { - nonVirtualParentView.set(viewName, null); - } - - childLen = childViews.length; - for (i=childLen-1; i>=0; i--) { - childViews[i].destroy(); - } - - return this; - }, - - /** - Instantiates a view to be added to the childViews array during view - initialization. You generally will not call this method directly unless - you are overriding `createChildViews()`. Note that this method will - automatically configure the correct settings on the new view instance to - act as a child of the parent. - - @method createChildView - @param {Class|String} viewClass - @param {Hash} [attrs] Attributes to add - @return {Ember.View} new instance - */ - createChildView: function(view, attrs) { - if (!view) { - throw new TypeError("createChildViews first argument must exist"); - } - - if (view.isView && view._parentView === this && view.container === this.container) { - return view; - } - - attrs = attrs || {}; - attrs._parentView = this; - - if (CoreView.detect(view)) { - attrs.templateData = attrs.templateData || get(this, 'templateData'); - - attrs.container = this.container; - view = view.create(attrs); - - // don't set the property on a virtual view, as they are invisible to - // consumers of the view API - if (view.viewName) { - set(get(this, 'concreteView'), view.viewName, view); - } - } else if ('string' === typeof view) { - var fullName = 'view:' + view; - var ViewKlass = this.container.lookupFactory(fullName); - - - attrs.templateData = get(this, 'templateData'); - view = ViewKlass.create(attrs); - } else { - attrs.container = this.container; - - if (!get(view, 'templateData')) { - attrs.templateData = get(this, 'templateData'); - } - - setProperties(view, attrs); - - } - - return view; - }, - - becameVisible: Ember.K, - becameHidden: Ember.K, - - /** - When the view's `isVisible` property changes, toggle the visibility - element of the actual DOM element. - - @method _isVisibleDidChange - @private - */ - _isVisibleDidChange: observer('isVisible', function() { - if (this._isVisible === get(this, 'isVisible')) { return ; } - run.scheduleOnce('render', this, this._toggleVisibility); - }), - - _toggleVisibility: function() { - var $el = this.$(); - if (!$el) { return; } - - var isVisible = get(this, 'isVisible'); - - if (this._isVisible === isVisible) { return ; } - - $el.toggle(isVisible); - - this._isVisible = isVisible; - - if (this._isAncestorHidden()) { return; } - - if (isVisible) { - this._notifyBecameVisible(); - } else { - this._notifyBecameHidden(); - } - }, - - _notifyBecameVisible: function() { - this.trigger('becameVisible'); - - this.forEachChildView(function(view) { - var isVisible = get(view, 'isVisible'); - - if (isVisible || isVisible === null) { - view._notifyBecameVisible(); - } - }); - }, - - _notifyBecameHidden: function() { - this.trigger('becameHidden'); - this.forEachChildView(function(view) { - var isVisible = get(view, 'isVisible'); - - if (isVisible || isVisible === null) { - view._notifyBecameHidden(); - } - }); - }, - - _isAncestorHidden: function() { - var parent = get(this, 'parentView'); - - while (parent) { - if (get(parent, 'isVisible') === false) { return true; } - - parent = get(parent, 'parentView'); - } - - return false; - }, - - clearBuffer: function() { - this.invokeRecursively(nullViewsBuffer); - }, - transitionTo: function(state, children) { - this._transitionTo(state, children); - }, - _transitionTo: function(state, children) { - var priorState = this.currentState; - var currentState = this.currentState = this._states[state]; - - this._state = state; - - if (priorState && priorState.exit) { priorState.exit(this); } - if (currentState.enter) { currentState.enter(this); } - if (state === 'inDOM') { meta(this).cache.element = undefined; } - - if (children !== false) { - this.forEachChildView(function(view) { - view._transitionTo(state); - }); - } - }, - - // ....................................................... - // EVENT HANDLING - // - - /** - Handle events from `Ember.EventDispatcher` - - @method handleEvent - @param eventName {String} - @param evt {Event} - @private - */ - handleEvent: function(eventName, evt) { - return this.currentState.handleEvent(this, eventName, evt); - }, - - registerObserver: function(root, path, target, observer) { - if (!observer && 'function' === typeof target) { - observer = target; - target = null; - } - - if (!root || typeof root !== 'object') { - return; - } - - var view = this, - stateCheckedObserver = function() { - view.currentState.invokeObserver(this, observer); - }, - scheduledObserver = function() { - run.scheduleOnce('render', this, stateCheckedObserver); - }; - - addObserver(root, path, target, scheduledObserver); - - this.one('willClearRender', function() { - removeObserver(root, path, target, scheduledObserver); - }); - } - - }); - - /* - Describe how the specified actions should behave in the various - states that a view can exist in. Possible states: - - * preRender: when a view is first instantiated, and after its - element was destroyed, it is in the preRender state - * inBuffer: once a view has been rendered, but before it has - been inserted into the DOM, it is in the inBuffer state - * hasElement: the DOM representation of the view is created, - and is ready to be inserted - * inDOM: once a view has been inserted into the DOM it is in - the inDOM state. A view spends the vast majority of its - existence in this state. - * destroyed: once a view has been destroyed (using the destroy - method), it is in this state. No further actions can be invoked - on a destroyed view. - */ - - // in the destroyed state, everything is illegal - - // before rendering has begun, all legal manipulations are noops. - - // inside the buffer, legal manipulations are done on the buffer - - // once the view has been inserted into the DOM, legal manipulations - // are done on the DOM element. - - function notifyMutationListeners() { - run.once(View, 'notifyMutationListeners'); - } - - var DOMManager = { - prepend: function(view, html) { - view.$().prepend(html); - notifyMutationListeners(); - }, - - after: function(view, html) { - view.$().after(html); - notifyMutationListeners(); - }, - - html: function(view, html) { - view.$().html(html); - notifyMutationListeners(); - }, - - replace: function(view) { - var element = get(view, 'element'); - - set(view, 'element', null); - - view._insertElementLater(function() { - jQuery(element).replaceWith(get(view, 'element')); - notifyMutationListeners(); - }); - }, - - remove: function(view) { - view.$().remove(); - notifyMutationListeners(); - }, - - empty: function(view) { - view.$().empty(); - notifyMutationListeners(); - } - }; - - View.reopen({ - domManager: DOMManager - }); - - View.reopenClass({ - - /** - Parse a path and return an object which holds the parsed properties. - - For example a path like "content.isEnabled:enabled:disabled" will return the - following object: - - ```javascript - { - path: "content.isEnabled", - className: "enabled", - falsyClassName: "disabled", - classNames: ":enabled:disabled" - } - ``` - - @method _parsePropertyPath - @static - @private - */ - _parsePropertyPath: function(path) { - var split = path.split(':'), - propertyPath = split[0], - classNames = "", - className, - falsyClassName; - - // check if the property is defined as prop:class or prop:trueClass:falseClass - if (split.length > 1) { - className = split[1]; - if (split.length === 3) { falsyClassName = split[2]; } - - classNames = ':' + className; - if (falsyClassName) { classNames += ":" + falsyClassName; } - } - - return { - path: propertyPath, - classNames: classNames, - className: (className === '') ? undefined : className, - falsyClassName: falsyClassName - }; - }, - - /** - Get the class name for a given value, based on the path, optional - `className` and optional `falsyClassName`. - - - if a `className` or `falsyClassName` has been specified: - - if the value is truthy and `className` has been specified, - `className` is returned - - if the value is falsy and `falsyClassName` has been specified, - `falsyClassName` is returned - - otherwise `null` is returned - - if the value is `true`, the dasherized last part of the supplied path - is returned - - if the value is not `false`, `undefined` or `null`, the `value` - is returned - - if none of the above rules apply, `null` is returned - - @method _classStringForValue - @param path - @param val - @param className - @param falsyClassName - @static - @private - */ - _classStringForValue: function(path, val, className, falsyClassName) { - if(isArray(val)) { - val = get(val, 'length') !== 0; - } - - // When using the colon syntax, evaluate the truthiness or falsiness - // of the value to determine which className to return - if (className || falsyClassName) { - if (className && !!val) { - return className; - - } else if (falsyClassName && !val) { - return falsyClassName; - - } else { - return null; - } - - // If value is a Boolean and true, return the dasherized property - // name. - } else if (val === true) { - // Normalize property path to be suitable for use - // as a class name. For exaple, content.foo.barBaz - // becomes bar-baz. - var parts = path.split('.'); - return dasherize(parts[parts.length-1]); - - // If the value is not false, undefined, or null, return the current - // value of the property. - } else if (val !== false && val != null) { - return val; - - // Nothing to display. Return null so that the old class is removed - // but no new class is added. - } else { - return null; - } - } - }); - - var mutation = EmberObject.extend(Evented).create(); - - View.addMutationListener = function(callback) { - mutation.on('change', callback); - }; - - View.removeMutationListener = function(callback) { - mutation.off('change', callback); - }; - - View.notifyMutationListeners = function() { - mutation.trigger('change'); - }; - - /** - Global views hash - - @property views - @static - @type Hash - */ - View.views = {}; - - // If someone overrides the child views computed property when - // defining their class, we want to be able to process the user's - // supplied childViews and then restore the original computed property - // at view initialization time. This happens in Ember.ContainerView's init - // method. - View.childViewsProperty = childViewsProperty; - - View.applyAttributeBindings = function(elem, name, value) { - var type = typeOf(value); - - // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js - if (name !== 'value' && (type === 'string' || (type === 'number' && !isNaN(value)))) { - if (value !== elem.attr(name)) { - elem.attr(name, value); - } - } else if (name === 'value' || type === 'boolean') { - if (isNone(value) || value === false) { - // `null`, `undefined` or `false` should remove attribute - elem.removeAttr(name); - // In IE8 `prop` couldn't remove attribute when name is `required`. - if (name === 'required') { - elem.removeProp(name); - } else { - elem.prop(name, ''); - } - } else if (value !== elem.prop(name)) { - // value should always be properties - elem.prop(name, value); - } - } else if (!value) { - elem.removeAttr(name); - } - }; - - __exports__["default"] = View; - }); -define("ember-views/views/view_collection", - ["ember-metal/enumerable_utils","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var forEach = __dependency1__.forEach; - - function ViewCollection(initialViews) { - var views = this.views = initialViews || []; - this.length = views.length; - } - - ViewCollection.prototype = { - length: 0, - - trigger: function(eventName) { - var views = this.views, view; - for (var i = 0, l = views.length; i < l; i++) { - view = views[i]; - if (view.trigger) { view.trigger(eventName); } - } - }, - - triggerRecursively: function(eventName) { - var views = this.views; - for (var i = 0, l = views.length; i < l; i++) { - views[i].triggerRecursively(eventName); - } - }, - - invokeRecursively: function(fn) { - var views = this.views, view; - - for (var i = 0, l = views.length; i < l; i++) { - view = views[i]; - fn(view); - } - }, - - transitionTo: function(state, children) { - var views = this.views; - for (var i = 0, l = views.length; i < l; i++) { - views[i]._transitionTo(state, children); - } - }, - - push: function() { - this.length += arguments.length; - var views = this.views; - return views.push.apply(views, arguments); - }, - - objectAt: function(idx) { - return this.views[idx]; - }, - - forEach: function(callback) { - var views = this.views; - return forEach(views, callback); - }, - - clear: function() { - this.length = 0; - this.views.length = 0; - } - }; - - __exports__["default"] = ViewCollection; - }); -define("ember", - ["ember-metal","ember-runtime","ember-handlebars","ember-views","ember-routing","ember-routing-handlebars","ember-application","ember-extension-support"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) { - "use strict"; - // require the main entry points for each of these packages - // this is so that the global exports occur properly - - // do this to ensure that Ember.Test is defined properly on the global - // if it is present. - if (Ember.__loader.registry['ember-testing']) { - requireModule('ember-testing'); - } - - /** - Ember - - @module ember - */ - - function throwWithMessage(msg) { - return function() { - throw new Ember.Error(msg); - }; - } - - function generateRemovedClass(className) { - var msg = " has been moved into a plugin: https://github.com/emberjs/ember-states"; - - return { - extend: throwWithMessage(className + msg), - create: throwWithMessage(className + msg) - }; - } - - Ember.StateManager = generateRemovedClass("Ember.StateManager"); - - /** - This was exported to ember-states plugin for v 1.0.0 release. See: https://github.com/emberjs/ember-states - - @class StateManager - @namespace Ember - */ - - Ember.State = generateRemovedClass("Ember.State"); - - /** - This was exported to ember-states plugin for v 1.0.0 release. See: https://github.com/emberjs/ember-states - - @class State - @namespace Ember - */ - }); -define("metamorph", - [], - function() { - "use strict"; - // ========================================================================== - // Project: metamorph - // Copyright: ©2014 Tilde, Inc. All rights reserved. - // ========================================================================== - - var K = function() {}, - guid = 0, - disableRange = (function(){ - if ('undefined' !== typeof MetamorphENV) { - return MetamorphENV.DISABLE_RANGE_API; - } else if ('undefined' !== ENV) { - return ENV.DISABLE_RANGE_API; - } else { - return false; - } - })(), - - // Feature-detect the W3C range API, the extended check is for IE9 which only partially supports ranges - supportsRange = (!disableRange) && typeof document !== 'undefined' && ('createRange' in document) && (typeof Range !== 'undefined') && Range.prototype.createContextualFragment, - - // Internet Explorer prior to 9 does not allow setting innerHTML if the first element - // is a "zero-scope" element. This problem can be worked around by making - // the first node an invisible text node. We, like Modernizr, use ­ - needsShy = typeof document !== 'undefined' && (function() { - var testEl = document.createElement('div'); - testEl.innerHTML = "
    "; - testEl.firstChild.innerHTML = ""; - return testEl.firstChild.innerHTML === ''; - })(), - - - // IE 8 (and likely earlier) likes to move whitespace preceeding - // a script tag to appear after it. This means that we can - // accidentally remove whitespace when updating a morph. - movesWhitespace = document && (function() { - var testEl = document.createElement('div'); - testEl.innerHTML = "Test: Value"; - return testEl.childNodes[0].nodeValue === 'Test:' && - testEl.childNodes[2].nodeValue === ' Value'; - })(); - - // Constructor that supports either Metamorph('foo') or new - // Metamorph('foo'); - // - // Takes a string of HTML as the argument. - - var Metamorph = function(html) { - var self; - - if (this instanceof Metamorph) { - self = this; - } else { - self = new K(); - } - - self.innerHTML = html; - var myGuid = 'metamorph-'+(guid++); - self.start = myGuid + '-start'; - self.end = myGuid + '-end'; - - return self; - }; - - K.prototype = Metamorph.prototype; - - var rangeFor, htmlFunc, removeFunc, outerHTMLFunc, appendToFunc, afterFunc, prependFunc, startTagFunc, endTagFunc; - - outerHTMLFunc = function() { - return this.startTag() + this.innerHTML + this.endTag(); - }; - - startTagFunc = function() { - /* - * We replace chevron by its hex code in order to prevent escaping problems. - * Check this thread for more explaination: - * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript - */ - return "hi"; - * div.firstChild.firstChild.tagName //=> "" - * - * If our script markers are inside such a node, we need to find that - * node and use *it* as the marker. - */ - var realNode = function(start) { - while (start.parentNode.tagName === "") { - start = start.parentNode; - } - - return start; - }; - - /* - * When automatically adding a tbody, Internet Explorer inserts the - * tbody immediately before the first . Other browsers create it - * before the first node, no matter what. - * - * This means the the following code: - * - * div = document.createElement("div"); - * div.innerHTML = "
    hi
    - * - * Generates the following DOM in IE: - * - * + div - * + table - * - script id='first' - * + tbody - * + tr - * + td - * - "hi" - * - script id='last' - * - * Which means that the two script tags, even though they were - * inserted at the same point in the hierarchy in the original - * HTML, now have different parents. - * - * This code reparents the first script tag by making it the tbody's - * first child. - * - */ - var fixParentage = function(start, end) { - if (start.parentNode !== end.parentNode) { - end.parentNode.insertBefore(start, end.parentNode.firstChild); - } - }; - - htmlFunc = function(html, outerToo) { - // get the real starting node. see realNode for details. - var start = realNode(document.getElementById(this.start)); - var end = document.getElementById(this.end); - var parentNode = end.parentNode; - var node, nextSibling, last; - - // make sure that the start and end nodes share the same - // parent. If not, fix it. - fixParentage(start, end); - - // remove all of the nodes after the starting placeholder and - // before the ending placeholder. - node = start.nextSibling; - while (node) { - nextSibling = node.nextSibling; - last = node === end; - - // if this is the last node, and we want to remove it as well, - // set the `end` node to the next sibling. This is because - // for the rest of the function, we insert the new nodes - // before the end (note that insertBefore(node, null) is - // the same as appendChild(node)). - // - // if we do not want to remove it, just break. - if (last) { - if (outerToo) { end = node.nextSibling; } else { break; } - } - - node.parentNode.removeChild(node); - - // if this is the last node and we didn't break before - // (because we wanted to remove the outer nodes), break - // now. - if (last) { break; } - - node = nextSibling; - } - - // get the first node for the HTML string, even in cases like - // tables and lists where a simple innerHTML on a div would - // swallow some of the content. - node = firstNodeFor(start.parentNode, html); - - if (outerToo) { - start.parentNode.removeChild(start); - } - - // copy the nodes for the HTML between the starting and ending - // placeholder. - while (node) { - nextSibling = node.nextSibling; - parentNode.insertBefore(node, end); - node = nextSibling; - } - }; - - // remove the nodes in the DOM representing this metamorph. - // - // this includes the starting and ending placeholders. - removeFunc = function() { - var start = realNode(document.getElementById(this.start)); - var end = document.getElementById(this.end); - - this.html(''); - start.parentNode.removeChild(start); - end.parentNode.removeChild(end); - }; - - appendToFunc = function(parentNode) { - var node = firstNodeFor(parentNode, this.outerHTML()); - var nextSibling; - - while (node) { - nextSibling = node.nextSibling; - parentNode.appendChild(node); - node = nextSibling; - } - }; - - afterFunc = function(html) { - // get the real starting node. see realNode for details. - var end = document.getElementById(this.end); - var insertBefore = end.nextSibling; - var parentNode = end.parentNode; - var nextSibling; - var node; - - // get the first node for the HTML string, even in cases like - // tables and lists where a simple innerHTML on a div would - // swallow some of the content. - node = firstNodeFor(parentNode, html); - - // copy the nodes for the HTML between the starting and ending - // placeholder. - while (node) { - nextSibling = node.nextSibling; - parentNode.insertBefore(node, insertBefore); - node = nextSibling; - } - }; - - prependFunc = function(html) { - var start = document.getElementById(this.start); - var parentNode = start.parentNode; - var nextSibling; - var node; - - node = firstNodeFor(parentNode, html); - var insertBefore = start.nextSibling; - - while (node) { - nextSibling = node.nextSibling; - parentNode.insertBefore(node, insertBefore); - node = nextSibling; - } - }; - } - - Metamorph.prototype.html = function(html) { - this.checkRemoved(); - if (html === undefined) { return this.innerHTML; } - - htmlFunc.call(this, html); - - this.innerHTML = html; - }; - - Metamorph.prototype.replaceWith = function(html) { - this.checkRemoved(); - htmlFunc.call(this, html, true); - }; - - Metamorph.prototype.remove = removeFunc; - Metamorph.prototype.outerHTML = outerHTMLFunc; - Metamorph.prototype.appendTo = appendToFunc; - Metamorph.prototype.after = afterFunc; - Metamorph.prototype.prepend = prependFunc; - Metamorph.prototype.startTag = startTagFunc; - Metamorph.prototype.endTag = endTagFunc; - - Metamorph.prototype.isRemoved = function() { - var before = document.getElementById(this.start); - var after = document.getElementById(this.end); - - return !before || !after; - }; - - Metamorph.prototype.checkRemoved = function() { - if (this.isRemoved()) { - throw new Error("Cannot perform operations on a Metamorph that is not in the DOM."); - } - }; - - return Metamorph; - }); - -define("route-recognizer", - ["route-recognizer/dsl","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var map = __dependency1__["default"]; - - var specials = [ - '/', '.', '*', '+', '?', '|', - '(', ')', '[', ']', '{', '}', '\\' - ]; - - var escapeRegex = new RegExp('(\\' + specials.join('|\\') + ')', 'g'); - - function isArray(test) { - return Object.prototype.toString.call(test) === "[object Array]"; - } - - // A Segment represents a segment in the original route description. - // Each Segment type provides an `eachChar` and `regex` method. - // - // The `eachChar` method invokes the callback with one or more character - // specifications. A character specification consumes one or more input - // characters. - // - // The `regex` method returns a regex fragment for the segment. If the - // segment is a dynamic of star segment, the regex fragment also includes - // a capture. - // - // A character specification contains: - // - // * `validChars`: a String with a list of all valid characters, or - // * `invalidChars`: a String with a list of all invalid characters - // * `repeat`: true if the character specification can repeat - - function StaticSegment(string) { this.string = string; } - StaticSegment.prototype = { - eachChar: function(callback) { - var string = this.string, ch; - - for (var i=0, l=string.length; i " + n.nextStates.map(function(s) { return s.debug() }).join(" or ") + " )"; - }).join(", ") - } - END IF **/ - - // This is a somewhat naive strategy, but should work in a lot of cases - // A better strategy would properly resolve /posts/:id/new and /posts/edit/:id. - // - // This strategy generally prefers more static and less dynamic matching. - // Specifically, it - // - // * prefers fewer stars to more, then - // * prefers using stars for less of the match to more, then - // * prefers fewer dynamic segments to more, then - // * prefers more static segments to more - function sortSolutions(states) { - return states.sort(function(a, b) { - if (a.types.stars !== b.types.stars) { return a.types.stars - b.types.stars; } - - if (a.types.stars) { - if (a.types.statics !== b.types.statics) { return b.types.statics - a.types.statics; } - if (a.types.dynamics !== b.types.dynamics) { return b.types.dynamics - a.types.dynamics; } - } - - if (a.types.dynamics !== b.types.dynamics) { return a.types.dynamics - b.types.dynamics; } - if (a.types.statics !== b.types.statics) { return b.types.statics - a.types.statics; } - - return 0; - }); - } - - function recognizeChar(states, ch) { - var nextStates = []; - - for (var i=0, l=states.length; i 2 && key.slice(keyLength -2) === '[]') { - isArray = true; - key = key.slice(0, keyLength - 2); - if(!queryParams[key]) { - queryParams[key] = []; - } - } - value = pair[1] ? decodeURIComponent(pair[1]) : ''; - } - if (isArray) { - queryParams[key].push(value); - } else { - queryParams[key] = value; - } - } - return queryParams; - }, - - recognize: function(path) { - var states = [ this.rootState ], - pathLen, i, l, queryStart, queryParams = {}, - isSlashDropped = false; - - queryStart = path.indexOf('?'); - if (queryStart !== -1) { - var queryString = path.substr(queryStart + 1, path.length); - path = path.substr(0, queryStart); - queryParams = this.parseQueryString(queryString); - } - - path = decodeURI(path); - - // DEBUG GROUP path - - if (path.charAt(0) !== "/") { path = "/" + path; } - - pathLen = path.length; - if (pathLen > 1 && path.charAt(pathLen - 1) === "/") { - path = path.substr(0, pathLen - 1); - isSlashDropped = true; - } - - for (i=0, l=path.length; i= 0 && proceed; --i) { - var route = routes[i]; - recognizer.add(routes, { as: route.handler }); - proceed = route.path === '/' || route.path === '' || route.handler.slice(-6) === '.index'; - } - }); - }, - - hasRoute: function(route) { - return this.recognizer.hasRoute(route); - }, - - queryParamsTransition: function(changelist, wasTransitioning, oldState, newState) { - var router = this; - - fireQueryParamDidChange(this, newState, changelist); - - if (!wasTransitioning && this.activeTransition) { - // One of the handlers in queryParamsDidChange - // caused a transition. Just return that transition. - return this.activeTransition; - } else { - // Running queryParamsDidChange didn't change anything. - // Just update query params and be on our way. - - // We have to return a noop transition that will - // perform a URL update at the end. This gives - // the user the ability to set the url update - // method (default is replaceState). - var newTransition = new Transition(this); - newTransition.queryParamsOnly = true; - - oldState.queryParams = finalizeQueryParamChange(this, newState.handlerInfos, newState.queryParams, newTransition); - - newTransition.promise = newTransition.promise.then(function(result) { - updateURL(newTransition, oldState, true); - if (router.didTransition) { - router.didTransition(router.currentHandlerInfos); - } - return result; - }, null, promiseLabel("Transition complete")); - return newTransition; - } - }, - - // NOTE: this doesn't really belong here, but here - // it shall remain until our ES6 transpiler can - // handle cyclical deps. - transitionByIntent: function(intent, isIntermediate) { - - var wasTransitioning = !!this.activeTransition; - var oldState = wasTransitioning ? this.activeTransition.state : this.state; - var newTransition; - var router = this; - - try { - var newState = intent.applyToState(oldState, this.recognizer, this.getHandler, isIntermediate); - var queryParamChangelist = getChangelist(oldState.queryParams, newState.queryParams); - - if (handlerInfosEqual(newState.handlerInfos, oldState.handlerInfos)) { - - // This is a no-op transition. See if query params changed. - if (queryParamChangelist) { - newTransition = this.queryParamsTransition(queryParamChangelist, wasTransitioning, oldState, newState); - if (newTransition) { - return newTransition; - } - } - - // No-op. No need to create a new transition. - return new Transition(this); - } - - if (isIntermediate) { - setupContexts(this, newState); - return; - } - - // Create a new transition to the destination route. - newTransition = new Transition(this, intent, newState); - - // Abort and usurp any previously active transition. - if (this.activeTransition) { - this.activeTransition.abort(); - } - this.activeTransition = newTransition; - - // Transition promises by default resolve with resolved state. - // For our purposes, swap out the promise to resolve - // after the transition has been finalized. - newTransition.promise = newTransition.promise.then(function(result) { - return finalizeTransition(newTransition, result.state); - }, null, promiseLabel("Settle transition promise when transition is finalized")); - - if (!wasTransitioning) { - notifyExistingHandlers(this, newState, newTransition); - } - - fireQueryParamDidChange(this, newState, queryParamChangelist); - - return newTransition; - } catch(e) { - return new Transition(this, intent, null, e); - } - }, - - /** - Clears the current and target route handlers and triggers exit - on each of them starting at the leaf and traversing up through - its ancestors. - */ - reset: function() { - if (this.state) { - forEach(this.state.handlerInfos.slice().reverse(), function(handlerInfo) { - var handler = handlerInfo.handler; - callHook(handler, 'exit'); - }); - } - - this.state = new TransitionState(); - this.currentHandlerInfos = null; - }, - - activeTransition: null, - - /** - var handler = handlerInfo.handler; - The entry point for handling a change to the URL (usually - via the back and forward button). - - Returns an Array of handlers and the parameters associated - with those parameters. - - @param {String} url a URL to process - - @return {Array} an Array of `[handler, parameter]` tuples - */ - handleURL: function(url) { - // Perform a URL-based transition, but don't change - // the URL afterward, since it already happened. - var args = slice.call(arguments); - if (url.charAt(0) !== '/') { args[0] = '/' + url; } - - return doTransition(this, args).method(null); - }, - - /** - Hook point for updating the URL. - - @param {String} url a URL to update to - */ - updateURL: function() { - throw new Error("updateURL is not implemented"); - }, - - /** - Hook point for replacing the current URL, i.e. with replaceState - - By default this behaves the same as `updateURL` - - @param {String} url a URL to update to - */ - replaceURL: function(url) { - this.updateURL(url); - }, - - /** - Transition into the specified named route. - - If necessary, trigger the exit callback on any handlers - that are no longer represented by the target route. - - @param {String} name the name of the route - */ - transitionTo: function(name) { - return doTransition(this, arguments); - }, - - intermediateTransitionTo: function(name) { - return doTransition(this, arguments, true); - }, - - refresh: function(pivotHandler) { - var state = this.activeTransition ? this.activeTransition.state : this.state; - var handlerInfos = state.handlerInfos; - var params = {}; - for (var i = 0, len = handlerInfos.length; i < len; ++i) { - var handlerInfo = handlerInfos[i]; - params[handlerInfo.name] = handlerInfo.params || {}; - } - - log(this, "Starting a refresh transition"); - var intent = new NamedTransitionIntent({ - name: handlerInfos[handlerInfos.length - 1].name, - pivotHandler: pivotHandler || handlerInfos[0].handler, - contexts: [], // TODO collect contexts...? - queryParams: this._changedQueryParams || state.queryParams || {} - }); - - return this.transitionByIntent(intent, false); - }, - - /** - Identical to `transitionTo` except that the current URL will be replaced - if possible. - - This method is intended primarily for use with `replaceState`. - - @param {String} name the name of the route - */ - replaceWith: function(name) { - return doTransition(this, arguments).method('replace'); - }, - - /** - Take a named route and context objects and generate a - URL. - - @param {String} name the name of the route to generate - a URL for - @param {...Object} objects a list of objects to serialize - - @return {String} a URL - */ - generate: function(handlerName) { - - var partitionedArgs = extractQueryParams(slice.call(arguments, 1)), - suppliedParams = partitionedArgs[0], - queryParams = partitionedArgs[1]; - - // Construct a TransitionIntent with the provided params - // and apply it to the present state of the router. - var intent = new NamedTransitionIntent({ name: handlerName, contexts: suppliedParams }); - var state = intent.applyToState(this.state, this.recognizer, this.getHandler); - var params = {}; - - for (var i = 0, len = state.handlerInfos.length; i < len; ++i) { - var handlerInfo = state.handlerInfos[i]; - var handlerParams = handlerInfo.serialize(); - merge(params, handlerParams); - } - params.queryParams = queryParams; - - return this.recognizer.generate(handlerName, params); - }, - - applyIntent: function(handlerName, contexts) { - var intent = new NamedTransitionIntent({ - name: handlerName, - contexts: contexts - }); - - var state = this.activeTransition && this.activeTransition.state || this.state; - return intent.applyToState(state, this.recognizer, this.getHandler); - }, - - isActiveIntent: function(handlerName, contexts, queryParams) { - var targetHandlerInfos = this.state.handlerInfos, - found = false, names, object, handlerInfo, handlerObj, i, len; - - if (!targetHandlerInfos.length) { return false; } - - var targetHandler = targetHandlerInfos[targetHandlerInfos.length - 1].name; - var recogHandlers = this.recognizer.handlersFor(targetHandler); - - var index = 0; - for (len = recogHandlers.length; index < len; ++index) { - handlerInfo = targetHandlerInfos[index]; - if (handlerInfo.name === handlerName) { break; } - } - - if (index === recogHandlers.length) { - // The provided route name isn't even in the route hierarchy. - return false; - } - - var state = new TransitionState(); - state.handlerInfos = targetHandlerInfos.slice(0, index + 1); - recogHandlers = recogHandlers.slice(0, index + 1); - - var intent = new NamedTransitionIntent({ - name: targetHandler, - contexts: contexts - }); - - var newState = intent.applyToHandlers(state, recogHandlers, this.getHandler, targetHandler, true, true); - - var handlersEqual = handlerInfosEqual(newState.handlerInfos, state.handlerInfos); - if (!queryParams || !handlersEqual) { - return handlersEqual; - } - - // Get a hash of QPs that will still be active on new route - var activeQPsOnNewHandler = {}; - merge(activeQPsOnNewHandler, queryParams); - - var activeQueryParams = this.state.queryParams; - for (var key in activeQueryParams) { - if (activeQueryParams.hasOwnProperty(key) && - activeQPsOnNewHandler.hasOwnProperty(key)) { - activeQPsOnNewHandler[key] = activeQueryParams[key]; - } - } - - return handlersEqual && !getChangelist(activeQPsOnNewHandler, queryParams); - }, - - isActive: function(handlerName) { - var partitionedArgs = extractQueryParams(slice.call(arguments, 1)); - return this.isActiveIntent(handlerName, partitionedArgs[0], partitionedArgs[1]); - }, - - trigger: function(name) { - var args = slice.call(arguments); - trigger(this, this.currentHandlerInfos, false, args); - }, - - /** - Hook point for logging transition status updates. - - @param {String} message The message to log. - */ - log: null, - - _willChangeContextEvent: 'willChangeContext', - _triggerWillChangeContext: function(handlerInfos, newTransition) { - trigger(this, handlerInfos, true, [this._willChangeContextEvent, newTransition]); - }, - - _triggerWillLeave: function(handlerInfos, newTransition, leavingChecker) { - trigger(this, handlerInfos, true, ['willLeave', newTransition, leavingChecker]); - } - }; - - /** - @private - - Fires queryParamsDidChange event - */ - function fireQueryParamDidChange(router, newState, queryParamChangelist) { - // If queryParams changed trigger event - if (queryParamChangelist) { - - // This is a little hacky but we need some way of storing - // changed query params given that no activeTransition - // is guaranteed to have occurred. - router._changedQueryParams = queryParamChangelist.all; - trigger(router, newState.handlerInfos, true, ['queryParamsDidChange', queryParamChangelist.changed, queryParamChangelist.all, queryParamChangelist.removed]); - router._changedQueryParams = null; - } - } - - /** - @private - - Takes an Array of `HandlerInfo`s, figures out which ones are - exiting, entering, or changing contexts, and calls the - proper handler hooks. - - For example, consider the following tree of handlers. Each handler is - followed by the URL segment it handles. - - ``` - |~index ("/") - | |~posts ("/posts") - | | |-showPost ("/:id") - | | |-newPost ("/new") - | | |-editPost ("/edit") - | |~about ("/about/:id") - ``` - - Consider the following transitions: - - 1. A URL transition to `/posts/1`. - 1. Triggers the `*model` callbacks on the - `index`, `posts`, and `showPost` handlers - 2. Triggers the `enter` callback on the same - 3. Triggers the `setup` callback on the same - 2. A direct transition to `newPost` - 1. Triggers the `exit` callback on `showPost` - 2. Triggers the `enter` callback on `newPost` - 3. Triggers the `setup` callback on `newPost` - 3. A direct transition to `about` with a specified - context object - 1. Triggers the `exit` callback on `newPost` - and `posts` - 2. Triggers the `serialize` callback on `about` - 3. Triggers the `enter` callback on `about` - 4. Triggers the `setup` callback on `about` - - @param {Router} transition - @param {TransitionState} newState - */ - function setupContexts(router, newState, transition) { - var partition = partitionHandlers(router.state, newState); - - forEach(partition.exited, function(handlerInfo) { - var handler = handlerInfo.handler; - delete handler.context; - - callHook(handler, 'reset', true, transition); - callHook(handler, 'exit', transition); - }); - - var oldState = router.oldState = router.state; - router.state = newState; - var currentHandlerInfos = router.currentHandlerInfos = partition.unchanged.slice(); - - try { - forEach(partition.reset, function(handlerInfo) { - var handler = handlerInfo.handler; - callHook(handler, 'reset', false, transition); - }); - - forEach(partition.updatedContext, function(handlerInfo) { - return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, false, transition); - }); - - forEach(partition.entered, function(handlerInfo) { - return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, true, transition); - }); - } catch(e) { - router.state = oldState; - router.currentHandlerInfos = oldState.handlerInfos; - throw e; - } - - router.state.queryParams = finalizeQueryParamChange(router, currentHandlerInfos, newState.queryParams, transition); - } - - - /** - @private - - Helper method used by setupContexts. Handles errors or redirects - that may happen in enter/setup. - */ - function handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, enter, transition) { - - var handler = handlerInfo.handler, - context = handlerInfo.context; - - callHook(handler, 'enter', transition); - if (transition && transition.isAborted) { - throw new TransitionAborted(); - } - - handler.context = context; - callHook(handler, 'contextDidChange'); - - callHook(handler, 'setup', context, transition); - if (transition && transition.isAborted) { - throw new TransitionAborted(); - } - - currentHandlerInfos.push(handlerInfo); - - return true; - } - - - /** - @private - - This function is called when transitioning from one URL to - another to determine which handlers are no longer active, - which handlers are newly active, and which handlers remain - active but have their context changed. - - Take a list of old handlers and new handlers and partition - them into four buckets: - - * unchanged: the handler was active in both the old and - new URL, and its context remains the same - * updated context: the handler was active in both the - old and new URL, but its context changed. The handler's - `setup` method, if any, will be called with the new - context. - * exited: the handler was active in the old URL, but is - no longer active. - * entered: the handler was not active in the old URL, but - is now active. - - The PartitionedHandlers structure has four fields: - - * `updatedContext`: a list of `HandlerInfo` objects that - represent handlers that remain active but have a changed - context - * `entered`: a list of `HandlerInfo` objects that represent - handlers that are newly active - * `exited`: a list of `HandlerInfo` objects that are no - longer active. - * `unchanged`: a list of `HanderInfo` objects that remain active. - - @param {Array[HandlerInfo]} oldHandlers a list of the handler - information for the previous URL (or `[]` if this is the - first handled transition) - @param {Array[HandlerInfo]} newHandlers a list of the handler - information for the new URL - - @return {Partition} - */ - function partitionHandlers(oldState, newState) { - var oldHandlers = oldState.handlerInfos; - var newHandlers = newState.handlerInfos; - - var handlers = { - updatedContext: [], - exited: [], - entered: [], - unchanged: [] - }; - - var handlerChanged, contextChanged = false, i, l; - - for (i=0, l=newHandlers.length; i= 0; --i) { - var handlerInfo = handlerInfos[i]; - merge(params, handlerInfo.params); - if (handlerInfo.handler.inaccessibleByURL) { - urlMethod = null; - } - } - - if (urlMethod) { - params.queryParams = transition._visibleQueryParams || state.queryParams; - var url = router.recognizer.generate(handlerName, params); - - if (urlMethod === 'replace') { - router.replaceURL(url); - } else { - router.updateURL(url); - } - } - } - - /** - @private - - Updates the URL (if necessary) and calls `setupContexts` - to update the router's array of `currentHandlerInfos`. - */ - function finalizeTransition(transition, newState) { - - try { - log(transition.router, transition.sequence, "Resolved all models on destination route; finalizing transition."); - - var router = transition.router, - handlerInfos = newState.handlerInfos, - seq = transition.sequence; - - // Run all the necessary enter/setup/exit hooks - setupContexts(router, newState, transition); - - // Check if a redirect occurred in enter/setup - if (transition.isAborted) { - // TODO: cleaner way? distinguish b/w targetHandlerInfos? - router.state.handlerInfos = router.currentHandlerInfos; - return Promise.reject(logAbort(transition)); - } - - updateURL(transition, newState, transition.intent.url); - - transition.isActive = false; - router.activeTransition = null; - - trigger(router, router.currentHandlerInfos, true, ['didTransition']); - - if (router.didTransition) { - router.didTransition(router.currentHandlerInfos); - } - - log(router, transition.sequence, "TRANSITION COMPLETE."); - - // Resolve with the final handler. - return handlerInfos[handlerInfos.length - 1].handler; - } catch(e) { - if (!((e instanceof TransitionAborted))) { - //var erroneousHandler = handlerInfos.pop(); - var infos = transition.state.handlerInfos; - transition.trigger(true, 'error', e, transition, infos[infos.length-1].handler); - transition.abort(); - } - - throw e; - } - } - - /** - @private - - Begins and returns a Transition based on the provided - arguments. Accepts arguments in the form of both URL - transitions and named transitions. - - @param {Router} router - @param {Array[Object]} args arguments passed to transitionTo, - replaceWith, or handleURL - */ - function doTransition(router, args, isIntermediate) { - // Normalize blank transitions to root URL transitions. - var name = args[0] || '/'; - - var lastArg = args[args.length-1]; - var queryParams = {}; - if (lastArg && lastArg.hasOwnProperty('queryParams')) { - queryParams = pop.call(args).queryParams; - } - - var intent; - if (args.length === 0) { - - log(router, "Updating query params"); - - // A query param update is really just a transition - // into the route you're already on. - var handlerInfos = router.state.handlerInfos; - intent = new NamedTransitionIntent({ - name: handlerInfos[handlerInfos.length - 1].name, - contexts: [], - queryParams: queryParams - }); - - } else if (name.charAt(0) === '/') { - - log(router, "Attempting URL transition to " + name); - intent = new URLTransitionIntent({ url: name }); - - } else { - - log(router, "Attempting transition to " + name); - intent = new NamedTransitionIntent({ - name: args[0], - contexts: slice.call(args, 1), - queryParams: queryParams - }); - } - - return router.transitionByIntent(intent, isIntermediate); - } - - function handlerInfosEqual(handlerInfos, otherHandlerInfos) { - if (handlerInfos.length !== otherHandlerInfos.length) { - return false; - } - - for (var i = 0, len = handlerInfos.length; i < len; ++i) { - if (handlerInfos[i] !== otherHandlerInfos[i]) { - return false; - } - } - return true; - } - - function finalizeQueryParamChange(router, resolvedHandlers, newQueryParams, transition) { - // We fire a finalizeQueryParamChange event which - // gives the new route hierarchy a chance to tell - // us which query params it's consuming and what - // their final values are. If a query param is - // no longer consumed in the final route hierarchy, - // its serialized segment will be removed - // from the URL. - - for (var k in newQueryParams) { - if (newQueryParams.hasOwnProperty(k) && - newQueryParams[k] === null) { - delete newQueryParams[k]; - } - } - - var finalQueryParamsArray = []; - trigger(router, resolvedHandlers, true, ['finalizeQueryParamChange', newQueryParams, finalQueryParamsArray, transition]); - - if (transition) { - transition._visibleQueryParams = {}; - } - - var finalQueryParams = {}; - for (var i = 0, len = finalQueryParamsArray.length; i < len; ++i) { - var qp = finalQueryParamsArray[i]; - finalQueryParams[qp.key] = qp.value; - if (transition && qp.visible !== false) { - transition._visibleQueryParams[qp.key] = qp.value; - } - } - return finalQueryParams; - } - - function notifyExistingHandlers(router, newState, newTransition) { - var oldHandlers = router.state.handlerInfos, - changing = [], - leavingIndex = null, - leaving, leavingChecker, i, oldHandlerLen, oldHandler, newHandler; - - oldHandlerLen = oldHandlers.length; - for (i = 0; i < oldHandlerLen; i++) { - oldHandler = oldHandlers[i]; - newHandler = newState.handlerInfos[i]; - - if (!newHandler || oldHandler.name !== newHandler.name) { - leavingIndex = i; - break; - } - - if (!newHandler.isResolved) { - changing.push(oldHandler); - } - } - - if (leavingIndex !== null) { - leaving = oldHandlers.slice(leavingIndex, oldHandlerLen); - leavingChecker = function(name) { - for (var h = 0, len = leaving.length; h < len; h++) { - if (leaving[h].name === name) { - return true; - } - } - return false; - }; - - router._triggerWillLeave(leaving, newTransition, leavingChecker); - } - - if (changing.length > 0) { - router._triggerWillChangeContext(changing, newTransition); - } - - trigger(router, oldHandlers, true, ['willTransition', newTransition]); - } - - __exports__["default"] = Router; - }); -define("router/transition-intent", - ["./utils","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var merge = __dependency1__.merge; - - function TransitionIntent(props) { - this.initialize(props); - - // TODO: wat - this.data = this.data || {}; - } - - TransitionIntent.prototype = { - initialize: null, - applyToState: null - }; - - __exports__["default"] = TransitionIntent; - }); -define("router/transition-intent/named-transition-intent", - ["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var TransitionIntent = __dependency1__["default"]; - var TransitionState = __dependency2__["default"]; - var handlerInfoFactory = __dependency3__["default"]; - var isParam = __dependency4__.isParam; - var extractQueryParams = __dependency4__.extractQueryParams; - var merge = __dependency4__.merge; - var subclass = __dependency4__.subclass; - - __exports__["default"] = subclass(TransitionIntent, { - name: null, - pivotHandler: null, - contexts: null, - queryParams: null, - - initialize: function(props) { - this.name = props.name; - this.pivotHandler = props.pivotHandler; - this.contexts = props.contexts || []; - this.queryParams = props.queryParams; - }, - - applyToState: function(oldState, recognizer, getHandler, isIntermediate) { - - var partitionedArgs = extractQueryParams([this.name].concat(this.contexts)), - pureArgs = partitionedArgs[0], - queryParams = partitionedArgs[1], - handlers = recognizer.handlersFor(pureArgs[0]); - - var targetRouteName = handlers[handlers.length-1].handler; - - return this.applyToHandlers(oldState, handlers, getHandler, targetRouteName, isIntermediate); - }, - - applyToHandlers: function(oldState, handlers, getHandler, targetRouteName, isIntermediate, checkingIfActive) { - - var i, len; - var newState = new TransitionState(); - var objects = this.contexts.slice(0); - - var invalidateIndex = handlers.length; - - // Pivot handlers are provided for refresh transitions - if (this.pivotHandler) { - for (i = 0, len = handlers.length; i < len; ++i) { - if (getHandler(handlers[i].handler) === this.pivotHandler) { - invalidateIndex = i; - break; - } - } - } - - var pivotHandlerFound = !this.pivotHandler; - - for (i = handlers.length - 1; i >= 0; --i) { - var result = handlers[i]; - var name = result.handler; - var handler = getHandler(name); - - var oldHandlerInfo = oldState.handlerInfos[i]; - var newHandlerInfo = null; - - if (result.names.length > 0) { - if (i >= invalidateIndex) { - newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo); - } else { - newHandlerInfo = this.getHandlerInfoForDynamicSegment(name, handler, result.names, objects, oldHandlerInfo, targetRouteName, i); - } - } else { - // This route has no dynamic segment. - // Therefore treat as a param-based handlerInfo - // with empty params. This will cause the `model` - // hook to be called with empty params, which is desirable. - newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo); - } - - if (checkingIfActive) { - // If we're performing an isActive check, we want to - // serialize URL params with the provided context, but - // ignore mismatches between old and new context. - newHandlerInfo = newHandlerInfo.becomeResolved(null, newHandlerInfo.context); - var oldContext = oldHandlerInfo && oldHandlerInfo.context; - if (result.names.length > 0 && newHandlerInfo.context === oldContext) { - // If contexts match in isActive test, assume params also match. - // This allows for flexibility in not requiring that every last - // handler provide a `serialize` method - newHandlerInfo.params = oldHandlerInfo && oldHandlerInfo.params; - } - newHandlerInfo.context = oldContext; - } - - var handlerToUse = oldHandlerInfo; - if (i >= invalidateIndex || newHandlerInfo.shouldSupercede(oldHandlerInfo)) { - invalidateIndex = Math.min(i, invalidateIndex); - handlerToUse = newHandlerInfo; - } - - if (isIntermediate && !checkingIfActive) { - handlerToUse = handlerToUse.becomeResolved(null, handlerToUse.context); - } - - newState.handlerInfos.unshift(handlerToUse); - } - - if (objects.length > 0) { - throw new Error("More context objects were passed than there are dynamic segments for the route: " + targetRouteName); - } - - if (!isIntermediate) { - this.invalidateChildren(newState.handlerInfos, invalidateIndex); - } - - merge(newState.queryParams, this.queryParams || {}); - - return newState; - }, - - invalidateChildren: function(handlerInfos, invalidateIndex) { - for (var i = invalidateIndex, l = handlerInfos.length; i < l; ++i) { - var handlerInfo = handlerInfos[i]; - handlerInfos[i] = handlerInfos[i].getUnresolved(); - } - }, - - getHandlerInfoForDynamicSegment: function(name, handler, names, objects, oldHandlerInfo, targetRouteName, i) { - - var numNames = names.length; - var objectToUse; - if (objects.length > 0) { - - // Use the objects provided for this transition. - objectToUse = objects[objects.length - 1]; - if (isParam(objectToUse)) { - return this.createParamHandlerInfo(name, handler, names, objects, oldHandlerInfo); - } else { - objects.pop(); - } - } else if (oldHandlerInfo && oldHandlerInfo.name === name) { - // Reuse the matching oldHandlerInfo - return oldHandlerInfo; - } else { - if (this.preTransitionState) { - var preTransitionHandlerInfo = this.preTransitionState.handlerInfos[i]; - objectToUse = preTransitionHandlerInfo && preTransitionHandlerInfo.context; - } else { - // Ideally we should throw this error to provide maximal - // information to the user that not enough context objects - // were provided, but this proves too cumbersome in Ember - // in cases where inner template helpers are evaluated - // before parent helpers un-render, in which cases this - // error somewhat prematurely fires. - //throw new Error("Not enough context objects were provided to complete a transition to " + targetRouteName + ". Specifically, the " + name + " route needs an object that can be serialized into its dynamic URL segments [" + names.join(', ') + "]"); - return oldHandlerInfo; - } - } - - return handlerInfoFactory('object', { - name: name, - handler: handler, - context: objectToUse, - names: names - }); - }, - - createParamHandlerInfo: function(name, handler, names, objects, oldHandlerInfo) { - var params = {}; - - // Soak up all the provided string/numbers - var numNames = names.length; - while (numNames--) { - - // Only use old params if the names match with the new handler - var oldParams = (oldHandlerInfo && name === oldHandlerInfo.name && oldHandlerInfo.params) || {}; - - var peek = objects[objects.length - 1]; - var paramName = names[numNames]; - if (isParam(peek)) { - params[paramName] = "" + objects.pop(); - } else { - // If we're here, this means only some of the params - // were string/number params, so try and use a param - // value from a previous handler. - if (oldParams.hasOwnProperty(paramName)) { - params[paramName] = oldParams[paramName]; - } else { - throw new Error("You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route " + name); - } - } - } - - return handlerInfoFactory('param', { - name: name, - handler: handler, - params: params - }); - } - }); - }); -define("router/transition-intent/url-transition-intent", - ["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var TransitionIntent = __dependency1__["default"]; - var TransitionState = __dependency2__["default"]; - var handlerInfoFactory = __dependency3__["default"]; - var oCreate = __dependency4__.oCreate; - var merge = __dependency4__.merge; - var subclass = __dependency4__.subclass; - - __exports__["default"] = subclass(TransitionIntent, { - url: null, - - initialize: function(props) { - this.url = props.url; - }, - - applyToState: function(oldState, recognizer, getHandler) { - var newState = new TransitionState(); - - var results = recognizer.recognize(this.url), - queryParams = {}, - i, len; - - if (!results) { - throw new UnrecognizedURLError(this.url); - } - - var statesDiffer = false; - - for (i = 0, len = results.length; i < len; ++i) { - var result = results[i]; - var name = result.handler; - var handler = getHandler(name); - - if (handler.inaccessibleByURL) { - throw new UnrecognizedURLError(this.url); - } - - var newHandlerInfo = handlerInfoFactory('param', { - name: name, - handler: handler, - params: result.params - }); - - var oldHandlerInfo = oldState.handlerInfos[i]; - if (statesDiffer || newHandlerInfo.shouldSupercede(oldHandlerInfo)) { - statesDiffer = true; - newState.handlerInfos[i] = newHandlerInfo; - } else { - newState.handlerInfos[i] = oldHandlerInfo; - } - } - - merge(newState.queryParams, results.queryParams); - - return newState; - } - }); - - /** - Promise reject reasons passed to promise rejection - handlers for failed transitions. - */ - function UnrecognizedURLError(message) { - this.message = (message || "UnrecognizedURLError"); - this.name = "UnrecognizedURLError"; - } - }); -define("router/transition-state", - ["./handler-info","./utils","rsvp/promise","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var ResolvedHandlerInfo = __dependency1__.ResolvedHandlerInfo; - var forEach = __dependency2__.forEach; - var promiseLabel = __dependency2__.promiseLabel; - var callHook = __dependency2__.callHook; - var Promise = __dependency3__["default"]; - - function TransitionState(other) { - this.handlerInfos = []; - this.queryParams = {}; - this.params = {}; - } - - TransitionState.prototype = { - handlerInfos: null, - queryParams: null, - params: null, - - promiseLabel: function(label) { - var targetName = ''; - forEach(this.handlerInfos, function(handlerInfo) { - if (targetName !== '') { - targetName += '.'; - } - targetName += handlerInfo.name; - }); - return promiseLabel("'" + targetName + "': " + label); - }, - - resolve: function(shouldContinue, payload) { - var self = this; - // First, calculate params for this state. This is useful - // information to provide to the various route hooks. - var params = this.params; - forEach(this.handlerInfos, function(handlerInfo) { - params[handlerInfo.name] = handlerInfo.params || {}; - }); - - payload = payload || {}; - payload.resolveIndex = 0; - - var currentState = this; - var wasAborted = false; - - // The prelude RSVP.resolve() asyncs us into the promise land. - return Promise.resolve(null, this.promiseLabel("Start transition")) - .then(resolveOneHandlerInfo, null, this.promiseLabel('Resolve handler'))['catch'](handleError, this.promiseLabel('Handle error')); - - function innerShouldContinue() { - return Promise.resolve(shouldContinue(), currentState.promiseLabel("Check if should continue"))['catch'](function(reason) { - // We distinguish between errors that occurred - // during resolution (e.g. beforeModel/model/afterModel), - // and aborts due to a rejecting promise from shouldContinue(). - wasAborted = true; - return Promise.reject(reason); - }, currentState.promiseLabel("Handle abort")); - } - - function handleError(error) { - // This is the only possible - // reject value of TransitionState#resolve - var handlerInfos = currentState.handlerInfos; - var errorHandlerIndex = payload.resolveIndex >= handlerInfos.length ? - handlerInfos.length - 1 : payload.resolveIndex; - return Promise.reject({ - error: error, - handlerWithError: currentState.handlerInfos[errorHandlerIndex].handler, - wasAborted: wasAborted, - state: currentState - }); - } - - function proceed(resolvedHandlerInfo) { - var wasAlreadyResolved = currentState.handlerInfos[payload.resolveIndex].isResolved; - - // Swap the previously unresolved handlerInfo with - // the resolved handlerInfo - currentState.handlerInfos[payload.resolveIndex++] = resolvedHandlerInfo; - - if (!wasAlreadyResolved) { - // Call the redirect hook. The reason we call it here - // vs. afterModel is so that redirects into child - // routes don't re-run the model hooks for this - // already-resolved route. - var handler = resolvedHandlerInfo.handler; - callHook(handler, 'redirect', resolvedHandlerInfo.context, payload); - } - - // Proceed after ensuring that the redirect hook - // didn't abort this transition by transitioning elsewhere. - return innerShouldContinue().then(resolveOneHandlerInfo, null, currentState.promiseLabel('Resolve handler')); - } - - function resolveOneHandlerInfo() { - if (payload.resolveIndex === currentState.handlerInfos.length) { - // This is is the only possible - // fulfill value of TransitionState#resolve - return { - error: null, - state: currentState - }; - } - - var handlerInfo = currentState.handlerInfos[payload.resolveIndex]; - - return handlerInfo.resolve(innerShouldContinue, payload) - .then(proceed, null, currentState.promiseLabel('Proceed')); - } - } - }; - - __exports__["default"] = TransitionState; - }); -define("router/transition", - ["rsvp/promise","./handler-info","./utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var ResolvedHandlerInfo = __dependency2__.ResolvedHandlerInfo; - var trigger = __dependency3__.trigger; - var slice = __dependency3__.slice; - var log = __dependency3__.log; - var promiseLabel = __dependency3__.promiseLabel; - - /** - @private - - A Transition is a thennable (a promise-like object) that represents - an attempt to transition to another route. It can be aborted, either - explicitly via `abort` or by attempting another transition while a - previous one is still underway. An aborted transition can also - be `retry()`d later. - */ - function Transition(router, intent, state, error) { - var transition = this; - this.state = state || router.state; - this.intent = intent; - this.router = router; - this.data = this.intent && this.intent.data || {}; - this.resolvedModels = {}; - this.queryParams = {}; - - if (error) { - this.promise = Promise.reject(error); - return; - } - - if (state) { - this.params = state.params; - this.queryParams = state.queryParams; - this.handlerInfos = state.handlerInfos; - - var len = state.handlerInfos.length; - if (len) { - this.targetName = state.handlerInfos[len-1].name; - } - - for (var i = 0; i < len; ++i) { - var handlerInfo = state.handlerInfos[i]; - - // TODO: this all seems hacky - if (!handlerInfo.isResolved) { break; } - this.pivotHandler = handlerInfo.handler; - } - - this.sequence = Transition.currentSequence++; - this.promise = state.resolve(checkForAbort, this)['catch'](function(result) { - if (result.wasAborted || transition.isAborted) { - return Promise.reject(logAbort(transition)); - } else { - transition.trigger('error', result.error, transition, result.handlerWithError); - transition.abort(); - return Promise.reject(result.error); - } - }, promiseLabel('Handle Abort')); - } else { - this.promise = Promise.resolve(this.state); - this.params = {}; - } - - function checkForAbort() { - if (transition.isAborted) { - return Promise.reject(undefined, promiseLabel("Transition aborted - reject")); - } - } - } - - Transition.currentSequence = 0; - - Transition.prototype = { - targetName: null, - urlMethod: 'update', - intent: null, - params: null, - pivotHandler: null, - resolveIndex: 0, - handlerInfos: null, - resolvedModels: null, - isActive: true, - state: null, - queryParamsOnly: false, - - isTransition: true, - - isExiting: function(handler) { - var handlerInfos = this.handlerInfos; - for (var i = 0, len = handlerInfos.length; i < len; ++i) { - var handlerInfo = handlerInfos[i]; - if (handlerInfo.name === handler || handlerInfo.handler === handler) { - return false; - } - } - return true; - }, - - /** - @public - - The Transition's internal promise. Calling `.then` on this property - is that same as calling `.then` on the Transition object itself, but - this property is exposed for when you want to pass around a - Transition's promise, but not the Transition object itself, since - Transition object can be externally `abort`ed, while the promise - cannot. - */ - promise: null, - - /** - @public - - Custom state can be stored on a Transition's `data` object. - This can be useful for decorating a Transition within an earlier - hook and shared with a later hook. Properties set on `data` will - be copied to new transitions generated by calling `retry` on this - transition. - */ - data: null, - - /** - @public - - A standard promise hook that resolves if the transition - succeeds and rejects if it fails/redirects/aborts. - - Forwards to the internal `promise` property which you can - use in situations where you want to pass around a thennable, - but not the Transition itself. - - @param {Function} onFulfilled - @param {Function} onRejected - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - then: function(onFulfilled, onRejected, label) { - return this.promise.then(onFulfilled, onRejected, label); - }, - - /** - @public - - Forwards to the internal `promise` property which you can - use in situations where you want to pass around a thennable, - but not the Transition itself. - - @method catch - @param {Function} onRejection - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - "catch": function(onRejection, label) { - return this.promise["catch"](onRejection, label); - }, - - /** - @public - - Forwards to the internal `promise` property which you can - use in situations where you want to pass around a thennable, - but not the Transition itself. - - @method finally - @param {Function} callback - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - "finally": function(callback, label) { - return this.promise["finally"](callback, label); - }, - - /** - @public - - Aborts the Transition. Note you can also implicitly abort a transition - by initiating another transition while a previous one is underway. - */ - abort: function() { - if (this.isAborted) { return this; } - log(this.router, this.sequence, this.targetName + ": transition was aborted"); - this.intent.preTransitionState = this.router.state; - this.isAborted = true; - this.isActive = false; - this.router.activeTransition = null; - return this; - }, - - /** - @public - - Retries a previously-aborted transition (making sure to abort the - transition if it's still active). Returns a new transition that - represents the new attempt to transition. - */ - retry: function() { - // TODO: add tests for merged state retry()s - this.abort(); - return this.router.transitionByIntent(this.intent, false); - }, - - /** - @public - - Sets the URL-changing method to be employed at the end of a - successful transition. By default, a new Transition will just - use `updateURL`, but passing 'replace' to this method will - cause the URL to update using 'replaceWith' instead. Omitting - a parameter will disable the URL change, allowing for transitions - that don't update the URL at completion (this is also used for - handleURL, since the URL has already changed before the - transition took place). - - @param {String} method the type of URL-changing method to use - at the end of a transition. Accepted values are 'replace', - falsy values, or any other non-falsy value (which is - interpreted as an updateURL transition). - - @return {Transition} this transition - */ - method: function(method) { - this.urlMethod = method; - return this; - }, - - /** - @public - - Fires an event on the current list of resolved/resolving - handlers within this transition. Useful for firing events - on route hierarchies that haven't fully been entered yet. - - Note: This method is also aliased as `send` - - @param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error - @param {String} name the name of the event to fire - */ - trigger: function (ignoreFailure) { - var args = slice.call(arguments); - if (typeof ignoreFailure === 'boolean') { - args.shift(); - } else { - // Throw errors on unhandled trigger events by default - ignoreFailure = false; - } - trigger(this.router, this.state.handlerInfos.slice(0, this.resolveIndex + 1), ignoreFailure, args); - }, - - /** - @public - - Transitions are aborted and their promises rejected - when redirects occur; this method returns a promise - that will follow any redirects that occur and fulfill - with the value fulfilled by any redirecting transitions - that occur. - - @return {Promise} a promise that fulfills with the same - value that the final redirecting transition fulfills with - */ - followRedirects: function() { - var router = this.router; - return this.promise['catch'](function(reason) { - if (router.activeTransition) { - return router.activeTransition.followRedirects(); - } - return Promise.reject(reason); - }); - }, - - toString: function() { - return "Transition (sequence " + this.sequence + ")"; - }, - - /** - @private - */ - log: function(message) { - log(this.router, this.sequence, message); - } - }; - - // Alias 'trigger' as 'send' - Transition.prototype.send = Transition.prototype.trigger; - - /** - @private - - Logs and returns a TransitionAborted error. - */ - function logAbort(transition) { - log(transition.router, transition.sequence, "detected abort."); - return new TransitionAborted(); - } - - function TransitionAborted(message) { - this.message = (message || "TransitionAborted"); - this.name = "TransitionAborted"; - } - - __exports__.Transition = Transition; - __exports__.logAbort = logAbort; - __exports__.TransitionAborted = TransitionAborted; - }); -define("router/utils", - ["exports"], - function(__exports__) { - "use strict"; - var slice = Array.prototype.slice; - - var _isArray; - if (!Array.isArray) { - _isArray = function (x) { - return Object.prototype.toString.call(x) === "[object Array]"; - }; - } else { - _isArray = Array.isArray; - } - - var isArray = _isArray; - __exports__.isArray = isArray; - function merge(hash, other) { - for (var prop in other) { - if (other.hasOwnProperty(prop)) { hash[prop] = other[prop]; } - } - } - - var oCreate = Object.create || function(proto) { - function F() {} - F.prototype = proto; - return new F(); - }; - __exports__.oCreate = oCreate; - /** - @private - - Extracts query params from the end of an array - **/ - function extractQueryParams(array) { - var len = (array && array.length), head, queryParams; - - if(len && len > 0 && array[len - 1] && array[len - 1].hasOwnProperty('queryParams')) { - queryParams = array[len - 1].queryParams; - head = slice.call(array, 0, len - 1); - return [head, queryParams]; - } else { - return [array, null]; - } - } - - __exports__.extractQueryParams = extractQueryParams;/** - @private - - Coerces query param properties and array elements into strings. - **/ - function coerceQueryParamsToString(queryParams) { - for (var key in queryParams) { - if (typeof queryParams[key] === 'number') { - queryParams[key] = '' + queryParams[key]; - } else if (isArray(queryParams[key])) { - for (var i = 0, l = queryParams[key].length; i < l; i++) { - queryParams[key][i] = '' + queryParams[key][i]; - } - } - } - } - /** - @private - */ - function log(router, sequence, msg) { - if (!router.log) { return; } - - if (arguments.length === 3) { - router.log("Transition #" + sequence + ": " + msg); - } else { - msg = sequence; - router.log(msg); - } - } - - __exports__.log = log;function bind(context, fn) { - var boundArgs = arguments; - return function(value) { - var args = slice.call(boundArgs, 2); - args.push(value); - return fn.apply(context, args); - }; - } - - __exports__.bind = bind;function isParam(object) { - return (typeof object === "string" || object instanceof String || typeof object === "number" || object instanceof Number); - } - - - function forEach(array, callback) { - for (var i=0, l=array.length; i=0; i--) { - var handlerInfo = handlerInfos[i], - handler = handlerInfo.handler; - - if (handler.events && handler.events[name]) { - if (handler.events[name].apply(handler, args) === true) { - eventWasHandled = true; - } else { - return; - } - } - } - - if (!eventWasHandled && !ignoreFailure) { - throw new Error("Nothing handled the event '" + name + "'."); - } - } - - __exports__.trigger = trigger;function getChangelist(oldObject, newObject) { - var key; - var results = { - all: {}, - changed: {}, - removed: {} - }; - - merge(results.all, newObject); - - var didChange = false; - coerceQueryParamsToString(oldObject); - coerceQueryParamsToString(newObject); - - // Calculate removals - for (key in oldObject) { - if (oldObject.hasOwnProperty(key)) { - if (!newObject.hasOwnProperty(key)) { - didChange = true; - results.removed[key] = oldObject[key]; - } - } - } - - // Calculate changes - for (key in newObject) { - if (newObject.hasOwnProperty(key)) { - if (isArray(oldObject[key]) && isArray(newObject[key])) { - if (oldObject[key].length !== newObject[key].length) { - results.changed[key] = newObject[key]; - didChange = true; - } else { - for (var i = 0, l = oldObject[key].length; i < l; i++) { - if (oldObject[key][i] !== newObject[key][i]) { - results.changed[key] = newObject[key]; - didChange = true; - } - } - } - } - else { - if (oldObject[key] !== newObject[key]) { - results.changed[key] = newObject[key]; - didChange = true; - } - } - } - } - - return didChange && results; - } - - __exports__.getChangelist = getChangelist;function promiseLabel(label) { - return 'Router: ' + label; - } - - __exports__.promiseLabel = promiseLabel;function subclass(parentConstructor, proto) { - function C(props) { - parentConstructor.call(this, props || {}); - } - C.prototype = oCreate(parentConstructor.prototype); - merge(C.prototype, proto); - return C; - } - - __exports__.subclass = subclass;function resolveHook(obj, hookName) { - if (!obj) { return; } - var underscored = "_" + hookName; - return obj[underscored] && underscored || - obj[hookName] && hookName; - } - - function callHook(obj, hookName) { - var args = slice.call(arguments, 2); - return applyHook(obj, hookName, args); - } - - function applyHook(obj, _hookName, args) { - var hookName = resolveHook(obj, _hookName); - if (hookName) { - return obj[hookName].apply(obj, args); - } - } - - __exports__.merge = merge; - __exports__.slice = slice; - __exports__.isParam = isParam; - __exports__.coerceQueryParamsToString = coerceQueryParamsToString; - __exports__.callHook = callHook; - __exports__.resolveHook = resolveHook; - __exports__.applyHook = applyHook; - }); -define("router", - ["./router/router","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Router = __dependency1__["default"]; - - __exports__["default"] = Router; - }); - -define("rsvp", - ["./rsvp/promise","./rsvp/events","./rsvp/node","./rsvp/all","./rsvp/all-settled","./rsvp/race","./rsvp/hash","./rsvp/hash-settled","./rsvp/rethrow","./rsvp/defer","./rsvp/config","./rsvp/map","./rsvp/resolve","./rsvp/reject","./rsvp/filter","./rsvp/asap","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var EventTarget = __dependency2__["default"]; - var denodeify = __dependency3__["default"]; - var all = __dependency4__["default"]; - var allSettled = __dependency5__["default"]; - var race = __dependency6__["default"]; - var hash = __dependency7__["default"]; - var hashSettled = __dependency8__["default"]; - var rethrow = __dependency9__["default"]; - var defer = __dependency10__["default"]; - var config = __dependency11__.config; - var configure = __dependency11__.configure; - var map = __dependency12__["default"]; - var resolve = __dependency13__["default"]; - var reject = __dependency14__["default"]; - var filter = __dependency15__["default"]; - var asap = __dependency16__["default"]; - - config.async = asap; // default async is asap; - var cast = resolve; - function async(callback, arg) { - config.async(callback, arg); - } - - function on() { - config.on.apply(config, arguments); - } - - function off() { - config.off.apply(config, arguments); - } - - // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__` - if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') { - var callbacks = window['__PROMISE_INSTRUMENTATION__']; - configure('instrument', true); - for (var eventName in callbacks) { - if (callbacks.hasOwnProperty(eventName)) { - on(eventName, callbacks[eventName]); - } - } - } - - __exports__.cast = cast; - __exports__.Promise = Promise; - __exports__.EventTarget = EventTarget; - __exports__.all = all; - __exports__.allSettled = allSettled; - __exports__.race = race; - __exports__.hash = hash; - __exports__.hashSettled = hashSettled; - __exports__.rethrow = rethrow; - __exports__.defer = defer; - __exports__.denodeify = denodeify; - __exports__.configure = configure; - __exports__.on = on; - __exports__.off = off; - __exports__.resolve = resolve; - __exports__.reject = reject; - __exports__.async = async; - __exports__.map = map; - __exports__.filter = filter; - }); -define("rsvp.umd", - ["./rsvp"], - function(__dependency1__) { - "use strict"; - var Promise = __dependency1__.Promise; - var allSettled = __dependency1__.allSettled; - var hash = __dependency1__.hash; - var hashSettled = __dependency1__.hashSettled; - var denodeify = __dependency1__.denodeify; - var on = __dependency1__.on; - var off = __dependency1__.off; - var map = __dependency1__.map; - var filter = __dependency1__.filter; - var resolve = __dependency1__.resolve; - var reject = __dependency1__.reject; - var rethrow = __dependency1__.rethrow; - var all = __dependency1__.all; - var defer = __dependency1__.defer; - var EventTarget = __dependency1__.EventTarget; - var configure = __dependency1__.configure; - var race = __dependency1__.race; - var async = __dependency1__.async; - - var RSVP = { - 'race': race, - 'Promise': Promise, - 'allSettled': allSettled, - 'hash': hash, - 'hashSettled': hashSettled, - 'denodeify': denodeify, - 'on': on, - 'off': off, - 'map': map, - 'filter': filter, - 'resolve': resolve, - 'reject': reject, - 'all': all, - 'rethrow': rethrow, - 'defer': defer, - 'EventTarget': EventTarget, - 'configure': configure, - 'async': async - }; - - /* global define:true module:true window: true */ - if (typeof define === 'function' && define.amd) { - define(function() { return RSVP; }); - } else if (typeof module !== 'undefined' && module.exports) { - module.exports = RSVP; - } else if (typeof this !== 'undefined') { - this['RSVP'] = RSVP; - } - }); -define("rsvp/-internal", - ["./utils","./instrument","./config","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var objectOrFunction = __dependency1__.objectOrFunction; - var isFunction = __dependency1__.isFunction; - - var instrument = __dependency2__["default"]; - - var config = __dependency3__.config; - - function noop() {} - - var PENDING = void 0; - var FULFILLED = 1; - var REJECTED = 2; - - var GET_THEN_ERROR = new ErrorObject(); - - function getThen(promise) { - try { - return promise.then; - } catch(error) { - GET_THEN_ERROR.error = error; - return GET_THEN_ERROR; - } - } - - function tryThen(then, value, fulfillmentHandler, rejectionHandler) { - try { - then.call(value, fulfillmentHandler, rejectionHandler); - } catch(e) { - return e; - } - } - - function handleForeignThenable(promise, thenable, then) { - config.async(function(promise) { - var sealed = false; - var error = tryThen(then, thenable, function(value) { - if (sealed) { return; } - sealed = true; - if (thenable !== value) { - resolve(promise, value); - } else { - fulfill(promise, value); - } - }, function(reason) { - if (sealed) { return; } - sealed = true; - - reject(promise, reason); - }, 'Settle: ' + (promise._label || ' unknown promise')); - - if (!sealed && error) { - sealed = true; - reject(promise, error); - } - }, promise); - } - - function handleOwnThenable(promise, thenable) { - if (thenable._state === FULFILLED) { - fulfill(promise, thenable._result); - } else if (promise._state === REJECTED) { - reject(promise, thenable._result); - } else { - subscribe(thenable, undefined, function(value) { - if (thenable !== value) { - resolve(promise, value); - } else { - fulfill(promise, value); - } - }, function(reason) { - reject(promise, reason); - }); - } - } - - function handleMaybeThenable(promise, maybeThenable) { - if (maybeThenable.constructor === promise.constructor) { - handleOwnThenable(promise, maybeThenable); - } else { - var then = getThen(maybeThenable); - - if (then === GET_THEN_ERROR) { - reject(promise, GET_THEN_ERROR.error); - } else if (then === undefined) { - fulfill(promise, maybeThenable); - } else if (isFunction(then)) { - handleForeignThenable(promise, maybeThenable, then); - } else { - fulfill(promise, maybeThenable); - } - } - } - - function resolve(promise, value) { - if (promise === value) { - fulfill(promise, value); - } else if (objectOrFunction(value)) { - handleMaybeThenable(promise, value); - } else { - fulfill(promise, value); - } - } - - function publishRejection(promise) { - if (promise._onerror) { - promise._onerror(promise._result); - } - - publish(promise); - } - - function fulfill(promise, value) { - if (promise._state !== PENDING) { return; } - - promise._result = value; - promise._state = FULFILLED; - - if (promise._subscribers.length === 0) { - if (config.instrument) { - instrument('fulfilled', promise); - } - } else { - config.async(publish, promise); - } - } - - function reject(promise, reason) { - if (promise._state !== PENDING) { return; } - promise._state = REJECTED; - promise._result = reason; - - config.async(publishRejection, promise); - } - - function subscribe(parent, child, onFulfillment, onRejection) { - var subscribers = parent._subscribers; - var length = subscribers.length; - - parent._onerror = null; - - subscribers[length] = child; - subscribers[length + FULFILLED] = onFulfillment; - subscribers[length + REJECTED] = onRejection; - - if (length === 0 && parent._state) { - config.async(publish, parent); - } - } - - function publish(promise) { - var subscribers = promise._subscribers; - var settled = promise._state; - - if (config.instrument) { - instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise); - } - - if (subscribers.length === 0) { return; } - - var child, callback, detail = promise._result; - - for (var i = 0; i < subscribers.length; i += 3) { - child = subscribers[i]; - callback = subscribers[i + settled]; - - if (child) { - invokeCallback(settled, child, callback, detail); - } else { - callback(detail); - } - } - - promise._subscribers.length = 0; - } - - function ErrorObject() { - this.error = null; - } - - var TRY_CATCH_ERROR = new ErrorObject(); - - function tryCatch(callback, detail) { - try { - return callback(detail); - } catch(e) { - TRY_CATCH_ERROR.error = e; - return TRY_CATCH_ERROR; - } - } - - function invokeCallback(settled, promise, callback, detail) { - var hasCallback = isFunction(callback), - value, error, succeeded, failed; - - if (hasCallback) { - value = tryCatch(callback, detail); - - if (value === TRY_CATCH_ERROR) { - failed = true; - error = value.error; - value = null; - } else { - succeeded = true; - } - - if (promise === value) { - reject(promise, new TypeError('A promises callback cannot return that same promise.')); - return; - } - - } else { - value = detail; - succeeded = true; - } - - if (promise._state !== PENDING) { - // noop - } else if (hasCallback && succeeded) { - resolve(promise, value); - } else if (failed) { - reject(promise, error); - } else if (settled === FULFILLED) { - fulfill(promise, value); - } else if (settled === REJECTED) { - reject(promise, value); - } - } - - function initializePromise(promise, resolver) { - try { - resolver(function resolvePromise(value){ - resolve(promise, value); - }, function rejectPromise(reason) { - reject(promise, reason); - }); - } catch(e) { - reject(promise, e); - } - } - - __exports__.noop = noop; - __exports__.resolve = resolve; - __exports__.reject = reject; - __exports__.fulfill = fulfill; - __exports__.subscribe = subscribe; - __exports__.publish = publish; - __exports__.publishRejection = publishRejection; - __exports__.initializePromise = initializePromise; - __exports__.invokeCallback = invokeCallback; - __exports__.FULFILLED = FULFILLED; - __exports__.REJECTED = REJECTED; - __exports__.PENDING = PENDING; - }); -define("rsvp/all-settled", - ["./enumerator","./promise","./utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Enumerator = __dependency1__["default"]; - var makeSettledResult = __dependency1__.makeSettledResult; - var Promise = __dependency2__["default"]; - var o_create = __dependency3__.o_create; - - function AllSettled(Constructor, entries, label) { - this._superConstructor(Constructor, entries, false /* don't abort on reject */, label); - } - - AllSettled.prototype = o_create(Enumerator.prototype); - AllSettled.prototype._superConstructor = Enumerator; - AllSettled.prototype._makeResult = makeSettledResult; - AllSettled.prototype._validationError = function() { - return new Error('allSettled must be called with an array'); - }; - - /** - `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing - a fail-fast method, it waits until all the promises have returned and - shows you all the results. This is useful if you want to handle multiple - promises' failure states together as a set. - - Returns a promise that is fulfilled when all the given promises have been - settled. The return promise is fulfilled with an array of the states of - the promises passed into the `promises` array argument. - - Each state object will either indicate fulfillment or rejection, and - provide the corresponding value or reason. The states will take one of - the following formats: - - ```javascript - { state: 'fulfilled', value: value } - or - { state: 'rejected', reason: reason } - ``` - - Example: - - ```javascript - var promise1 = RSVP.Promise.resolve(1); - var promise2 = RSVP.Promise.reject(new Error('2')); - var promise3 = RSVP.Promise.reject(new Error('3')); - var promises = [ promise1, promise2, promise3 ]; - - RSVP.allSettled(promises).then(function(array){ - // array == [ - // { state: 'fulfilled', value: 1 }, - // { state: 'rejected', reason: Error }, - // { state: 'rejected', reason: Error } - // ] - // Note that for the second item, reason.message will be '2', and for the - // third item, reason.message will be '3'. - }, function(error) { - // Not run. (This block would only be called if allSettled had failed, - // for instance if passed an incorrect argument type.) - }); - ``` - - @method allSettled - @static - @for RSVP - @param {Array} promises - @param {String} label - optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled with an array of the settled - states of the constituent promises. - */ - - __exports__["default"] = function allSettled(entries, label) { - return new AllSettled(Promise, entries, label).promise; - } - }); -define("rsvp/all", - ["./promise","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - - /** - This is a convenient alias for `RSVP.Promise.all`. - - @method all - @static - @for RSVP - @param {Array} array Array of promises. - @param {String} label An optional label. This is useful - for tooling. - */ - __exports__["default"] = function all(array, label) { - return Promise.all(array, label); - } - }); -define("rsvp/asap", - ["exports"], - function(__exports__) { - "use strict"; - var len = 0; - - __exports__["default"] = function asap(callback, arg) { - queue[len] = callback; - queue[len + 1] = arg; - len += 2; - if (len === 2) { - // If len is 1, that means that we need to schedule an async flush. - // If additional callbacks are queued before the queue is flushed, they - // will be processed by this flush that we are scheduling. - scheduleFlush(); - } - } - - var browserGlobal = (typeof window !== 'undefined') ? window : {}; - var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; - - // test for web worker but not in IE10 - var isWorker = typeof Uint8ClampedArray !== 'undefined' && - typeof importScripts !== 'undefined' && - typeof MessageChannel !== 'undefined'; - - // node - function useNextTick() { - return function() { - process.nextTick(flush); - }; - } - - function useMutationObserver() { - var iterations = 0; - var observer = new BrowserMutationObserver(flush); - var node = document.createTextNode(''); - observer.observe(node, { characterData: true }); - - return function() { - node.data = (iterations = ++iterations % 2); - }; - } - - // web worker - function useMessageChannel() { - var channel = new MessageChannel(); - channel.port1.onmessage = flush; - return function () { - channel.port2.postMessage(0); - }; - } - - function useSetTimeout() { - return function() { - setTimeout(flush, 1); - }; - } - - var queue = new Array(1000); - function flush() { - for (var i = 0; i < len; i+=2) { - var callback = queue[i]; - var arg = queue[i+1]; - - callback(arg); - - queue[i] = undefined; - queue[i+1] = undefined; - } - - len = 0; - } - - var scheduleFlush; - - // Decide what async method to use to triggering processing of queued callbacks: - if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') { - scheduleFlush = useNextTick(); - } else if (BrowserMutationObserver) { - scheduleFlush = useMutationObserver(); - } else if (isWorker) { - scheduleFlush = useMessageChannel(); - } else { - scheduleFlush = useSetTimeout(); - } - }); -define("rsvp/config", - ["./events","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var EventTarget = __dependency1__["default"]; - - var config = { - instrument: false - }; - - EventTarget.mixin(config); - - function configure(name, value) { - if (name === 'onerror') { - // handle for legacy users that expect the actual - // error to be passed to their function added via - // `RSVP.configure('onerror', someFunctionHere);` - config.on('error', value); - return; - } - - if (arguments.length === 2) { - config[name] = value; - } else { - return config[name]; - } - } - - __exports__.config = config; - __exports__.configure = configure; - }); -define("rsvp/defer", - ["./promise","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - - /** - `RSVP.defer` returns an object similar to jQuery's `$.Deferred`. - `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s - interface. New code should use the `RSVP.Promise` constructor instead. - - The object returned from `RSVP.defer` is a plain object with three properties: - - * promise - an `RSVP.Promise`. - * reject - a function that causes the `promise` property on this object to - become rejected - * resolve - a function that causes the `promise` property on this object to - become fulfilled. - - Example: - - ```javascript - var deferred = RSVP.defer(); - - deferred.resolve("Success!"); - - defered.promise.then(function(value){ - // value here is "Success!" - }); - ``` - - @method defer - @static - @for RSVP - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Object} - */ - - __exports__["default"] = function defer(label) { - var deferred = { }; - - deferred.promise = new Promise(function(resolve, reject) { - deferred.resolve = resolve; - deferred.reject = reject; - }, label); - - return deferred; - } - }); -define("rsvp/enumerator", - ["./utils","./-internal","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var isArray = __dependency1__.isArray; - var isMaybeThenable = __dependency1__.isMaybeThenable; - - var noop = __dependency2__.noop; - var reject = __dependency2__.reject; - var fulfill = __dependency2__.fulfill; - var subscribe = __dependency2__.subscribe; - var FULFILLED = __dependency2__.FULFILLED; - var REJECTED = __dependency2__.REJECTED; - var PENDING = __dependency2__.PENDING; - - function makeSettledResult(state, position, value) { - if (state === FULFILLED) { - return { - state: 'fulfilled', - value: value - }; - } else { - return { - state: 'rejected', - reason: value - }; - } - } - - __exports__.makeSettledResult = makeSettledResult;function Enumerator(Constructor, input, abortOnReject, label) { - this._instanceConstructor = Constructor; - this.promise = new Constructor(noop, label); - this._abortOnReject = abortOnReject; - - if (this._validateInput(input)) { - this._input = input; - this.length = input.length; - this._remaining = input.length; - - this._init(); - - if (this.length === 0) { - fulfill(this.promise, this._result); - } else { - this.length = this.length || 0; - this._enumerate(); - if (this._remaining === 0) { - fulfill(this.promise, this._result); - } - } - } else { - reject(this.promise, this._validationError()); - } - } - - Enumerator.prototype._validateInput = function(input) { - return isArray(input); - }; - - Enumerator.prototype._validationError = function() { - return new Error('Array Methods must be provided an Array'); - }; - - Enumerator.prototype._init = function() { - this._result = new Array(this.length); - }; - - __exports__["default"] = Enumerator; - - Enumerator.prototype._enumerate = function() { - var length = this.length; - var promise = this.promise; - var input = this._input; - - for (var i = 0; promise._state === PENDING && i < length; i++) { - this._eachEntry(input[i], i); - } - }; - - Enumerator.prototype._eachEntry = function(entry, i) { - var c = this._instanceConstructor; - if (isMaybeThenable(entry)) { - if (entry.constructor === c && entry._state !== PENDING) { - entry._onerror = null; - this._settledAt(entry._state, i, entry._result); - } else { - this._willSettleAt(c.resolve(entry), i); - } - } else { - this._remaining--; - this._result[i] = this._makeResult(FULFILLED, i, entry); - } - }; - - Enumerator.prototype._settledAt = function(state, i, value) { - var promise = this.promise; - - if (promise._state === PENDING) { - this._remaining--; - - if (this._abortOnReject && state === REJECTED) { - reject(promise, value); - } else { - this._result[i] = this._makeResult(state, i, value); - } - } - - if (this._remaining === 0) { - fulfill(promise, this._result); - } - }; - - Enumerator.prototype._makeResult = function(state, i, value) { - return value; - }; - - Enumerator.prototype._willSettleAt = function(promise, i) { - var enumerator = this; - - subscribe(promise, undefined, function(value) { - enumerator._settledAt(FULFILLED, i, value); - }, function(reason) { - enumerator._settledAt(REJECTED, i, reason); - }); - }; - }); -define("rsvp/events", - ["exports"], - function(__exports__) { - "use strict"; - function indexOf(callbacks, callback) { - for (var i=0, l=callbacks.length; i 1; - }; - - RSVP.filter(promises, filterFn).then(function(result){ - // result is [ 2, 3 ] - }); - ``` - - If any of the `promises` given to `RSVP.filter` are rejected, the first promise - that is rejected will be given as an argument to the returned promise's - rejection handler. For example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.reject(new Error('2')); - var promise3 = RSVP.reject(new Error('3')); - var promises = [ promise1, promise2, promise3 ]; - - var filterFn = function(item){ - return item > 1; - }; - - RSVP.filter(promises, filterFn).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === '2' - }); - ``` - - `RSVP.filter` will also wait for any promises returned from `filterFn`. - For instance, you may want to fetch a list of users then return a subset - of those users based on some asynchronous operation: - - ```javascript - - var alice = { name: 'alice' }; - var bob = { name: 'bob' }; - var users = [ alice, bob ]; - - var promises = users.map(function(user){ - return RSVP.resolve(user); - }); - - var filterFn = function(user){ - // Here, Alice has permissions to create a blog post, but Bob does not. - return getPrivilegesForUser(user).then(function(privs){ - return privs.can_create_blog_post === true; - }); - }; - RSVP.filter(promises, filterFn).then(function(users){ - // true, because the server told us only Alice can create a blog post. - users.length === 1; - // false, because Alice is the only user present in `users` - users[0] === bob; - }); - ``` - - @method filter - @static - @for RSVP - @param {Array} promises - @param {Function} filterFn - function to be called on each resolved value to - filter the final results. - @param {String} label optional string describing the promise. Useful for - tooling. - @return {Promise} - */ - __exports__["default"] = function filter(promises, filterFn, label) { - return Promise.all(promises, label).then(function(values) { - if (!isFunction(filterFn)) { - throw new TypeError("You must pass a function as filter's second argument."); - } - - var length = values.length; - var filtered = new Array(length); - - for (var i = 0; i < length; i++) { - filtered[i] = filterFn(values[i]); - } - - return Promise.all(filtered, label).then(function(filtered) { - var results = new Array(length); - var newLength = 0; - - for (var i = 0; i < length; i++) { - if (filtered[i]) { - results[newLength] = values[i]; - newLength++; - } - } - - results.length = newLength; - - return results; - }); - }); - } - }); -define("rsvp/hash-settled", - ["./promise","./enumerator","./promise-hash","./utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var makeSettledResult = __dependency2__.makeSettledResult; - var PromiseHash = __dependency3__["default"]; - var Enumerator = __dependency2__["default"]; - var o_create = __dependency4__.o_create; - - function HashSettled(Constructor, object, label) { - this._superConstructor(Constructor, object, false, label); - } - - HashSettled.prototype = o_create(PromiseHash.prototype); - HashSettled.prototype._superConstructor = Enumerator; - HashSettled.prototype._makeResult = makeSettledResult; - - HashSettled.prototype._validationError = function() { - return new Error('hashSettled must be called with an object'); - }; - - /** - `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object - instead of an array for its `promises` argument. - - Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method, - but like `RSVP.allSettled`, `hashSettled` waits until all the - constituent promises have returned and then shows you all the results - with their states and values/reasons. This is useful if you want to - handle multiple promises' failure states together as a set. - - Returns a promise that is fulfilled when all the given promises have been - settled, or rejected if the passed parameters are invalid. - - The returned promise is fulfilled with a hash that has the same key names as - the `promises` object argument. If any of the values in the object are not - promises, they will be copied over to the fulfilled object and marked with state - 'fulfilled'. - - Example: - - ```javascript - var promises = { - myPromise: RSVP.Promise.resolve(1), - yourPromise: RSVP.Promise.resolve(2), - theirPromise: RSVP.Promise.resolve(3), - notAPromise: 4 - }; - - RSVP.hashSettled(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: { state: 'fulfilled', value: 1 }, - // yourPromise: { state: 'fulfilled', value: 2 }, - // theirPromise: { state: 'fulfilled', value: 3 }, - // notAPromise: { state: 'fulfilled', value: 4 } - // } - }); - ``` - - If any of the `promises` given to `RSVP.hash` are rejected, the state will - be set to 'rejected' and the reason for rejection provided. - - Example: - - ```javascript - var promises = { - myPromise: RSVP.Promise.resolve(1), - rejectedPromise: RSVP.Promise.reject(new Error('rejection')), - anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection')), - }; - - RSVP.hashSettled(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: { state: 'fulfilled', value: 1 }, - // rejectedPromise: { state: 'rejected', reason: Error }, - // anotherRejectedPromise: { state: 'rejected', reason: Error }, - // } - // Note that for rejectedPromise, reason.message == 'rejection', - // and for anotherRejectedPromise, reason.message == 'more rejection'. - }); - ``` - - An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that - are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype - chains. - - Example: - - ```javascript - function MyConstructor(){ - this.example = RSVP.Promise.resolve('Example'); - } - - MyConstructor.prototype = { - protoProperty: RSVP.Promise.resolve('Proto Property') - }; - - var myObject = new MyConstructor(); - - RSVP.hashSettled(myObject).then(function(hash){ - // protoProperty will not be present, instead you will just have an - // object that looks like: - // { - // example: { state: 'fulfilled', value: 'Example' } - // } - // - // hash.hasOwnProperty('protoProperty'); // false - // 'undefined' === typeof hash.protoProperty - }); - ``` - - @method hashSettled - @for RSVP - @param {Object} promises - @param {String} label optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when when all properties of `promises` - have been settled. - @static - */ - __exports__["default"] = function hashSettled(object, label) { - return new HashSettled(Promise, object, label).promise; - } - }); -define("rsvp/hash", - ["./promise","./promise-hash","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var PromiseHash = __dependency2__["default"]; - - /** - `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array - for its `promises` argument. - - Returns a promise that is fulfilled when all the given promises have been - fulfilled, or rejected if any of them become rejected. The returned promise - is fulfilled with a hash that has the same key names as the `promises` object - argument. If any of the values in the object are not promises, they will - simply be copied over to the fulfilled object. - - Example: - - ```javascript - var promises = { - myPromise: RSVP.resolve(1), - yourPromise: RSVP.resolve(2), - theirPromise: RSVP.resolve(3), - notAPromise: 4 - }; - - RSVP.hash(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: 1, - // yourPromise: 2, - // theirPromise: 3, - // notAPromise: 4 - // } - }); - ```` - - If any of the `promises` given to `RSVP.hash` are rejected, the first promise - that is rejected will be given as the reason to the rejection handler. - - Example: - - ```javascript - var promises = { - myPromise: RSVP.resolve(1), - rejectedPromise: RSVP.reject(new Error('rejectedPromise')), - anotherRejectedPromise: RSVP.reject(new Error('anotherRejectedPromise')), - }; - - RSVP.hash(promises).then(function(hash){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === 'rejectedPromise' - }); - ``` - - An important note: `RSVP.hash` is intended for plain JavaScript objects that - are just a set of keys and values. `RSVP.hash` will NOT preserve prototype - chains. - - Example: - - ```javascript - function MyConstructor(){ - this.example = RSVP.resolve('Example'); - } - - MyConstructor.prototype = { - protoProperty: RSVP.resolve('Proto Property') - }; - - var myObject = new MyConstructor(); - - RSVP.hash(myObject).then(function(hash){ - // protoProperty will not be present, instead you will just have an - // object that looks like: - // { - // example: 'Example' - // } - // - // hash.hasOwnProperty('protoProperty'); // false - // 'undefined' === typeof hash.protoProperty - }); - ``` - - @method hash - @static - @for RSVP - @param {Object} promises - @param {String} label optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all properties of `promises` - have been fulfilled, or rejected if any of them become rejected. - */ - __exports__["default"] = function hash(object, label) { - return new PromiseHash(Promise, object, label).promise; - } - }); -define("rsvp/instrument", - ["./config","./utils","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var config = __dependency1__.config; - var now = __dependency2__.now; - - var queue = []; - - __exports__["default"] = function instrument(eventName, promise, child) { - if (1 === queue.push({ - name: eventName, - payload: { - guid: promise._guidKey + promise._id, - eventName: eventName, - detail: promise._result, - childGuid: child && promise._guidKey + child._id, - label: promise._label, - timeStamp: now(), - stack: new Error(promise._label).stack - }})) { - - setTimeout(function() { - var entry; - for (var i = 0; i < queue.length; i++) { - entry = queue[i]; - config.trigger(entry.name, entry.payload); - } - queue.length = 0; - }, 50); - } - } - }); -define("rsvp/map", - ["./promise","./utils","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var isFunction = __dependency2__.isFunction; - - /** - `RSVP.map` is similar to JavaScript's native `map` method, except that it - waits for all promises to become fulfilled before running the `mapFn` on - each item in given to `promises`. `RSVP.map` returns a promise that will - become fulfilled with the result of running `mapFn` on the values the promises - become fulfilled with. - - For example: - - ```javascript - - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.resolve(2); - var promise3 = RSVP.resolve(3); - var promises = [ promise1, promise2, promise3 ]; - - var mapFn = function(item){ - return item + 1; - }; - - RSVP.map(promises, mapFn).then(function(result){ - // result is [ 2, 3, 4 ] - }); - ``` - - If any of the `promises` given to `RSVP.map` are rejected, the first promise - that is rejected will be given as an argument to the returned promise's - rejection handler. For example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.reject(new Error('2')); - var promise3 = RSVP.reject(new Error('3')); - var promises = [ promise1, promise2, promise3 ]; - - var mapFn = function(item){ - return item + 1; - }; - - RSVP.map(promises, mapFn).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === '2' - }); - ``` - - `RSVP.map` will also wait if a promise is returned from `mapFn`. For example, - say you want to get all comments from a set of blog posts, but you need - the blog posts first because they contain a url to those comments. - - ```javscript - - var mapFn = function(blogPost){ - // getComments does some ajax and returns an RSVP.Promise that is fulfilled - // with some comments data - return getComments(blogPost.comments_url); - }; - - // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled - // with some blog post data - RSVP.map(getBlogPosts(), mapFn).then(function(comments){ - // comments is the result of asking the server for the comments - // of all blog posts returned from getBlogPosts() - }); - ``` - - @method map - @static - @for RSVP - @param {Array} promises - @param {Function} mapFn function to be called on each fulfilled promise. - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled with the result of calling - `mapFn` on each fulfilled promise or value when they become fulfilled. - The promise will be rejected if any of the given `promises` become rejected. - @static - */ - __exports__["default"] = function map(promises, mapFn, label) { - return Promise.all(promises, label).then(function(values) { - if (!isFunction(mapFn)) { - throw new TypeError("You must pass a function as map's second argument."); - } - - var length = values.length; - var results = new Array(length); - - for (var i = 0; i < length; i++) { - results[i] = mapFn(values[i]); - } - - return Promise.all(results, label); - }); - } - }); -define("rsvp/node", - ["./promise","./-internal","./utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - var noop = __dependency2__.noop; - var resolve = __dependency2__.resolve; - var reject = __dependency2__.reject; - var isArray = __dependency3__.isArray; - - function Result() { - this.value = undefined; - } - - var ERROR = new Result(); - var GET_THEN_ERROR = new Result(); - - function getThen(obj) { - try { - return obj.then; - } catch(error) { - ERROR.value= error; - return ERROR; - } - } - - - function tryApply(f, s, a) { - try { - f.apply(s, a); - } catch(error) { - ERROR.value = error; - return ERROR; - } - } - - function makeObject(_, argumentNames) { - var obj = {}; - var name; - var i; - var length = _.length; - var args = new Array(length); - - for (var x = 0; x < length; x++) { - args[x] = _[x]; - } - - for (i = 0; i < argumentNames.length; i++) { - name = argumentNames[i]; - obj[name] = args[i + 1]; - } - - return obj; - } - - function arrayResult(_) { - var length = _.length; - var args = new Array(length - 1); - - for (var i = 1; i < length; i++) { - args[i - 1] = _[i]; - } - - return args; - } - - function wrapThenable(then, promise) { - return { - then: function(onFulFillment, onRejection) { - return then.call(promise, onFulFillment, onRejection); - } - }; - } - - /** - `RSVP.denodeify` takes a 'node-style' function and returns a function that - will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the - browser when you'd prefer to use promises over using callbacks. For example, - `denodeify` transforms the following: - - ```javascript - var fs = require('fs'); - - fs.readFile('myfile.txt', function(err, data){ - if (err) return handleError(err); - handleData(data); - }); - ``` - - into: - - ```javascript - var fs = require('fs'); - var readFile = RSVP.denodeify(fs.readFile); - - readFile('myfile.txt').then(handleData, handleError); - ``` - - If the node function has multiple success parameters, then `denodeify` - just returns the first one: - - ```javascript - var request = RSVP.denodeify(require('request')); - - request('http://example.com').then(function(res) { - // ... - }); - ``` - - However, if you need all success parameters, setting `denodeify`'s - second parameter to `true` causes it to return all success parameters - as an array: - - ```javascript - var request = RSVP.denodeify(require('request'), true); - - request('http://example.com').then(function(result) { - // result[0] -> res - // result[1] -> body - }); - ``` - - Or if you pass it an array with names it returns the parameters as a hash: - - ```javascript - var request = RSVP.denodeify(require('request'), ['res', 'body']); - - request('http://example.com').then(function(result) { - // result.res - // result.body - }); - ``` - - Sometimes you need to retain the `this`: - - ```javascript - var app = require('express')(); - var render = RSVP.denodeify(app.render.bind(app)); - ``` - - The denodified function inherits from the original function. It works in all - environments, except IE 10 and below. Consequently all properties of the original - function are available to you. However, any properties you change on the - denodeified function won't be changed on the original function. Example: - - ```javascript - var request = RSVP.denodeify(require('request')), - cookieJar = request.jar(); // <- Inheritance is used here - - request('http://example.com', {jar: cookieJar}).then(function(res) { - // cookieJar.cookies holds now the cookies returned by example.com - }); - ``` - - Using `denodeify` makes it easier to compose asynchronous operations instead - of using callbacks. For example, instead of: - - ```javascript - var fs = require('fs'); - - fs.readFile('myfile.txt', function(err, data){ - if (err) { ... } // Handle error - fs.writeFile('myfile2.txt', data, function(err){ - if (err) { ... } // Handle error - console.log('done') - }); - }); - ``` - - you can chain the operations together using `then` from the returned promise: - - ```javascript - var fs = require('fs'); - var readFile = RSVP.denodeify(fs.readFile); - var writeFile = RSVP.denodeify(fs.writeFile); - - readFile('myfile.txt').then(function(data){ - return writeFile('myfile2.txt', data); - }).then(function(){ - console.log('done') - }).catch(function(error){ - // Handle error - }); - ``` - - @method denodeify - @static - @for RSVP - @param {Function} nodeFunc a 'node-style' function that takes a callback as - its last argument. The callback expects an error to be passed as its first - argument (if an error occurred, otherwise null), and the value from the - operation as its second argument ('function(err, value){ }'). - @param {Boolean|Array} argumentNames An optional paramter that if set - to `true` causes the promise to fulfill with the callback's success arguments - as an array. This is useful if the node function has multiple success - paramters. If you set this paramter to an array with names, the promise will - fulfill with a hash with these names as keys and the success parameters as - values. - @return {Function} a function that wraps `nodeFunc` to return an - `RSVP.Promise` - @static - */ - __exports__["default"] = function denodeify(nodeFunc, options) { - var fn = function() { - var self = this; - var l = arguments.length; - var args = new Array(l + 1); - var arg; - var promiseInput = false; - - for (var i = 0; i < l; ++i) { - arg = arguments[i]; - - if (!promiseInput) { - // TODO: clean this up - promiseInput = needsPromiseInput(arg); - if (promiseInput === GET_THEN_ERROR) { - var p = new Promise(noop); - reject(p, GET_THEN_ERROR.value); - return p; - } else if (promiseInput && promiseInput !== true) { - arg = wrapThenable(promiseInput, arg); - } - } - args[i] = arg; - } - - var promise = new Promise(noop); - - args[l] = function(err, val) { - if (err) - reject(promise, err); - else if (options === undefined) - resolve(promise, val); - else if (options === true) - resolve(promise, arrayResult(arguments)); - else if (isArray(options)) - resolve(promise, makeObject(arguments, options)); - else - resolve(promise, val); - }; - - if (promiseInput) { - return handlePromiseInput(promise, args, nodeFunc, self); - } else { - return handleValueInput(promise, args, nodeFunc, self); - } - }; - - fn.__proto__ = nodeFunc; - - return fn; - } - - function handleValueInput(promise, args, nodeFunc, self) { - var result = tryApply(nodeFunc, self, args); - if (result === ERROR) { - reject(promise, result.value); - } - return promise; - } - - function handlePromiseInput(promise, args, nodeFunc, self){ - return Promise.all(args).then(function(args){ - var result = tryApply(nodeFunc, self, args); - if (result === ERROR) { - reject(promise, result.value); - } - return promise; - }); - } - - function needsPromiseInput(arg) { - if (arg && typeof arg === 'object') { - if (arg.constructor === Promise) { - return true; - } else { - return getThen(arg); - } - } else { - return false; - } - } - }); -define("rsvp/promise-hash", - ["./enumerator","./-internal","./utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - var Enumerator = __dependency1__["default"]; - var PENDING = __dependency2__.PENDING; - var o_create = __dependency3__.o_create; - - function PromiseHash(Constructor, object, label) { - this._superConstructor(Constructor, object, true, label); - } - - __exports__["default"] = PromiseHash; - - PromiseHash.prototype = o_create(Enumerator.prototype); - PromiseHash.prototype._superConstructor = Enumerator; - PromiseHash.prototype._init = function() { - this._result = {}; - }; - - PromiseHash.prototype._validateInput = function(input) { - return input && typeof input === 'object'; - }; - - PromiseHash.prototype._validationError = function() { - return new Error('Promise.hash must be called with an object'); - }; - - PromiseHash.prototype._enumerate = function() { - var promise = this.promise; - var input = this._input; - var results = []; - - for (var key in input) { - if (promise._state === PENDING && input.hasOwnProperty(key)) { - results.push({ - position: key, - entry: input[key] - }); - } - } - - var length = results.length; - this._remaining = length; - var result; - - for (var i = 0; promise._state === PENDING && i < length; i++) { - result = results[i]; - this._eachEntry(result.entry, result.position); - } - }; - }); -define("rsvp/promise", - ["./config","./instrument","./utils","./-internal","./promise/all","./promise/race","./promise/resolve","./promise/reject","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - var config = __dependency1__.config; - var instrument = __dependency2__["default"]; - - var isFunction = __dependency3__.isFunction; - var now = __dependency3__.now; - - var noop = __dependency4__.noop; - var subscribe = __dependency4__.subscribe; - var initializePromise = __dependency4__.initializePromise; - var invokeCallback = __dependency4__.invokeCallback; - var FULFILLED = __dependency4__.FULFILLED; - var REJECTED = __dependency4__.REJECTED; - - var all = __dependency5__["default"]; - var race = __dependency6__["default"]; - var Resolve = __dependency7__["default"]; - var Reject = __dependency8__["default"]; - - var guidKey = 'rsvp_' + now() + '-'; - var counter = 0; - - function needsResolver() { - throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); - } - - function needsNew() { - throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); - } - __exports__["default"] = Promise; - /** - Promise objects represent the eventual result of an asynchronous operation. The - primary way of interacting with a promise is through its `then` method, which - registers callbacks to receive either a promise’s eventual value or the reason - why the promise cannot be fulfilled. - - Terminology - ----------- - - - `promise` is an object or function with a `then` method whose behavior conforms to this specification. - - `thenable` is an object or function that defines a `then` method. - - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). - - `exception` is a value that is thrown using the throw statement. - - `reason` is a value that indicates why a promise was rejected. - - `settled` the final resting state of a promise, fulfilled or rejected. - - A promise can be in one of three states: pending, fulfilled, or rejected. - - Promises that are fulfilled have a fulfillment value and are in the fulfilled - state. Promises that are rejected have a rejection reason and are in the - rejected state. A fulfillment value is never a thenable. - - Promises can also be said to *resolve* a value. If this value is also a - promise, then the original promise's settled state will match the value's - settled state. So a promise that *resolves* a promise that rejects will - itself reject, and a promise that *resolves* a promise that fulfills will - itself fulfill. - - - Basic Usage: - ------------ - - ```js - var promise = new Promise(function(resolve, reject) { - // on success - resolve(value); - - // on failure - reject(reason); - }); - - promise.then(function(value) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Advanced Usage: - --------------- - - Promises shine when abstracting away asynchronous interactions such as - `XMLHttpRequest`s. - - ```js - function getJSON(url) { - return new Promise(function(resolve, reject){ - var xhr = new XMLHttpRequest(); - - xhr.open('GET', url); - xhr.onreadystatechange = handler; - xhr.responseType = 'json'; - xhr.setRequestHeader('Accept', 'application/json'); - xhr.send(); - - function handler() { - if (this.readyState === this.DONE) { - if (this.status === 200) { - resolve(this.response); - } else { - reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); - } - } - }; - }); - } - - getJSON('/posts.json').then(function(json) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Unlike callbacks, promises are great composable primitives. - - ```js - Promise.all([ - getJSON('/posts'), - getJSON('/comments') - ]).then(function(values){ - values[0] // => postsJSON - values[1] // => commentsJSON - - return values; - }); - ``` - - @class RSVP.Promise - @param {function} resolver - @param {String} label optional string for labeling the promise. - Useful for tooling. - @constructor - */ - function Promise(resolver, label) { - this._id = counter++; - this._label = label; - this._state = undefined; - this._result = undefined; - this._subscribers = []; - - if (config.instrument) { - instrument('created', this); - } - - if (noop !== resolver) { - if (!isFunction(resolver)) { - needsResolver(); - } - - if (!(this instanceof Promise)) { - needsNew(); - } - - initializePromise(this, resolver); - } - } - - Promise.cast = Resolve; // deprecated - Promise.all = all; - Promise.race = race; - Promise.resolve = Resolve; - Promise.reject = Reject; - - Promise.prototype = { - constructor: Promise, - - _guidKey: guidKey, - - _onerror: function (reason) { - config.trigger('error', reason); - }, - - /** - The primary way of interacting with a promise is through its `then` method, - which registers callbacks to receive either a promise's eventual value or the - reason why the promise cannot be fulfilled. - - ```js - findUser().then(function(user){ - // user is available - }, function(reason){ - // user is unavailable, and you are given the reason why - }); - ``` - - Chaining - -------- - - The return value of `then` is itself a promise. This second, 'downstream' - promise is resolved with the return value of the first promise's fulfillment - or rejection handler, or rejected if the handler throws an exception. - - ```js - findUser().then(function (user) { - return user.name; - }, function (reason) { - return 'default name'; - }).then(function (userName) { - // If `findUser` fulfilled, `userName` will be the user's name, otherwise it - // will be `'default name'` - }); - - findUser().then(function (user) { - throw new Error('Found user, but still unhappy'); - }, function (reason) { - throw new Error('`findUser` rejected and we're unhappy'); - }).then(function (value) { - // never reached - }, function (reason) { - // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. - // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. - }); - ``` - If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. - - ```js - findUser().then(function (user) { - throw new PedagogicalException('Upstream error'); - }).then(function (value) { - // never reached - }).then(function (value) { - // never reached - }, function (reason) { - // The `PedgagocialException` is propagated all the way down to here - }); - ``` - - Assimilation - ------------ - - Sometimes the value you want to propagate to a downstream promise can only be - retrieved asynchronously. This can be achieved by returning a promise in the - fulfillment or rejection handler. The downstream promise will then be pending - until the returned promise is settled. This is called *assimilation*. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // The user's comments are now available - }); - ``` - - If the assimliated promise rejects, then the downstream promise will also reject. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // If `findCommentsByAuthor` fulfills, we'll have the value here - }, function (reason) { - // If `findCommentsByAuthor` rejects, we'll have the reason here - }); - ``` - - Simple Example - -------------- - - Synchronous Example - - ```javascript - var result; - - try { - result = findResult(); - // success - } catch(reason) { - // failure - } - ``` - - Errback Example - - ```js - findResult(function(result, err){ - if (err) { - // failure - } else { - // success - } - }); - ``` - - Promise Example; - - ```javascript - findResult().then(function(result){ - // success - }, function(reason){ - // failure - }); - ``` - - Advanced Example - -------------- - - Synchronous Example - - ```javascript - var author, books; - - try { - author = findAuthor(); - books = findBooksByAuthor(author); - // success - } catch(reason) { - // failure - } - ``` - - Errback Example - - ```js - - function foundBooks(books) { - - } - - function failure(reason) { - - } - - findAuthor(function(author, err){ - if (err) { - failure(err); - // failure - } else { - try { - findBoooksByAuthor(author, function(books, err) { - if (err) { - failure(err); - } else { - try { - foundBooks(books); - } catch(reason) { - failure(reason); - } - } - }); - } catch(error) { - failure(err); - } - // success - } - }); - ``` - - Promise Example; - - ```javascript - findAuthor(). - then(findBooksByAuthor). - then(function(books){ - // found books - }).catch(function(reason){ - // something went wrong - }); - ``` - - @method then - @param {Function} onFulfilled - @param {Function} onRejected - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - then: function(onFulfillment, onRejection, label) { - var parent = this; - var state = parent._state; - - if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) { - if (config.instrument) { - instrument('chained', this, this); - } - return this; - } - - parent._onerror = null; - - var child = new this.constructor(noop, label); - var result = parent._result; - - if (config.instrument) { - instrument('chained', parent, child); - } - - if (state) { - var callback = arguments[state - 1]; - config.async(function(){ - invokeCallback(state, child, callback, result); - }); - } else { - subscribe(parent, child, onFulfillment, onRejection); - } - - return child; - }, - - /** - `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same - as the catch block of a try/catch statement. - - ```js - function findAuthor(){ - throw new Error('couldn't find that author'); - } - - // synchronous - try { - findAuthor(); - } catch(reason) { - // something went wrong - } - - // async with promises - findAuthor().catch(function(reason){ - // something went wrong - }); - ``` - - @method catch - @param {Function} onRejection - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - 'catch': function(onRejection, label) { - return this.then(null, onRejection, label); - }, - - /** - `finally` will be invoked regardless of the promise's fate just as native - try/catch/finally behaves - - Synchronous example: - - ```js - findAuthor() { - if (Math.random() > 0.5) { - throw new Error(); - } - return new Author(); - } - - try { - return findAuthor(); // succeed or fail - } catch(error) { - return findOtherAuther(); - } finally { - // always runs - // doesn't affect the return value - } - ``` - - Asynchronous example: - - ```js - findAuthor().catch(function(reason){ - return findOtherAuther(); - }).finally(function(){ - // author was either found, or not - }); - ``` - - @method finally - @param {Function} callback - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} - */ - 'finally': function(callback, label) { - var constructor = this.constructor; - - return this.then(function(value) { - return constructor.resolve(callback()).then(function(){ - return value; - }); - }, function(reason) { - return constructor.resolve(callback()).then(function(){ - throw reason; - }); - }, label); - } - }; - }); -define("rsvp/promise/all", - ["../enumerator","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Enumerator = __dependency1__["default"]; - - /** - `RSVP.Promise.all` accepts an array of promises, and returns a new promise which - is fulfilled with an array of fulfillment values for the passed promises, or - rejected with the reason of the first passed promise to be rejected. It casts all - elements of the passed iterable to promises as it runs this algorithm. - - Example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.resolve(2); - var promise3 = RSVP.resolve(3); - var promises = [ promise1, promise2, promise3 ]; - - RSVP.Promise.all(promises).then(function(array){ - // The array here would be [ 1, 2, 3 ]; - }); - ``` - - If any of the `promises` given to `RSVP.all` are rejected, the first promise - that is rejected will be given as an argument to the returned promises's - rejection handler. For example: - - Example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.reject(new Error("2")); - var promise3 = RSVP.reject(new Error("3")); - var promises = [ promise1, promise2, promise3 ]; - - RSVP.Promise.all(promises).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(error) { - // error.message === "2" - }); - ``` - - @method all - @static - @param {Array} entries array of promises - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all `promises` have been - fulfilled, or rejected if any of them become rejected. - @static - */ - __exports__["default"] = function all(entries, label) { - return new Enumerator(this, entries, true /* abort on reject */, label).promise; - } - }); -define("rsvp/promise/race", - ["../utils","../-internal","exports"], - function(__dependency1__, __dependency2__, __exports__) { - "use strict"; - var isArray = __dependency1__.isArray; - - var noop = __dependency2__.noop; - var resolve = __dependency2__.resolve; - var reject = __dependency2__.reject; - var subscribe = __dependency2__.subscribe; - var PENDING = __dependency2__.PENDING; - - /** - `RSVP.Promise.race` returns a new promise which is settled in the same way as the - first passed promise to settle. - - Example: - - ```javascript - var promise1 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - var promise2 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 2'); - }, 100); - }); - - RSVP.Promise.race([promise1, promise2]).then(function(result){ - // result === 'promise 2' because it was resolved before promise1 - // was resolved. - }); - ``` - - `RSVP.Promise.race` is deterministic in that only the state of the first - settled promise matters. For example, even if other promises given to the - `promises` array argument are resolved, but the first settled promise has - become rejected before the other promises became fulfilled, the returned - promise will become rejected: - - ```javascript - var promise1 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - var promise2 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - reject(new Error('promise 2')); - }, 100); - }); - - RSVP.Promise.race([promise1, promise2]).then(function(result){ - // Code here never runs - }, function(reason){ - // reason.message === 'promise 2' because promise 2 became rejected before - // promise 1 became fulfilled - }); - ``` - - An example real-world use case is implementing timeouts: - - ```javascript - RSVP.Promise.race([ajax('foo.json'), timeout(5000)]) - ``` - - @method race - @static - @param {Array} promises array of promises to observe - @param {String} label optional string for describing the promise returned. - Useful for tooling. - @return {Promise} a promise which settles in the same way as the first passed - promise to settle. - */ - __exports__["default"] = function race(entries, label) { - /*jshint validthis:true */ - var Constructor = this; - - var promise = new Constructor(noop, label); - - if (!isArray(entries)) { - reject(promise, new TypeError('You must pass an array to race.')); - return promise; - } - - var length = entries.length; - - function onFulfillment(value) { - resolve(promise, value); - } - - function onRejection(reason) { - reject(promise, reason); - } - - for (var i = 0; promise._state === PENDING && i < length; i++) { - subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); - } - - return promise; - } - }); -define("rsvp/promise/reject", - ["../-internal","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var noop = __dependency1__.noop; - var _reject = __dependency1__.reject; - - /** - `RSVP.Promise.reject` returns a promise rejected with the passed `reason`. - It is shorthand for the following: - - ```javascript - var promise = new RSVP.Promise(function(resolve, reject){ - reject(new Error('WHOOPS')); - }); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - var promise = RSVP.Promise.reject(new Error('WHOOPS')); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - @method reject - @static - @param {Any} reason value that the returned promise will be rejected with. - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. - */ - __exports__["default"] = function reject(reason, label) { - /*jshint validthis:true */ - var Constructor = this; - var promise = new Constructor(noop, label); - _reject(promise, reason); - return promise; - } - }); -define("rsvp/promise/resolve", - ["../-internal","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var noop = __dependency1__.noop; - var _resolve = __dependency1__.resolve; - - /** - `RSVP.Promise.resolve` returns a promise that will become resolved with the - passed `value`. It is shorthand for the following: - - ```javascript - var promise = new RSVP.Promise(function(resolve, reject){ - resolve(1); - }); - - promise.then(function(value){ - // value === 1 - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - var promise = RSVP.Promise.resolve(1); - - promise.then(function(value){ - // value === 1 - }); - ``` - - @method resolve - @static - @param {Any} value value that the returned promise will be resolved with - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` - */ - __exports__["default"] = function resolve(object, label) { - /*jshint validthis:true */ - var Constructor = this; - - if (object && typeof object === 'object' && object.constructor === Constructor) { - return object; - } - - var promise = new Constructor(noop, label); - _resolve(promise, object); - return promise; - } - }); -define("rsvp/race", - ["./promise","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - - /** - This is a convenient alias for `RSVP.Promise.race`. - - @method race - @static - @for RSVP - @param {Array} array Array of promises. - @param {String} label An optional label. This is useful - for tooling. - */ - __exports__["default"] = function race(array, label) { - return Promise.race(array, label); - } - }); -define("rsvp/reject", - ["./promise","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - - /** - This is a convenient alias for `RSVP.Promise.reject`. - - @method reject - @static - @for RSVP - @param {Any} reason value that the returned promise will be rejected with. - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. - */ - __exports__["default"] = function reject(reason, label) { - return Promise.reject(reason, label); - } - }); -define("rsvp/resolve", - ["./promise","exports"], - function(__dependency1__, __exports__) { - "use strict"; - var Promise = __dependency1__["default"]; - - /** - This is a convenient alias for `RSVP.Promise.resolve`. - - @method resolve - @static - @for RSVP - @param {Any} value value that the returned promise will be resolved with - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` - */ - __exports__["default"] = function resolve(value, label) { - return Promise.resolve(value, label); - } - }); -define("rsvp/rethrow", - ["exports"], - function(__exports__) { - "use strict"; - /** - `RSVP.rethrow` will rethrow an error on the next turn of the JavaScript event - loop in order to aid debugging. - - Promises A+ specifies that any exceptions that occur with a promise must be - caught by the promises implementation and bubbled to the last handler. For - this reason, it is recommended that you always specify a second rejection - handler function to `then`. However, `RSVP.rethrow` will throw the exception - outside of the promise, so it bubbles up to your console if in the browser, - or domain/cause uncaught exception in Node. `rethrow` will also throw the - error again so the error can be handled by the promise per the spec. - - ```javascript - function throws(){ - throw new Error('Whoops!'); - } - - var promise = new RSVP.Promise(function(resolve, reject){ - throws(); - }); - - promise.catch(RSVP.rethrow).then(function(){ - // Code here doesn't run because the promise became rejected due to an - // error! - }, function (err){ - // handle the error here - }); - ``` - - The 'Whoops' error will be thrown on the next turn of the event loop - and you can watch for it in your console. You can also handle it using a - rejection handler given to `.then` or `.catch` on the returned promise. - - @method rethrow - @static - @for RSVP - @param {Error} reason reason the promise became rejected. - @throws Error - @static - */ - __exports__["default"] = function rethrow(reason) { - setTimeout(function() { - throw reason; - }); - throw reason; - } - }); -define("rsvp/utils", - ["exports"], - function(__exports__) { - "use strict"; - function objectOrFunction(x) { - return typeof x === 'function' || (typeof x === 'object' && x !== null); - } - - __exports__.objectOrFunction = objectOrFunction;function isFunction(x) { - return typeof x === 'function'; - } - - __exports__.isFunction = isFunction;function isMaybeThenable(x) { - return typeof x === 'object' && x !== null; - } - - __exports__.isMaybeThenable = isMaybeThenable;var _isArray; - if (!Array.isArray) { - _isArray = function (x) { - return Object.prototype.toString.call(x) === '[object Array]'; - }; - } else { - _isArray = Array.isArray; - } - - var isArray = _isArray; - __exports__.isArray = isArray; - // Date.now is not available in browsers < IE9 - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility - var now = Date.now || function() { return new Date().getTime(); }; - __exports__.now = now; - function F() { } - - var o_create = (Object.create || function (o) { - if (arguments.length > 1) { - throw new Error('Second argument not supported'); - } - if (typeof o !== 'object') { - throw new TypeError('Argument must be an object'); - } - F.prototype = o; - return new F(); - }); - __exports__.o_create = o_create; - }); -requireModule("ember"); - -})(); \ No newline at end of file diff --git a/httpclient/.classpath b/httpclient/.classpath deleted file mode 100644 index 8ebf6d9c31..0000000000 --- a/httpclient/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/httpclient/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/httpclient/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/httpclient/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/httpclient/.project b/httpclient/.project deleted file mode 100644 index 83c3ed0493..0000000000 --- a/httpclient/.project +++ /dev/null @@ -1,36 +0,0 @@ - - - httpclient - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/httpclient/.settings/.jsdtscope b/httpclient/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/httpclient/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/httpclient/.settings/org.eclipse.jdt.core.prefs b/httpclient/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/httpclient/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/httpclient/.settings/org.eclipse.jdt.ui.prefs b/httpclient/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/httpclient/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/httpclient/.settings/org.eclipse.m2e.core.prefs b/httpclient/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/httpclient/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/httpclient/.settings/org.eclipse.m2e.wtp.prefs b/httpclient/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/httpclient/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/httpclient/.settings/org.eclipse.wst.common.component b/httpclient/.settings/org.eclipse.wst.common.component deleted file mode 100644 index e98377cb0f..0000000000 --- a/httpclient/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/httpclient/.settings/org.eclipse.wst.common.project.facet.core.xml b/httpclient/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f4ef8aa0a5..0000000000 --- a/httpclient/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/httpclient/.settings/org.eclipse.wst.jsdt.ui.superType.container b/httpclient/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/httpclient/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/httpclient/.settings/org.eclipse.wst.jsdt.ui.superType.name b/httpclient/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/httpclient/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/httpclient/.settings/org.eclipse.wst.validation.prefs b/httpclient/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index cacf5451ae..0000000000 --- a/httpclient/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,14 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.303.v201202090300 -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/httpclient/.settings/org.eclipse.wst.ws.service.policy.prefs b/httpclient/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/httpclient/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/httpclient/.springBeans b/httpclient/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/httpclient/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/httpclient/README.md b/httpclient/README.md index 529ac754f8..a848edfea6 100644 --- a/httpclient/README.md +++ b/httpclient/README.md @@ -1,16 +1,21 @@ ========= - ## HttpClient 4.x Cookbooks and Examples +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + ### Relevant Articles: -- [HttpClient 4 – Send Custom Cookie](http://www.baeldung.com/httpclient-4-cookies) -- [HttpClient 4 – Get the Status Code](http://www.baeldung.com/httpclient-status-code) -- [HttpClient 4 – Cancel / Abort Request](http://www.baeldung.com/httpclient-cancel-request) +- [HttpClient 4 – Send Custom Cookie](http://www.baeldung.com/httpclient-4-cookies) +- [HttpClient 4 – Get the Status Code](http://www.baeldung.com/httpclient-status-code) +- [HttpClient 4 – Cancel / Abort Request](http://www.baeldung.com/httpclient-cancel-request) - [HttpClient 4 Cookbook](http://www.baeldung.com/httpclient4) - [Unshorten URLs with HttpClient](http://www.baeldung.com/unshorten-url-httpclient) - [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl) -- [HttpClient 4 – Follow Redirects for POST](http://www.baeldung.com/httpclient-redirect-on-http-post) -- [HttpClient – Set Custom Header](http://www.baeldung.com/httpclient-custom-http-header) +- [HttpClient 4 – Follow Redirects for POST](http://www.baeldung.com/httpclient-redirect-on-http-post) +- [HttpClient – Set Custom Header](http://www.baeldung.com/httpclient-custom-http-header) - [HttpClient Basic Authentication](http://www.baeldung.com/httpclient-4-basic-authentication) +- [Multipart Upload with HttpClient 4](http://www.baeldung.com/httpclient-multipart-upload) +- [HttpAsyncClient Tutorial](http://www.baeldung.com/httpasyncclient-tutorial) +- [HttpClient 4 Tutorial](http://www.baeldung.com/httpclient-guide) diff --git a/httpclient/pom.xml b/httpclient/pom.xml index 0098c40d52..66b2076852 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung httpclient 0.1-SNAPSHOT @@ -148,13 +148,9 @@ - - 4.1.5.RELEASE - 3.2.5.RELEASE - - 4.3.10.Final - 5.1.35 + 4.3.11.Final + 5.1.38 1.7.13 @@ -175,14 +171,14 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.14 + 1.4.18 diff --git a/httpclient/src/test/java/org/baeldung/httpclient/HttpClientMultipartTest.java b/httpclient/src/test/java/org/baeldung/httpclient/HttpClientMultipartTest.java index 687a248490..371657af62 100644 --- a/httpclient/src/test/java/org/baeldung/httpclient/HttpClientMultipartTest.java +++ b/httpclient/src/test/java/org/baeldung/httpclient/HttpClientMultipartTest.java @@ -79,18 +79,22 @@ public class HttpClientMultipartTest { @Test public final void givenFileandMultipleTextParts_whenUploadwithAddPart_thenNoExceptions() throws IOException { final URL url = Thread.currentThread().getContextClassLoader().getResource("uploads/" + TEXTFILENAME); + final File file = new File(url.getPath()); final FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY); final StringBody stringBody1 = new StringBody("This is message 1", ContentType.MULTIPART_FORM_DATA); final StringBody stringBody2 = new StringBody("This is message 2", ContentType.MULTIPART_FORM_DATA); + // final MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.addPart("upfile", fileBody); builder.addPart("text1", stringBody1); builder.addPart("text2", stringBody2); final HttpEntity entity = builder.build(); + // post.setEntity(entity); response = client.execute(post); + final int statusCode = response.getStatusLine().getStatusCode(); final String responseString = getContent(); final String contentTypeInHeader = getContentTypeHeader(); @@ -124,7 +128,7 @@ public class HttpClientMultipartTest { } @Test - public final void givenFileandInputStreamandText_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoException() throws ClientProtocolException, IOException { + public final void givenFileAndInputStreamandText_whenUploadwithAddBinaryBodyandAddTextBody_ThenNoException() throws ClientProtocolException, IOException { final URL url = Thread.currentThread().getContextClassLoader().getResource("uploads/" + ZIPFILENAME); final URL url2 = Thread.currentThread().getContextClassLoader().getResource("uploads/" + IMAGEFILENAME); final InputStream inputStream = new FileInputStream(url.getPath()); diff --git a/httpclient/src/test/java/org/baeldung/httpclient/SandboxTest.java b/httpclient/src/test/java/org/baeldung/httpclient/SandboxTest.java new file mode 100644 index 0000000000..dc1a206f0d --- /dev/null +++ b/httpclient/src/test/java/org/baeldung/httpclient/SandboxTest.java @@ -0,0 +1,188 @@ +package org.baeldung.httpclient; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.apache.http.Header; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.AuthenticationException; +import org.apache.http.auth.MalformedChallengeException; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.AuthCache; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.CookieStore; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.auth.DigestScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.cookie.BasicClientCookie; +import org.apache.http.util.EntityUtils; +import org.junit.Ignore; +import org.junit.Test; + +public class SandboxTest { + + // original example + @Ignore + @Test + public final void whenInterestingDigestAuthScenario_then401UnAuthorized() throws AuthenticationException, ClientProtocolException, IOException, MalformedChallengeException { + final HttpHost targetHost = new HttpHost("httpbin.org", 80, "http"); + + // set up the credentials to run agains the server + final CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new UsernamePasswordCredentials("user", "passwd")); + + // We need a first run to get a 401 to seed the digest auth + + // Make a client using those creds + final CloseableHttpClient client = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build(); + + // And make a call to the URL we are after + final HttpGet httpget = new HttpGet("http://httpbin.org/digest-auth/auth/user/passwd"); + + // Create a context to use + final HttpClientContext context = HttpClientContext.create(); + + // Get a response from the sever (expect a 401!) + final HttpResponse authResponse = client.execute(targetHost, httpget, context); + + // Pull out the auth header that came back from the server + final Header challenge = authResponse.getHeaders("WWW-Authenticate")[0]; + + // Lets use a digest scheme to solve it + final DigestScheme digest = new DigestScheme(); + digest.processChallenge(challenge); + + // Make a header with the solution based upon user/password and what the digest got out of the initial 401 reponse + final Header solution = digest.authenticate(new UsernamePasswordCredentials("user", "passwd"), httpget, context); + + // Need an auth cache to use the new digest we made + final AuthCache authCache = new BasicAuthCache(); + authCache.put(targetHost, digest); + + // Add the authCache and thus solved digest to the context + context.setAuthCache(authCache); + + // Pimp up our http get with the solved header made by the digest + httpget.addHeader(solution); + + // use it! + System.out.println("Executing request " + httpget.getRequestLine() + " to target " + targetHost); + + for (int i = 0; i < 3; i++) { + final CloseableHttpResponse responseGood = client.execute(targetHost, httpget, context); + + try { + System.out.println("----------------------------------------"); + System.out.println(responseGood.getStatusLine()); + System.out.println(EntityUtils.toString(responseGood.getEntity())); + } finally { + responseGood.close(); + } + } + } + + @Test + public final void whenInterestingDigestAuthScenario_then200OK() throws AuthenticationException, ClientProtocolException, IOException, MalformedChallengeException { + final HttpHost targetHost = new HttpHost("httpbin.org", 80, "http"); + + // set up the credentials to run agains the server + final CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()), new UsernamePasswordCredentials("user", "passwd")); + + // This endpoint need fake cookie to work properly + final CookieStore cookieStore = new BasicCookieStore(); + final BasicClientCookie cookie = new BasicClientCookie("fake", "fake_value"); + cookie.setDomain("httpbin.org"); + cookie.setPath("/"); + cookieStore.addCookie(cookie); + + // Make a client using those creds + final CloseableHttpClient client = HttpClients.custom().setDefaultCookieStore(cookieStore).setDefaultCredentialsProvider(credsProvider).build(); + + // And make a call to the URL we are after + final HttpGet httpget = new HttpGet("http://httpbin.org/digest-auth/auth/user/passwd"); + + // Create a context to use + final HttpClientContext context = HttpClientContext.create(); + + // Get a response from the sever (401 implicitly) + final HttpResponse authResponse = client.execute(targetHost, httpget, context); + assertEquals(200, authResponse.getStatusLine().getStatusCode()); + + // HttpClient will use cached digest parameters for future requests + System.out.println("Executing request " + httpget.getRequestLine() + " to target " + targetHost); + + for (int i = 0; i < 3; i++) { + final CloseableHttpResponse responseGood = client.execute(targetHost, httpget, context); + + try { + System.out.println("----------------------------------------"); + System.out.println(responseGood.getStatusLine()); + assertEquals(200, responseGood.getStatusLine().getStatusCode()); + } finally { + responseGood.close(); + } + } + client.close(); + } + + // This test needs module spring-security-rest-digest-auth to be running + @Test + public final void whenWeKnowDigestParameters_thenNo401Status() throws AuthenticationException, ClientProtocolException, IOException, MalformedChallengeException { + final HttpHost targetHost = new HttpHost("localhost", 8080, "http"); + + final CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("user1", "user1Pass")); + + final CloseableHttpClient client = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build(); + + final HttpGet httpget = new HttpGet("http://localhost:8080/spring-security-rest-digest-auth/api/foos/1"); + + final HttpClientContext context = HttpClientContext.create(); + // == make it preemptive + final AuthCache authCache = new BasicAuthCache(); + final DigestScheme digestAuth = new DigestScheme(); + digestAuth.overrideParamter("realm", "Custom Realm Name"); + digestAuth.overrideParamter("nonce", "nonce value goes here"); + authCache.put(targetHost, digestAuth); + context.setAuthCache(authCache); + // == end + System.out.println("Executing The Request knowing the digest parameters ==== "); + final HttpResponse authResponse = client.execute(targetHost, httpget, context); + assertEquals(200, authResponse.getStatusLine().getStatusCode()); + client.close(); + } + + // This test needs module spring-security-rest-digest-auth to be running + @Test + public final void whenDoNotKnowParameters_thenOnlyOne401() throws AuthenticationException, ClientProtocolException, IOException, MalformedChallengeException { + final HttpClientContext context = HttpClientContext.create(); + final HttpHost targetHost = new HttpHost("localhost", 8080, "http"); + final CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("user1", "user1Pass")); + final CloseableHttpClient client = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build(); + + final HttpGet httpget = new HttpGet("http://localhost:8080/spring-security-rest-digest-auth/api/foos/1"); + System.out.println("Executing The Request NOT knowing the digest parameters ==== "); + final HttpResponse tempResponse = client.execute(targetHost, httpget, context); + assertEquals(200, tempResponse.getStatusLine().getStatusCode()); + + for (int i = 0; i < 3; i++) { + System.out.println("No more Challenges or 401"); + final CloseableHttpResponse authResponse = client.execute(targetHost, httpget, context); + assertEquals(200, authResponse.getStatusLine().getStatusCode()); + authResponse.close(); + } + client.close(); + } +} diff --git a/hystrix/.gitignore b/hystrix/.gitignore new file mode 100644 index 0000000000..b092c8122f --- /dev/null +++ b/hystrix/.gitignore @@ -0,0 +1,12 @@ +*.class + +#folders# +/target +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear +*.iml \ No newline at end of file diff --git a/hystrix/pom.xml b/hystrix/pom.xml new file mode 100644 index 0000000000..42828e1c97 --- /dev/null +++ b/hystrix/pom.xml @@ -0,0 +1,121 @@ + + + 4.0.0 + com.baeldung + hystrix + 1.0 + hystrix + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + + + 1.8 + + + 1.5.4 + 0.20.7 + + + 1.3 + 4.12 + + + 3.5.1 + 2.6 + 2.19.1 + 2.7 + 1.3.16 + 1.4.3 + 1.4.0.RELEASE + + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-aop + + + com.netflix.hystrix + hystrix-core + ${hystrix-core.version} + + + com.netflix.hystrix + hystrix-metrics-event-stream + ${hystrix-metrics-event-stream.version} + + + + com.netflix.rxjava + rxjava-core + ${rxjava-core.version} + + + org.hamcrest + hamcrest-all + ${hamcrest-all.version} + test + + + junit + junit + ${junit.version} + test + + + org.springframework + spring-test + test + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot-starter-test.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + + + + + diff --git a/hystrix/src/main/java/com/baeldung/hystrix/AppConfig.java b/hystrix/src/main/java/com/baeldung/hystrix/AppConfig.java new file mode 100644 index 0000000000..8b11ac99c3 --- /dev/null +++ b/hystrix/src/main/java/com/baeldung/hystrix/AppConfig.java @@ -0,0 +1,20 @@ +package com.baeldung.hystrix; + +import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class AppConfig { + + public static void main(String[] args) { + SpringApplication.run(AppConfig.class, args); + } + + @Bean + public ServletRegistrationBean adminServletRegistrationBean() { + return new ServletRegistrationBean(new HystrixMetricsStreamServlet(), "/hystrix.stream"); + } +} diff --git a/hystrix/src/main/java/com/baeldung/hystrix/CommandHelloWorld.java b/hystrix/src/main/java/com/baeldung/hystrix/CommandHelloWorld.java new file mode 100644 index 0000000000..4f2b0c38c3 --- /dev/null +++ b/hystrix/src/main/java/com/baeldung/hystrix/CommandHelloWorld.java @@ -0,0 +1,19 @@ +package com.baeldung.hystrix; + +import com.netflix.hystrix.HystrixCommand; +import com.netflix.hystrix.HystrixCommandGroupKey; + +class CommandHelloWorld extends HystrixCommand { + + private final String name; + + CommandHelloWorld(String name) { + super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")); + this.name = name; + } + + @Override + protected String run() { + return "Hello " + name + "!"; + } +} diff --git a/hystrix/src/main/java/com/baeldung/hystrix/HystrixAspect.java b/hystrix/src/main/java/com/baeldung/hystrix/HystrixAspect.java new file mode 100644 index 0000000000..3a650c2f4f --- /dev/null +++ b/hystrix/src/main/java/com/baeldung/hystrix/HystrixAspect.java @@ -0,0 +1,83 @@ +package com.baeldung.hystrix; + +import com.netflix.hystrix.*; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +@Component +@Aspect +public class HystrixAspect { + + private HystrixCommand.Setter config; + private HystrixCommandProperties.Setter commandProperties; + private HystrixThreadPoolProperties.Setter threadPoolProperties; + + @Value("${remoteservice.command.execution.timeout}") + private int executionTimeout; + + @Value("${remoteservice.command.sleepwindow}") + private int sleepWindow; + + @Value("${remoteservice.command.threadpool.maxsize}") + private int maxThreadCount; + + @Value("${remoteservice.command.threadpool.coresize}") + private int coreThreadCount; + + @Value("${remoteservice.command.task.queue.size}") + private int queueCount; + + @Value("${remoteservice.command.group.key}") + private String groupKey; + + @Value("${remoteservice.command.key}") + private String key; + + + @Around("@annotation(com.baeldung.hystrix.HystrixCircuitBreaker)") + public Object circuitBreakerAround(final ProceedingJoinPoint aJoinPoint) { + return new RemoteServiceCommand(config, aJoinPoint).execute(); + } + + @PostConstruct + private void setup() { + this.config = HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey)); + this.config = config.andCommandKey(HystrixCommandKey.Factory.asKey(key)); + + this.commandProperties = HystrixCommandProperties.Setter(); + this.commandProperties.withExecutionTimeoutInMilliseconds(executionTimeout); + this.commandProperties.withCircuitBreakerSleepWindowInMilliseconds(sleepWindow); + + this.threadPoolProperties = HystrixThreadPoolProperties.Setter(); + this.threadPoolProperties.withMaxQueueSize(maxThreadCount).withCoreSize(coreThreadCount).withMaxQueueSize(queueCount); + + this.config.andCommandPropertiesDefaults(commandProperties); + this.config.andThreadPoolPropertiesDefaults(threadPoolProperties); + } + + private static class RemoteServiceCommand extends HystrixCommand { + + private final ProceedingJoinPoint joinPoint; + + RemoteServiceCommand(final Setter config, final ProceedingJoinPoint joinPoint) { + super(config); + this.joinPoint = joinPoint; + } + + @Override + protected String run() throws Exception { + try { + return (String) joinPoint.proceed(); + } catch (final Throwable th) { + throw new Exception(th); + } + + } + } + +} diff --git a/hystrix/src/main/java/com/baeldung/hystrix/HystrixCircuitBreaker.java b/hystrix/src/main/java/com/baeldung/hystrix/HystrixCircuitBreaker.java new file mode 100644 index 0000000000..e7c0694a7b --- /dev/null +++ b/hystrix/src/main/java/com/baeldung/hystrix/HystrixCircuitBreaker.java @@ -0,0 +1,11 @@ +package com.baeldung.hystrix; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface HystrixCircuitBreaker { +} diff --git a/hystrix/src/main/java/com/baeldung/hystrix/HystrixController.java b/hystrix/src/main/java/com/baeldung/hystrix/HystrixController.java new file mode 100644 index 0000000000..69d9e30ff8 --- /dev/null +++ b/hystrix/src/main/java/com/baeldung/hystrix/HystrixController.java @@ -0,0 +1,22 @@ +package com.baeldung.hystrix; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HystrixController { + + @Autowired + private SpringExistingClient client; + + @RequestMapping("/withHystrix") + public String withHystrix() throws InterruptedException{ + return client.invokeRemoteServiceWithHystrix(); + } + + @RequestMapping("/withOutHystrix") + public String withOutHystrix() throws InterruptedException{ + return client.invokeRemoteServiceWithOutHystrix(); + } +} diff --git a/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestCommand.java b/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestCommand.java new file mode 100644 index 0000000000..49ea951579 --- /dev/null +++ b/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestCommand.java @@ -0,0 +1,20 @@ +package com.baeldung.hystrix; + +import com.netflix.hystrix.HystrixCommand; +import com.netflix.hystrix.HystrixCommandGroupKey; + + +class RemoteServiceTestCommand extends HystrixCommand { + + private final RemoteServiceTestSimulator remoteService; + + RemoteServiceTestCommand(Setter config, RemoteServiceTestSimulator remoteService) { + super(config); + this.remoteService = remoteService; + } + + @Override + protected String run() throws Exception { + return remoteService.execute(); + } +} diff --git a/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestSimulator.java b/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestSimulator.java new file mode 100644 index 0000000000..d302166ea8 --- /dev/null +++ b/hystrix/src/main/java/com/baeldung/hystrix/RemoteServiceTestSimulator.java @@ -0,0 +1,16 @@ +package com.baeldung.hystrix; + + +public class RemoteServiceTestSimulator { + + private long wait; + + RemoteServiceTestSimulator(long wait) throws InterruptedException { + this.wait = wait; + } + + String execute() throws InterruptedException { + Thread.sleep(wait); + return "Success"; + } +} diff --git a/hystrix/src/main/java/com/baeldung/hystrix/SpringExistingClient.java b/hystrix/src/main/java/com/baeldung/hystrix/SpringExistingClient.java new file mode 100644 index 0000000000..525c7b4785 --- /dev/null +++ b/hystrix/src/main/java/com/baeldung/hystrix/SpringExistingClient.java @@ -0,0 +1,20 @@ +package com.baeldung.hystrix; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component("springClient") +public class SpringExistingClient { + + @Value("${remoteservice.timeout}") + private int remoteServiceDelay; + + @HystrixCircuitBreaker + public String invokeRemoteServiceWithHystrix() throws InterruptedException{ + return new RemoteServiceTestSimulator(remoteServiceDelay).execute(); + } + + public String invokeRemoteServiceWithOutHystrix() throws InterruptedException{ + return new RemoteServiceTestSimulator(remoteServiceDelay).execute(); + } +} diff --git a/hystrix/src/main/resources/application.properties b/hystrix/src/main/resources/application.properties new file mode 100644 index 0000000000..50c241d03f --- /dev/null +++ b/hystrix/src/main/resources/application.properties @@ -0,0 +1,8 @@ +remoteservice.command.group.key=RemoteServiceGroup +remoteservice.command.key=RemoteServiceKey +remoteservice.command.execution.timeout=10000 +remoteservice.command.threadpool.coresize=5 +remoteservice.command.threadpool.maxsize=10 +remoteservice.command.task.queue.size=5 +remoteservice.command.sleepwindow=5000 +remoteservice.timeout=15000 \ No newline at end of file diff --git a/hystrix/src/test/java/com/baeldung/hystrix/HystrixTimeoutTest.java b/hystrix/src/test/java/com/baeldung/hystrix/HystrixTimeoutTest.java new file mode 100644 index 0000000000..d72895aab9 --- /dev/null +++ b/hystrix/src/test/java/com/baeldung/hystrix/HystrixTimeoutTest.java @@ -0,0 +1,132 @@ +package com.baeldung.hystrix; + +import com.netflix.hystrix.HystrixCommand; +import com.netflix.hystrix.HystrixCommandGroupKey; +import com.netflix.hystrix.HystrixCommandProperties; +import com.netflix.hystrix.HystrixThreadPoolProperties; +import com.netflix.hystrix.exception.HystrixRuntimeException; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +public class HystrixTimeoutTest { + + @Test + public void givenInputBobAndDefaultSettings_whenCommandExecuted_thenReturnHelloBob(){ + assertThat(new CommandHelloWorld("Bob").execute(), equalTo("Hello Bob!")); + } + + @Test + public void givenSvcTimeoutOf100AndDefaultSettings_whenRemoteSvcExecuted_thenReturnSuccess() + throws InterruptedException { + HystrixCommand.Setter config = HystrixCommand + .Setter + .withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceGroup2")); + + assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(100)).execute(), + equalTo("Success")); + } + + @Test(expected = HystrixRuntimeException.class) + public void givenSvcTimeoutOf10000AndDefaultSettings__whenRemoteSvcExecuted_thenExpectHRE() throws InterruptedException { + HystrixCommand.Setter config = HystrixCommand + .Setter + .withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceGroupTest3")); + new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(10_000)).execute(); + } + + @Test + public void givenSvcTimeoutOf5000AndExecTimeoutOf10000_whenRemoteSvcExecuted_thenReturnSuccess() + throws InterruptedException { + + HystrixCommand.Setter config = HystrixCommand + .Setter + .withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceGroupTest4")); + HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter(); + commandProperties.withExecutionTimeoutInMilliseconds(10_000); + config.andCommandPropertiesDefaults(commandProperties); + + assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(), + equalTo("Success")); + } + + @Test(expected = HystrixRuntimeException.class) + public void givenSvcTimeoutOf15000AndExecTimeoutOf5000__whenExecuted_thenExpectHRE() + throws InterruptedException { + HystrixCommand.Setter config = HystrixCommand + .Setter + .withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceGroupTest5")); + HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter(); + commandProperties.withExecutionTimeoutInMilliseconds(5_000); + config.andCommandPropertiesDefaults(commandProperties); + new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(15_000)).execute(); + } + + @Test + public void givenSvcTimeoutOf500AndExecTimeoutOf10000AndThreadPool__whenExecuted_thenReturnSuccess() + throws InterruptedException { + + HystrixCommand.Setter config = HystrixCommand + .Setter + .withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceGroupThreadPool")); + HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter(); + commandProperties.withExecutionTimeoutInMilliseconds(10_000); + config.andCommandPropertiesDefaults(commandProperties); + config.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter() + .withMaxQueueSize(10) + .withCoreSize(3) + .withQueueSizeRejectionThreshold(10)); + + assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(), + equalTo("Success")); + } + + @Test + public void givenCircuitBreakerSetup__whenRemoteSvcCmdExecuted_thenReturnSuccess() + throws InterruptedException { + + HystrixCommand.Setter config = HystrixCommand + .Setter + .withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceGroupCircuitBreaker")); + HystrixCommandProperties.Setter properties = HystrixCommandProperties.Setter(); + properties.withExecutionTimeoutInMilliseconds(1000); + + properties.withCircuitBreakerSleepWindowInMilliseconds(4000); + properties.withExecutionIsolationStrategy( + HystrixCommandProperties.ExecutionIsolationStrategy.THREAD); + properties.withCircuitBreakerEnabled(true); + properties.withCircuitBreakerRequestVolumeThreshold(1); + + config.andCommandPropertiesDefaults(properties); + + config.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter() + .withMaxQueueSize(1) + .withCoreSize(1) + .withQueueSizeRejectionThreshold(1)); + + assertThat(this.invokeRemoteService(config, 10_000), equalTo(null)); + assertThat(this.invokeRemoteService(config, 10_000), equalTo(null)); + assertThat(this.invokeRemoteService(config, 10_000), equalTo(null)); + Thread.sleep(5000); + + assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(), + equalTo("Success")); + assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(), + equalTo("Success")); + assertThat(new RemoteServiceTestCommand(config, new RemoteServiceTestSimulator(500)).execute(), + equalTo("Success")); + } + + public String invokeRemoteService(HystrixCommand.Setter config, int timeout) + throws InterruptedException { + String response = null; + try { + response = new RemoteServiceTestCommand(config, + new RemoteServiceTestSimulator(timeout)).execute(); + } catch (HystrixRuntimeException ex) { + System.out.println("ex = " + ex); + } + return response; + } +} diff --git a/hystrix/src/test/java/com/baeldung/hystrix/SpringAndHystrixIntegrationTest.java b/hystrix/src/test/java/com/baeldung/hystrix/SpringAndHystrixIntegrationTest.java new file mode 100644 index 0000000000..004314b0ed --- /dev/null +++ b/hystrix/src/test/java/com/baeldung/hystrix/SpringAndHystrixIntegrationTest.java @@ -0,0 +1,36 @@ +package com.baeldung.hystrix; + +import com.netflix.hystrix.exception.HystrixRuntimeException; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, classes = AppConfig.class) +public class SpringAndHystrixIntegrationTest { + + @Autowired + private HystrixController hystrixController; + + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Test + public void givenTimeOutOf15000_whenClientCalledWithHystrix_thenExpectHystrixRuntimeException() throws InterruptedException { + exception.expect(HystrixRuntimeException.class); + hystrixController.withHystrix(); + } + + @Test + public void givenTimeOutOf15000_whenClientCalledWithOutHystrix_thenExpectSuccess() throws InterruptedException { + assertThat(hystrixController.withOutHystrix(), equalTo("Success")); + } + +} diff --git a/immutables/pom.xml b/immutables/pom.xml new file mode 100644 index 0000000000..2b4aba59b1 --- /dev/null +++ b/immutables/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + com.baeldung + immutables + 1.0.0-SNAPSHOT + + + + org.immutables + value + 2.2.10 + + + junit + junit + 4.12 + test + + + org.assertj + assertj-core + 3.5.2 + test + + + org.mutabilitydetector + MutabilityDetector + 0.9.5 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/immutables/src/main/java/com/baeldung/immutable/Address.java b/immutables/src/main/java/com/baeldung/immutable/Address.java new file mode 100644 index 0000000000..93474dc043 --- /dev/null +++ b/immutables/src/main/java/com/baeldung/immutable/Address.java @@ -0,0 +1,9 @@ +package com.baeldung.immutable; + +import org.immutables.value.Value; + +@Value.Immutable +public interface Address { + String getStreetName(); + Integer getNumber(); +} diff --git a/immutables/src/main/java/com/baeldung/immutable/Person.java b/immutables/src/main/java/com/baeldung/immutable/Person.java new file mode 100644 index 0000000000..466daf42c2 --- /dev/null +++ b/immutables/src/main/java/com/baeldung/immutable/Person.java @@ -0,0 +1,9 @@ +package com.baeldung.immutable; + +import org.immutables.value.Value; + +@Value.Immutable +public abstract class Person { + abstract String getName(); + abstract Integer getAge(); +} diff --git a/immutables/src/main/java/com/baeldung/immutable/auxiliary/Person.java b/immutables/src/main/java/com/baeldung/immutable/auxiliary/Person.java new file mode 100644 index 0000000000..78fe28c50c --- /dev/null +++ b/immutables/src/main/java/com/baeldung/immutable/auxiliary/Person.java @@ -0,0 +1,13 @@ +package com.baeldung.immutable.auxiliary; + + +import org.immutables.value.Value; + +@Value.Immutable +public abstract class Person { + abstract String getName(); + abstract Integer getAge(); + + @Value.Auxiliary + abstract String getAuxiliaryField(); +} \ No newline at end of file diff --git a/immutables/src/main/java/com/baeldung/immutable/default_/Person.java b/immutables/src/main/java/com/baeldung/immutable/default_/Person.java new file mode 100644 index 0000000000..bc48f11a38 --- /dev/null +++ b/immutables/src/main/java/com/baeldung/immutable/default_/Person.java @@ -0,0 +1,14 @@ +package com.baeldung.immutable.default_; + +import org.immutables.value.Value; + +@Value.Immutable(prehash = true) +public abstract class Person { + + abstract String getName(); + + @Value.Default + Integer getAge() { + return 42; + } +} diff --git a/immutables/src/main/java/com/baeldung/immutable/parameter/Person.java b/immutables/src/main/java/com/baeldung/immutable/parameter/Person.java new file mode 100644 index 0000000000..4e8218f99c --- /dev/null +++ b/immutables/src/main/java/com/baeldung/immutable/parameter/Person.java @@ -0,0 +1,14 @@ +package com.baeldung.immutable.parameter; + + +import org.immutables.value.Value; + +@Value.Immutable +public abstract class Person { + + @Value.Parameter + abstract String getName(); + + @Value.Parameter + abstract Integer getAge(); +} \ No newline at end of file diff --git a/immutables/src/main/java/com/baeldung/immutable/prehash/Person.java b/immutables/src/main/java/com/baeldung/immutable/prehash/Person.java new file mode 100644 index 0000000000..5e5dd4d9e9 --- /dev/null +++ b/immutables/src/main/java/com/baeldung/immutable/prehash/Person.java @@ -0,0 +1,9 @@ +package com.baeldung.immutable.prehash; + +import org.immutables.value.Value; + +@Value.Immutable(prehash = true) +public abstract class Person { + abstract String getName(); + abstract Integer getAge(); +} diff --git a/immutables/src/test/java/com/baeldung/immutable/ImmutablePersonTest.java b/immutables/src/test/java/com/baeldung/immutable/ImmutablePersonTest.java new file mode 100644 index 0000000000..bf075569db --- /dev/null +++ b/immutables/src/test/java/com/baeldung/immutable/ImmutablePersonTest.java @@ -0,0 +1,27 @@ +package com.baeldung.immutable; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mutabilitydetector.unittesting.MutabilityAssert.assertImmutable; + +public class ImmutablePersonTest { + + @Test + public void whenModifying_shouldCreateNewInstance() throws Exception { + final ImmutablePerson john = ImmutablePerson.builder() + .age(42) + .name("John") + .build(); + + final ImmutablePerson john43 = john.withAge(43); + + assertThat(john) + .isNotSameAs(john43); + + assertThat(john.getAge()) + .isEqualTo(42); + + assertImmutable(ImmutablePerson.class); + } +} \ No newline at end of file diff --git a/immutables/src/test/java/com/baeldung/immutable/auxiliary/ImmutablePersonAuxiliaryTest.java b/immutables/src/test/java/com/baeldung/immutable/auxiliary/ImmutablePersonAuxiliaryTest.java new file mode 100644 index 0000000000..83f9e51ed5 --- /dev/null +++ b/immutables/src/test/java/com/baeldung/immutable/auxiliary/ImmutablePersonAuxiliaryTest.java @@ -0,0 +1,33 @@ +package com.baeldung.immutable.auxiliary; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ImmutablePersonAuxiliaryTest { + + @Test + public void whenComparing_shouldIgnore() throws Exception { + final ImmutablePerson john1 = ImmutablePerson.builder() + .name("John") + .age(42) + .auxiliaryField("Value1") + .build(); + + final ImmutablePerson john2 = ImmutablePerson.builder() + .name("John") + .age(42) + .auxiliaryField("Value2") + .build(); + + + assertThat(john1.equals(john2)) + .isTrue(); + + assertThat(john1.toString()) + .isEqualTo(john2.toString()); + + assertThat(john1.hashCode()) + .isEqualTo(john2.hashCode()); + } +} \ No newline at end of file diff --git a/immutables/src/test/java/com/baeldung/immutable/default_/ImmutablePersonDefaultTest.java b/immutables/src/test/java/com/baeldung/immutable/default_/ImmutablePersonDefaultTest.java new file mode 100644 index 0000000000..5cf4ac0cf7 --- /dev/null +++ b/immutables/src/test/java/com/baeldung/immutable/default_/ImmutablePersonDefaultTest.java @@ -0,0 +1,17 @@ +package com.baeldung.immutable.default_; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ImmutablePersonDefaultTest { + + @Test + public void whenInstantiating_shouldUseDefaultValue() throws Exception { + + final ImmutablePerson john = ImmutablePerson.builder().name("John").build(); + + assertThat(john.getAge()).isEqualTo(42); + + } +} \ No newline at end of file diff --git a/jackson/.classpath b/jackson/.classpath deleted file mode 100644 index 8ebf6d9c31..0000000000 --- a/jackson/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/jackson/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/jackson/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/jackson/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/jackson/.project b/jackson/.project deleted file mode 100644 index ea8ae1a67f..0000000000 --- a/jackson/.project +++ /dev/null @@ -1,36 +0,0 @@ - - - jackson - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/jackson/.settings/.jsdtscope b/jackson/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/jackson/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/jackson/.settings/org.eclipse.jdt.core.prefs b/jackson/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/jackson/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/jackson/.settings/org.eclipse.jdt.ui.prefs b/jackson/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/jackson/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/jackson/.settings/org.eclipse.m2e.core.prefs b/jackson/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/jackson/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/jackson/.settings/org.eclipse.m2e.wtp.prefs b/jackson/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/jackson/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/jackson/.settings/org.eclipse.wst.common.component b/jackson/.settings/org.eclipse.wst.common.component deleted file mode 100644 index e98377cb0f..0000000000 --- a/jackson/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/jackson/.settings/org.eclipse.wst.common.project.facet.core.xml b/jackson/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f4ef8aa0a5..0000000000 --- a/jackson/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/jackson/.settings/org.eclipse.wst.jsdt.ui.superType.container b/jackson/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/jackson/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/jackson/.settings/org.eclipse.wst.jsdt.ui.superType.name b/jackson/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/jackson/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/jackson/.settings/org.eclipse.wst.validation.prefs b/jackson/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index cacf5451ae..0000000000 --- a/jackson/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,14 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.303.v201202090300 -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/jackson/.settings/org.eclipse.wst.ws.service.policy.prefs b/jackson/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/jackson/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/jackson/.springBeans b/jackson/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/jackson/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/jackson/README.md b/jackson/README.md index 539cb34761..68765de686 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -2,11 +2,20 @@ ## Jackson Cookbooks and Examples +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + ### Relevant Articles: - [Jackson Ignore Properties on Marshalling](http://www.baeldung.com/jackson-ignore-properties-on-serialization) -- [Jackson – Unmarshall to Collection/Array](http://www.baeldung.com/jackson-collection-array) +- [Jackson – Unmarshall to Collection/Array](http://www.baeldung.com/jackson-collection-array) - [Jackson Unmarshalling json with Unknown Properties](http://www.baeldung.com/jackson-deserialize-json-unknown-properties) -- [Jackson – Custom Serializer](http://www.baeldung.com/jackson-custom-serialization) -- [Jackson – Custom Deserializer](http://www.baeldung.com/jackson-deserialization) - - +- [Jackson – Custom Serializer](http://www.baeldung.com/jackson-custom-serialization) +- [Jackson – Custom Deserializer](http://www.baeldung.com/jackson-deserialization) +- [Jackson Exceptions – Problems and Solutions](http://www.baeldung.com/jackson-exception) +- [Jackson Date](http://www.baeldung.com/jackson-serialize-dates) +- [Jackson – Bidirectional Relationships](http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion) +- [Jackson JSON Tutorial](http://www.baeldung.com/jackson) +- [Jackson – Working with Maps and nulls](http://www.baeldung.com/jackson-map-null-values-or-null-key) +- [Jackson – Decide What Fields Get Serialized/Deserializaed](http://www.baeldung.com/jackson-field-serializable-deserializable-or-not) +- [A Guide to Jackson Annotations](http://www.baeldung.com/jackson-annotations) +- [Working with Tree Model Nodes in Jackson](http://www.baeldung.com/jackson-json-node-tree-model) diff --git a/jackson/pom.xml b/jackson/pom.xml index 9996330361..17b0ac507e 100644 --- a/jackson/pom.xml +++ b/jackson/pom.xml @@ -1,6 +1,7 @@ - + 4.0.0 - org.baeldung + com.baeldung jackson 0.1-SNAPSHOT @@ -21,6 +22,12 @@ commons-io 2.4 + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + 2.7.4 + org.apache.commons @@ -47,25 +54,31 @@ com.fasterxml.jackson.datatype jackson-datatype-jsr310 - 2.4.0 + ${jackson.version} com.fasterxml.jackson.datatype jackson-datatype-joda - 2.4.0 + ${jackson.version} + + + + com.fasterxml.jackson.module + jackson-module-jsonSchema + 2.7.2 joda-time joda-time - 2.6 + 2.9.2 com.google.code.gson gson - 2.3.1 + 2.6.2 @@ -96,6 +109,31 @@ ${mockito.version} test + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + @@ -131,16 +169,12 @@ - - 4.1.5.RELEASE - 3.2.5.RELEASE - - 4.3.10.Final - 5.1.35 + 4.3.11.Final + 5.1.38 - 2.5.5 + 2.7.2 1.7.13 @@ -161,15 +195,15 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.14 + 1.4.18 - \ No newline at end of file + diff --git a/jackson/src/main/java/org/baeldung/jackson/entities/ActorJackson.java b/jackson/src/main/java/org/baeldung/jackson/entities/ActorJackson.java new file mode 100644 index 0000000000..68cd6117d6 --- /dev/null +++ b/jackson/src/main/java/org/baeldung/jackson/entities/ActorJackson.java @@ -0,0 +1,52 @@ +package org.baeldung.jackson.entities; + +import java.util.Date; +import java.util.List; + +public class ActorJackson { + + private String imdbId; + private Date dateOfBirth; + private List filmography; + + public ActorJackson() { + super(); + } + + public ActorJackson(String imdbId, Date dateOfBirth, List filmography) { + super(); + this.imdbId = imdbId; + this.dateOfBirth = dateOfBirth; + this.filmography = filmography; + } + + @Override + public String toString() { + return "ActorJackson [imdbId=" + imdbId + ", dateOfBirth=" + dateOfBirth + ", filmography=" + filmography + "]"; + } + + public String getImdbId() { + return imdbId; + } + + public void setImdbId(String imdbId) { + this.imdbId = imdbId; + } + + public Date getDateOfBirth() { + return dateOfBirth; + } + + public void setDateOfBirth(Date dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } + + public List getFilmography() { + return filmography; + } + + public void setFilmography(List filmography) { + this.filmography = filmography; + } + +} diff --git a/jackson/src/main/java/org/baeldung/jackson/entities/Movie.java b/jackson/src/main/java/org/baeldung/jackson/entities/Movie.java new file mode 100644 index 0000000000..68b7464563 --- /dev/null +++ b/jackson/src/main/java/org/baeldung/jackson/entities/Movie.java @@ -0,0 +1,50 @@ +package org.baeldung.jackson.entities; + +import java.util.List; + +public class Movie { + + private String imdbId; + private String director; + private List actors; + + public Movie(String imdbId, String director, List actors) { + super(); + this.imdbId = imdbId; + this.director = director; + this.actors = actors; + } + + public Movie() { + super(); + } + + @Override + public String toString() { + return "Movie [imdbId=" + imdbId + ", director=" + director + ", actors=" + actors + "]"; + } + + public String getImdbId() { + return imdbId; + } + + public void setImdbId(String imdbId) { + this.imdbId = imdbId; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public List getActors() { + return actors; + } + + public void setActors(List actors) { + this.actors = actors; + } +} \ No newline at end of file diff --git a/jackson/src/main/java/org/baeldung/jackson/entities/MovieWithNullValue.java b/jackson/src/main/java/org/baeldung/jackson/entities/MovieWithNullValue.java new file mode 100644 index 0000000000..23f5de2858 --- /dev/null +++ b/jackson/src/main/java/org/baeldung/jackson/entities/MovieWithNullValue.java @@ -0,0 +1,46 @@ +package org.baeldung.jackson.entities; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.util.List; + +public class MovieWithNullValue { + + private String imdbId; + + @JsonIgnore + private String director; + + private List actors; + + public MovieWithNullValue(String imdbID, String director, List actors) { + super(); + this.imdbId = imdbID; + this.director = director; + this.actors = actors; + } + + public String getImdbID() { + return imdbId; + } + + public void setImdbID(String imdbID) { + this.imdbId = imdbID; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public List getActors() { + return actors; + } + + public void setActors(List actors) { + this.actors = actors; + } +} \ No newline at end of file diff --git a/jackson/src/main/java/org/baeldung/jackson/serialization/ActorJacksonSerializer.java b/jackson/src/main/java/org/baeldung/jackson/serialization/ActorJacksonSerializer.java new file mode 100644 index 0000000000..c33cf59482 --- /dev/null +++ b/jackson/src/main/java/org/baeldung/jackson/serialization/ActorJacksonSerializer.java @@ -0,0 +1,31 @@ +package org.baeldung.jackson.serialization; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.stream.Collectors; + +import org.baeldung.jackson.entities.ActorJackson; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class ActorJacksonSerializer extends StdSerializer { + + private SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); + + public ActorJacksonSerializer(Class t) { + super(t); + } + + @Override + public void serialize(ActorJackson actor, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + + jsonGenerator.writeStartObject(); + jsonGenerator.writeStringField("imdbId", actor.getImdbId()); + jsonGenerator.writeObjectField("dateOfBirth", actor.getDateOfBirth() != null ? sdf.format(actor.getDateOfBirth()) : null); + jsonGenerator.writeNumberField("N° Film: ", actor.getFilmography() != null ? actor.getFilmography().size() : null); + jsonGenerator.writeStringField("filmography", actor.getFilmography().stream().collect(Collectors.joining("-"))); + jsonGenerator.writeEndObject(); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithCreator.java b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCreator.java similarity index 89% rename from jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithCreator.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCreator.java index 01507ab4d6..90a45efc96 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithCreator.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCreator.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithCustomAnnotation.java b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java similarity index 90% rename from jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithCustomAnnotation.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java index 3b468f474f..65d64059c9 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithCustomAnnotation.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java @@ -1,10 +1,10 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Date; -import org.baeldung.jackson.annotation.BeanWithCustomAnnotation.CustomAnnotation; +import com.baeldung.jackson.annotation.BeanWithCustomAnnotation.CustomAnnotation; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithFilter.java b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java similarity index 88% rename from jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithFilter.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java index a0627757b6..48fecf8c13 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithFilter.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import com.fasterxml.jackson.annotation.JsonFilter; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithGetter.java b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithGetter.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java index 6585018564..39db9f06b9 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithGetter.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithIgnore.java b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java similarity index 90% rename from jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithIgnore.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java index 4f0866bdc0..aa4e6b495d 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithIgnore.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithInject.java b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java similarity index 88% rename from jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithInject.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java index aa8da1da4f..473058fd1c 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/BeanWithInject.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import com.fasterxml.jackson.annotation.JacksonInject; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/ExtendableBean.java b/jackson/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java similarity index 94% rename from jackson/src/test/java/org/baeldung/jackson/annotation/ExtendableBean.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java index c8e5f453ec..e03ffed613 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/ExtendableBean.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import java.util.HashMap; import java.util.Map; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/MyBean.java b/jackson/src/test/java/com/baeldung/jackson/annotation/MyBean.java similarity index 91% rename from jackson/src/test/java/org/baeldung/jackson/annotation/MyBean.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/MyBean.java index 651d7c2da0..5d4ce4202c 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/MyBean.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/MyBean.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/PrivateBean.java b/jackson/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java similarity index 90% rename from jackson/src/test/java/org/baeldung/jackson/annotation/PrivateBean.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java index 472fa84a26..a49ce2e6d5 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/PrivateBean.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/RawBean.java b/jackson/src/test/java/com/baeldung/jackson/annotation/RawBean.java similarity index 87% rename from jackson/src/test/java/org/baeldung/jackson/annotation/RawBean.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/RawBean.java index a481fbf02e..a0482ef5c1 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/RawBean.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/RawBean.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import com.fasterxml.jackson.annotation.JsonRawValue; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/UnwrappedUser.java b/jackson/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/annotation/UnwrappedUser.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java index 4c761a57e0..d2b7522221 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/UnwrappedUser.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import com.fasterxml.jackson.annotation.JsonUnwrapped; diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/UserWithIgnoreType.java b/jackson/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/annotation/UserWithIgnoreType.java rename to jackson/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java index eaf4cb7b74..36f383cf65 100644 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/UserWithIgnoreType.java +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.annotation; +package com.baeldung.jackson.annotation; import com.fasterxml.jackson.annotation.JsonIgnoreType; diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/Zoo.java b/jackson/src/test/java/com/baeldung/jackson/annotation/Zoo.java new file mode 100644 index 0000000000..9c11ec0e36 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/Zoo.java @@ -0,0 +1,56 @@ +package com.baeldung.jackson.annotation; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeInfo.As; +import com.fasterxml.jackson.annotation.JsonTypeName; + +public class Zoo { + public Animal animal; + + public Zoo() { + + } + + public Zoo(final Animal animal) { + this.animal = animal; + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type") + @JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "dog"), @JsonSubTypes.Type(value = Cat.class, name = "cat") }) + public static class Animal { + public String name; + + public Animal() { + } + + public Animal(final String name) { + this.name = name; + } + } + + @JsonTypeName("dog") + public static class Dog extends Animal { + public double barkVolume; + + public Dog() { + } + + public Dog(final String name) { + this.name = name; + } + } + + @JsonTypeName("cat") + public static class Cat extends Animal { + boolean likesCream; + public int lives; + + public Cat() { + } + + public Cat(final String name) { + this.name = name; + } + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/extra/AppendBeans.java b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/AppendBeans.java new file mode 100644 index 0000000000..7b75c205c9 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/AppendBeans.java @@ -0,0 +1,58 @@ +package com.baeldung.jackson.annotation.extra; + +import com.fasterxml.jackson.databind.annotation.JsonAppend; + +public class AppendBeans { + public static class BeanWithoutAppend { + private int id; + private String name; + + public BeanWithoutAppend(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @JsonAppend(attrs = { @JsonAppend.Attr(value = "version") }) + public static class BeanWithAppend { + private int id; + private String name; + + public BeanWithAppend(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/extra/ExtraAnnotationTest.java b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/ExtraAnnotationTest.java new file mode 100644 index 0000000000..79aae1dd04 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/ExtraAnnotationTest.java @@ -0,0 +1,131 @@ +package com.baeldung.jackson.annotation.extra; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import org.junit.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.jackson.annotation.extra.AppendBeans.BeanWithAppend; +import com.baeldung.jackson.annotation.extra.AppendBeans.BeanWithoutAppend; +import com.baeldung.jackson.annotation.extra.IdentityReferenceBeans.BeanWithIdentityReference; +import com.baeldung.jackson.annotation.extra.IdentityReferenceBeans.BeanWithoutIdentityReference; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.module.jsonSchema.JsonSchema; +import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper; + +public class ExtraAnnotationTest { + @Test + public void whenNotUsingJsonIdentityReferenceAnnotation_thenCorrect() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + BeanWithoutIdentityReference bean = new BeanWithoutIdentityReference(1, "Bean Without Identity Reference Annotation"); + String jsonString = mapper.writeValueAsString(bean); + + assertThat(jsonString, containsString("Bean Without Identity Reference Annotation")); + } + + @Test + public void whenUsingJsonIdentityReferenceAnnotation_thenCorrect() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + BeanWithIdentityReference bean = new BeanWithIdentityReference(1, "Bean With Identity Reference Annotation"); + String jsonString = mapper.writeValueAsString(bean); + + assertEquals("1", jsonString); + } + + @Test + public void whenNotUsingJsonAppendAnnotation_thenCorrect() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + + BeanWithoutAppend bean = new BeanWithoutAppend(2, "Bean Without Append Annotation"); + ObjectWriter writer = mapper.writerFor(BeanWithoutAppend.class).withAttribute("version", "1.0"); + String jsonString = writer.writeValueAsString(bean); + + assertThat(jsonString, not(containsString("version"))); + assertThat(jsonString, not(containsString("1.0"))); + } + + @Test + public void whenUsingJsonAppendAnnotation_thenCorrect() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + + BeanWithAppend bean = new BeanWithAppend(2, "Bean With Append Annotation"); + ObjectWriter writer = mapper.writerFor(BeanWithAppend.class).withAttribute("version", "1.0"); + String jsonString = writer.writeValueAsString(bean); + + assertThat(jsonString, containsString("version")); + assertThat(jsonString, containsString("1.0")); + } + + @Test + public void whenUsingJsonNamingAnnotation_thenCorrect() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + NamingBean bean = new NamingBean(3, "Naming Bean"); + String jsonString = mapper.writeValueAsString(bean); + + assertThat(jsonString, containsString("bean_name")); + } + + @Test + public void whenUsingJsonPropertyDescriptionAnnotation_thenCorrect() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + SchemaFactoryWrapper wrapper = new SchemaFactoryWrapper(); + mapper.acceptJsonFormatVisitor(PropertyDescriptionBean.class, wrapper); + JsonSchema jsonSchema = wrapper.finalSchema(); + String jsonString = mapper.writeValueAsString(jsonSchema); + System.out.println(jsonString); + assertThat(jsonString, containsString("This is a description of the name property")); + } + + @Test + public void whenUsingJsonPOJOBuilderAnnotation_thenCorrect() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + String jsonString = "{\"id\":5,\"name\":\"POJO Builder Bean\"}"; + POJOBuilderBean bean = mapper.readValue(jsonString, POJOBuilderBean.class); + + assertEquals(5, bean.getIdentity()); + assertEquals("POJO Builder Bean", bean.getBeanName()); + } + + @Test + public void whenUsingJsonTypeIdAnnotation_thenCorrect() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(DefaultTyping.NON_FINAL); + TypeIdBean bean = new TypeIdBean(6, "Type Id Bean"); + String jsonString = mapper.writeValueAsString(bean); + + assertThat(jsonString, containsString("Type Id Bean")); + } + + @Test + public void whenUsingJsonTypeIdResolverAnnotation_thenCorrect() throws IOException { + TypeIdResolverStructure.FirstBean bean1 = new TypeIdResolverStructure.FirstBean(1, "Bean 1"); + TypeIdResolverStructure.LastBean bean2 = new TypeIdResolverStructure.LastBean(2, "Bean 2"); + + List beans = new ArrayList<>(); + beans.add(bean1); + beans.add(bean2); + + TypeIdResolverStructure.BeanContainer serializedContainer = new TypeIdResolverStructure.BeanContainer(); + serializedContainer.setBeans(beans); + + ObjectMapper mapper = new ObjectMapper(); + String jsonString = mapper.writeValueAsString(serializedContainer); + assertThat(jsonString, containsString("bean1")); + assertThat(jsonString, containsString("bean2")); + + TypeIdResolverStructure.BeanContainer deserializedContainer = mapper.readValue(jsonString, TypeIdResolverStructure.BeanContainer.class); + List beanList = deserializedContainer.getBeans(); + assertThat(beanList.get(0), instanceOf(TypeIdResolverStructure.FirstBean.class)); + assertThat(beanList.get(1), instanceOf(TypeIdResolverStructure.LastBean.class)); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/extra/IdentityReferenceBeans.java b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/IdentityReferenceBeans.java new file mode 100644 index 0000000000..495bb7de43 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/IdentityReferenceBeans.java @@ -0,0 +1,63 @@ +package com.baeldung.jackson.annotation.extra; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.JsonIdentityReference; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + + +public class IdentityReferenceBeans { + @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") + public static class BeanWithoutIdentityReference { + private int id; + private String name; + + public BeanWithoutIdentityReference(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") + @JsonIdentityReference(alwaysAsId = true) + public static class BeanWithIdentityReference { + private int id; + private String name; + + public BeanWithIdentityReference(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/extra/NamingBean.java b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/NamingBean.java new file mode 100644 index 0000000000..efd26ab9ae --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/NamingBean.java @@ -0,0 +1,31 @@ +package com.baeldung.jackson.annotation.extra; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class NamingBean { + private int id; + private String beanName; + + public NamingBean(int id, String beanName) { + this.id = id; + this.beanName = beanName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getBeanName() { + return beanName; + } + + public void setBeanName(String beanName) { + this.beanName = beanName; + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/extra/POJOBuilderBean.java b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/POJOBuilderBean.java new file mode 100644 index 0000000000..e0a89c6903 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/POJOBuilderBean.java @@ -0,0 +1,51 @@ +package com.baeldung.jackson.annotation.extra; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; + +@JsonDeserialize(builder = POJOBuilderBean.BeanBuilder.class) +public class POJOBuilderBean { + private int identity; + private String beanName; + + @JsonPOJOBuilder(buildMethodName = "createBean", withPrefix = "construct") + public static class BeanBuilder { + private int idValue; + private String nameValue; + + public BeanBuilder constructId(int id) { + idValue = id; + return this; + } + + public BeanBuilder constructName(String name) { + nameValue = name; + return this; + } + + public POJOBuilderBean createBean() { + return new POJOBuilderBean(idValue, nameValue); + } + } + + public POJOBuilderBean(int identity, String beanName) { + this.identity = identity; + this.beanName = beanName; + } + + public int getIdentity() { + return identity; + } + + public void setIdentity(int identity) { + this.identity = identity; + } + + public String getBeanName() { + return beanName; + } + + public void setBeanName(String beanName) { + this.beanName = beanName; + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/extra/PropertyDescriptionBean.java b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/PropertyDescriptionBean.java new file mode 100644 index 0000000000..1563cddb83 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/PropertyDescriptionBean.java @@ -0,0 +1,25 @@ +package com.baeldung.jackson.annotation.extra; + +import com.fasterxml.jackson.annotation.JsonPropertyDescription; + +public class PropertyDescriptionBean { + private int id; + @JsonPropertyDescription("This is a description of the name property") + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/extra/TypeIdBean.java b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/TypeIdBean.java new file mode 100644 index 0000000000..32a6d5a1d5 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/TypeIdBean.java @@ -0,0 +1,30 @@ +package com.baeldung.jackson.annotation.extra; + +import com.fasterxml.jackson.annotation.JsonTypeId; + +public class TypeIdBean { + private int id; + @JsonTypeId + private String name; + + public TypeIdBean(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/extra/TypeIdResolverStructure.java b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/TypeIdResolverStructure.java new file mode 100644 index 0000000000..9056023c69 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/extra/TypeIdResolverStructure.java @@ -0,0 +1,130 @@ +package com.baeldung.jackson.annotation.extra; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; +import com.fasterxml.jackson.databind.DatabindContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver; +import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase; + +public class TypeIdResolverStructure { + public static class BeanContainer { + private List beans; + + public List getBeans() { + return beans; + } + + public void setBeans(List beans) { + this.beans = beans; + } + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type") + @JsonTypeIdResolver(BeanIdResolver.class) + public static class AbstractBean { + private int id; + + protected AbstractBean() { + } + + protected AbstractBean(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + } + + public static class FirstBean extends AbstractBean { + String firstName; + + public FirstBean() { + } + + public FirstBean(int id, String name) { + super(id); + setFirstName(name); + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String name) { + firstName = name; + } + } + + public static class LastBean extends AbstractBean { + String lastName; + + public LastBean() { + } + + public LastBean(int id, String name) { + super(id); + setLastName(name); + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String name) { + lastName = name; + } + } + + public static class BeanIdResolver extends TypeIdResolverBase { + private JavaType superType; + + @Override + public void init(JavaType baseType) { + superType = baseType; + } + + @Override + public Id getMechanism() { + return Id.NAME; + } + + @Override + public String idFromValue(Object obj) { + return idFromValueAndType(obj, obj.getClass()); + } + + @Override + public String idFromValueAndType(Object obj, Class subType) { + String typeId = null; + switch (subType.getSimpleName()) { + case "FirstBean": + typeId = "bean1"; + break; + case "LastBean": + typeId = "bean2"; + } + return typeId; + } + + @Override + public JavaType typeFromId(DatabindContext context, String id) { + Class subType = null; + switch (id) { + case "bean1": + subType = FirstBean.class; + break; + case "bean2": + subType = LastBean.class; + } + return context.constructSpecializedType(superType, subType); + } + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/bidirection/CustomListDeserializer.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/CustomListDeserializer.java new file mode 100644 index 0000000000..c00316e365 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/CustomListDeserializer.java @@ -0,0 +1,29 @@ +package com.baeldung.jackson.bidirection; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +public class CustomListDeserializer extends StdDeserializer> { + + private static final long serialVersionUID = 1095767961632979804L; + + public CustomListDeserializer() { + this(null); + } + + public CustomListDeserializer(final Class vc) { + super(vc); + } + + @Override + public List deserialize(final JsonParser jsonparser, final DeserializationContext context) throws IOException, JsonProcessingException { + return new ArrayList(); + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/bidirection/CustomListSerializer.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/CustomListSerializer.java new file mode 100644 index 0000000000..75e0a4ecb7 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/CustomListSerializer.java @@ -0,0 +1,31 @@ +package com.baeldung.jackson.bidirection; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class CustomListSerializer extends StdSerializer> { + + private static final long serialVersionUID = 3698763098000900856L; + + public CustomListSerializer() { + this(null); + } + + public CustomListSerializer(final Class> t) { + super(t); + } + @Override + public void serialize(final List items, final JsonGenerator generator, final SerializerProvider provider) throws IOException, JsonProcessingException { + final List ids = new ArrayList(); + for (final ItemWithSerializer item : items) { + ids.add(item.id); + } + generator.writeObject(ids); + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/bidirection/Item.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/Item.java new file mode 100644 index 0000000000..55b8632e42 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/Item.java @@ -0,0 +1,17 @@ +package com.baeldung.jackson.bidirection; + +public class Item { + public int id; + public String itemName; + public User owner; + + public Item() { + super(); + } + + public Item(final int id, final String itemName, final User owner) { + this.id = id; + this.itemName = itemName; + this.owner = owner; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithIdentity.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithIdentity.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithIdentity.java rename to jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithIdentity.java index 2091ec6e40..25de4a8f7a 100644 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithIdentity.java +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithIdentity.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.bidirection; +package com.baeldung.jackson.bidirection; import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithIgnore.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithIgnore.java similarity index 89% rename from jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithIgnore.java rename to jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithIgnore.java index 8b6d623f18..910ccec174 100644 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithIgnore.java +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithIgnore.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.bidirection; +package com.baeldung.jackson.bidirection; public class ItemWithIgnore { public int id; diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithRef.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithRef.java similarity index 91% rename from jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithRef.java rename to jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithRef.java index 295ec9580d..0ca8d721e8 100644 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithRef.java +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithRef.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.bidirection; +package com.baeldung.jackson.bidirection; import com.fasterxml.jackson.annotation.JsonManagedReference; diff --git a/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithSerializer.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithSerializer.java new file mode 100644 index 0000000000..a57ca89d2c --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithSerializer.java @@ -0,0 +1,17 @@ +package com.baeldung.jackson.bidirection; + +public class ItemWithSerializer { + public int id; + public String itemName; + public UserWithSerializer owner; + + public ItemWithSerializer() { + super(); + } + + public ItemWithSerializer(final int id, final String itemName, final UserWithSerializer owner) { + this.id = id; + this.itemName = itemName; + this.owner = owner; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithView.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithView.java similarity index 85% rename from jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithView.java rename to jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithView.java index 65e0d08b4e..ffa19fbad2 100644 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithView.java +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/ItemWithView.java @@ -1,6 +1,6 @@ -package org.baeldung.jackson.bidirection; +package com.baeldung.jackson.bidirection; -import org.baeldung.jackson.jsonview.Views; +import com.baeldung.jackson.jsonview.Views; import com.fasterxml.jackson.annotation.JsonView; diff --git a/jackson/src/test/java/com/baeldung/jackson/bidirection/User.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/User.java new file mode 100644 index 0000000000..71c9ec6a68 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/User.java @@ -0,0 +1,24 @@ +package com.baeldung.jackson.bidirection; + +import java.util.ArrayList; +import java.util.List; + +public class User { + public int id; + public String name; + public List userItems; + + public User() { + super(); + } + + public User(final int id, final String name) { + this.id = id; + this.name = name; + userItems = new ArrayList(); + } + + public void addItem(final Item item) { + userItems.add(item); + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithIdentity.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithIdentity.java similarity index 94% rename from jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithIdentity.java rename to jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithIdentity.java index 52fa22c32d..db83a09389 100644 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithIdentity.java +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithIdentity.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.bidirection; +package com.baeldung.jackson.bidirection; import java.util.ArrayList; import java.util.List; diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithIgnore.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithIgnore.java similarity index 92% rename from jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithIgnore.java rename to jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithIgnore.java index 7714487f76..857a373cc5 100644 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithIgnore.java +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithIgnore.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.bidirection; +package com.baeldung.jackson.bidirection; import java.util.ArrayList; import java.util.List; diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithRef.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithRef.java similarity index 92% rename from jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithRef.java rename to jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithRef.java index 406b87f78c..3de03fc651 100644 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithRef.java +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithRef.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.bidirection; +package com.baeldung.jackson.bidirection; import java.util.ArrayList; import java.util.List; diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithSerializer.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithSerializer.java similarity index 94% rename from jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithSerializer.java rename to jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithSerializer.java index 25c202a9d3..9fda969e41 100644 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithSerializer.java +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithSerializer.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.bidirection; +package com.baeldung.jackson.bidirection; import java.util.ArrayList; import java.util.List; diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithView.java b/jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithView.java similarity index 87% rename from jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithView.java rename to jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithView.java index e7043292a0..d92d67b3a1 100644 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/UserWithView.java +++ b/jackson/src/test/java/com/baeldung/jackson/bidirection/UserWithView.java @@ -1,9 +1,9 @@ -package org.baeldung.jackson.bidirection; +package com.baeldung.jackson.bidirection; import java.util.ArrayList; import java.util.List; -import org.baeldung.jackson.jsonview.Views; +import com.baeldung.jackson.jsonview.Views; import com.fasterxml.jackson.annotation.JsonView; diff --git a/jackson/src/test/java/com/baeldung/jackson/date/CustomDateDeserializer.java b/jackson/src/test/java/com/baeldung/jackson/date/CustomDateDeserializer.java new file mode 100644 index 0000000000..90c7d9fbac --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/date/CustomDateDeserializer.java @@ -0,0 +1,36 @@ +package com.baeldung.jackson.date; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +public class CustomDateDeserializer extends StdDeserializer { + + private static final long serialVersionUID = -5451717385630622729L; + private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + + public CustomDateDeserializer() { + this(null); + } + + public CustomDateDeserializer(final Class vc) { + super(vc); + } + + @Override + public Date deserialize(final JsonParser jsonparser, final DeserializationContext context) throws IOException, JsonProcessingException { + final String date = jsonparser.getText(); + try { + return formatter.parse(date); + } catch (final ParseException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/date/CustomDateSerializer.java b/jackson/src/test/java/com/baeldung/jackson/date/CustomDateSerializer.java new file mode 100644 index 0000000000..d840e1940f --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/date/CustomDateSerializer.java @@ -0,0 +1,29 @@ +package com.baeldung.jackson.date; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class CustomDateSerializer extends StdSerializer { + + private static final long serialVersionUID = -2894356342227378312L; + private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + + public CustomDateSerializer() { + this(null); + } + + public CustomDateSerializer(final Class t) { + super(t); + } + + @Override + public void serialize(final Date value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { + gen.writeString(formatter.format(value)); + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/date/CustomDateTimeSerializer.java b/jackson/src/test/java/com/baeldung/jackson/date/CustomDateTimeSerializer.java new file mode 100644 index 0000000000..ab4f4bbec7 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/date/CustomDateTimeSerializer.java @@ -0,0 +1,32 @@ +package com.baeldung.jackson.date; + +import java.io.IOException; + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class CustomDateTimeSerializer extends StdSerializer { + + private static final long serialVersionUID = -3927232057990121460L; + + public CustomDateTimeSerializer() { + this(null); + } + + public CustomDateTimeSerializer(final Class t) { + super(t); + } + + private static DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"); + + @Override + public void serialize(final DateTime value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { + gen.writeString(formatter.print(value)); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/date/CustomLocalDateTimeSerializer.java b/jackson/src/test/java/com/baeldung/jackson/date/CustomLocalDateTimeSerializer.java new file mode 100644 index 0000000000..dbcf42488e --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/date/CustomLocalDateTimeSerializer.java @@ -0,0 +1,30 @@ +package com.baeldung.jackson.date; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class CustomLocalDateTimeSerializer extends StdSerializer { + + + private static final long serialVersionUID = -7449444168934819290L; + private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + + public CustomLocalDateTimeSerializer() { + this(null); + } + + public CustomLocalDateTimeSerializer(final Class t) { + super(t); + } + + @Override + public void serialize(final LocalDateTime value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { + gen.writeString(formatter.format(value)); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/date/Event.java b/jackson/src/test/java/com/baeldung/jackson/date/Event.java similarity index 91% rename from jackson/src/test/java/org/baeldung/jackson/date/Event.java rename to jackson/src/test/java/com/baeldung/jackson/date/Event.java index 783eee6af8..e20882abc1 100644 --- a/jackson/src/test/java/org/baeldung/jackson/date/Event.java +++ b/jackson/src/test/java/com/baeldung/jackson/date/Event.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.date; +package com.baeldung.jackson.date; import java.util.Date; diff --git a/jackson/src/test/java/org/baeldung/jackson/date/EventWithFormat.java b/jackson/src/test/java/com/baeldung/jackson/date/EventWithFormat.java similarity index 94% rename from jackson/src/test/java/org/baeldung/jackson/date/EventWithFormat.java rename to jackson/src/test/java/com/baeldung/jackson/date/EventWithFormat.java index 4b2053eb4b..607e694cef 100644 --- a/jackson/src/test/java/org/baeldung/jackson/date/EventWithFormat.java +++ b/jackson/src/test/java/com/baeldung/jackson/date/EventWithFormat.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.date; +package com.baeldung.jackson.date; import java.util.Date; diff --git a/jackson/src/test/java/org/baeldung/jackson/date/EventWithJodaTime.java b/jackson/src/test/java/com/baeldung/jackson/date/EventWithJodaTime.java similarity index 94% rename from jackson/src/test/java/org/baeldung/jackson/date/EventWithJodaTime.java rename to jackson/src/test/java/com/baeldung/jackson/date/EventWithJodaTime.java index 0c72030650..6abee344ef 100644 --- a/jackson/src/test/java/org/baeldung/jackson/date/EventWithJodaTime.java +++ b/jackson/src/test/java/com/baeldung/jackson/date/EventWithJodaTime.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.date; +package com.baeldung.jackson.date; import org.joda.time.DateTime; diff --git a/jackson/src/test/java/org/baeldung/jackson/date/EventWithLocalDateTime.java b/jackson/src/test/java/com/baeldung/jackson/date/EventWithLocalDateTime.java similarity index 94% rename from jackson/src/test/java/org/baeldung/jackson/date/EventWithLocalDateTime.java rename to jackson/src/test/java/com/baeldung/jackson/date/EventWithLocalDateTime.java index 6c48cf3f0e..16104222d4 100644 --- a/jackson/src/test/java/org/baeldung/jackson/date/EventWithLocalDateTime.java +++ b/jackson/src/test/java/com/baeldung/jackson/date/EventWithLocalDateTime.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.date; +package com.baeldung.jackson.date; import java.time.LocalDateTime; diff --git a/jackson/src/test/java/org/baeldung/jackson/date/EventWithSerializer.java b/jackson/src/test/java/com/baeldung/jackson/date/EventWithSerializer.java similarity index 95% rename from jackson/src/test/java/org/baeldung/jackson/date/EventWithSerializer.java rename to jackson/src/test/java/com/baeldung/jackson/date/EventWithSerializer.java index 9cdd6a0fab..c359b5c846 100644 --- a/jackson/src/test/java/org/baeldung/jackson/date/EventWithSerializer.java +++ b/jackson/src/test/java/com/baeldung/jackson/date/EventWithSerializer.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.date; +package com.baeldung.jackson.date; import java.util.Date; diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializer.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializer.java new file mode 100644 index 0000000000..e9c89b8c78 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializer.java @@ -0,0 +1,39 @@ +package com.baeldung.jackson.deserialization; + +import java.io.IOException; + +import com.baeldung.jackson.dtos.Item; +import com.baeldung.jackson.dtos.User; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.node.IntNode; + +public class ItemDeserializer extends StdDeserializer { + + private static final long serialVersionUID = 1883547683050039861L; + + public ItemDeserializer() { + this(null); + } + + public ItemDeserializer(final Class vc) { + super(vc); + } + + /** + * {"id":1,"itemNr":"theItem","owner":2} + */ + @Override + public Item deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException { + final JsonNode node = jp.getCodec().readTree(jp); + final int id = (Integer) ((IntNode) node.get("id")).numberValue(); + final String itemName = node.get("itemName").asText(); + final int userId = (Integer) ((IntNode) node.get("createdBy")).numberValue(); + + return new Item(id, itemName, new User(userId, null)); + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializerOnClass.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializerOnClass.java new file mode 100644 index 0000000000..2036780e99 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializerOnClass.java @@ -0,0 +1,39 @@ +package com.baeldung.jackson.deserialization; + +import java.io.IOException; + +import com.baeldung.jackson.dtos.ItemWithSerializer; +import com.baeldung.jackson.dtos.User; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.node.IntNode; + +public class ItemDeserializerOnClass extends StdDeserializer { + + private static final long serialVersionUID = 5579141241817332594L; + + public ItemDeserializerOnClass() { + this(null); + } + + public ItemDeserializerOnClass(final Class vc) { + super(vc); + } + + /** + * {"id":1,"itemNr":"theItem","owner":2} + */ + @Override + public ItemWithSerializer deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException { + final JsonNode node = jp.getCodec().readTree(jp); + final int id = (Integer) ((IntNode) node.get("id")).numberValue(); + final String itemName = node.get("itemName").asText(); + final int userId = (Integer) ((IntNode) node.get("owner")).numberValue(); + + return new ItemWithSerializer(id, itemName, new User(userId, null)); + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/Item.java b/jackson/src/test/java/com/baeldung/jackson/dtos/Item.java new file mode 100644 index 0000000000..6fce2bc88e --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Item.java @@ -0,0 +1,32 @@ +package com.baeldung.jackson.dtos; + +public class Item { + public int id; + public String itemName; + public User owner; + + public Item() { + super(); + } + + public Item(final int id, final String itemName, final User owner) { + this.id = id; + this.itemName = itemName; + this.owner = owner; + } + + // API + + public int getId() { + return id; + } + + public String getItemName() { + return itemName; + } + + public User getOwner() { + return owner; + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/ItemWithSerializer.java b/jackson/src/test/java/com/baeldung/jackson/dtos/ItemWithSerializer.java new file mode 100644 index 0000000000..aea9aa770d --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/ItemWithSerializer.java @@ -0,0 +1,36 @@ +package com.baeldung.jackson.dtos; + +import com.baeldung.jackson.deserialization.ItemDeserializerOnClass; +import com.baeldung.jackson.serialization.ItemSerializerOnClass; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +@JsonSerialize(using = ItemSerializerOnClass.class) +@JsonDeserialize(using = ItemDeserializerOnClass.class) +public class ItemWithSerializer { + public final int id; + public final String itemName; + public final User owner; + + public ItemWithSerializer(final int id, final String itemName, final User owner) { + this.id = id; + this.itemName = itemName; + this.owner = owner; + } + + // API + + public int getId() { + return id; + } + + public String getItemName() { + return itemName; + } + + public User getOwner() { + return owner; + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDto.java b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDto.java new file mode 100644 index 0000000000..49cf07baea --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDto.java @@ -0,0 +1,54 @@ +package com.baeldung.jackson.dtos; + +public class MyDto { + + private String stringValue; + private int intValue; + private boolean booleanValue; + + public MyDto() { + super(); + } + + public MyDto(final String stringValue, final int intValue, final boolean booleanValue) { + super(); + + this.stringValue = stringValue; + this.intValue = intValue; + this.booleanValue = booleanValue; + } + + // API + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(final String stringValue) { + this.stringValue = stringValue; + } + + public int getIntValue() { + return intValue; + } + + public void setIntValue(final int intValue) { + this.intValue = intValue; + } + + public boolean isBooleanValue() { + return booleanValue; + } + + public void setBooleanValue(final boolean booleanValue) { + this.booleanValue = booleanValue; + } + + // + + @Override + public String toString() { + return "MyDto [stringValue=" + stringValue + ", intValue=" + intValue + ", booleanValue=" + booleanValue + "]"; + } + +} diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoFieldNameChanged.java b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java similarity index 96% rename from jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoFieldNameChanged.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java index 9c4086a965..ce7086f1fe 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoFieldNameChanged.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos; +package com.baeldung.jackson.dtos; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java similarity index 96% rename from jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java index b99d793363..ca03a8be62 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos; +package com.baeldung.jackson.dtos; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoNoAccessors.java b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java similarity index 92% rename from jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoNoAccessors.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java index 6e88f5a2db..6e9abc90ae 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoNoAccessors.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos; +package com.baeldung.jackson.dtos; public class MyDtoNoAccessors { diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java similarity index 94% rename from jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java index 1723a71230..149969f769 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos; +package com.baeldung.jackson.dtos; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoWithFilter.java b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java similarity index 96% rename from jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoWithFilter.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java index 03d7edf985..91f5e148b2 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDtoWithFilter.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos; +package com.baeldung.jackson.dtos; import com.fasterxml.jackson.annotation.JsonFilter; diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java new file mode 100644 index 0000000000..58293c0562 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java @@ -0,0 +1,54 @@ +package com.baeldung.jackson.dtos; + +public class MyDtoWithSpecialField { + + private String[] stringValue; + private int intValue; + private boolean booleanValue; + + public MyDtoWithSpecialField() { + super(); + } + + public MyDtoWithSpecialField(final String[] stringValue, final int intValue, final boolean booleanValue) { + super(); + + this.stringValue = stringValue; + this.intValue = intValue; + this.booleanValue = booleanValue; + } + + // API + + public String[] getStringValue() { + return stringValue; + } + + public void setStringValue(final String[] stringValue) { + this.stringValue = stringValue; + } + + public int getIntValue() { + return intValue; + } + + public void setIntValue(final int intValue) { + this.intValue = intValue; + } + + public boolean isBooleanValue() { + return booleanValue; + } + + public void setBooleanValue(final boolean booleanValue) { + this.booleanValue = booleanValue; + } + + // + + @Override + public String toString() { + return "MyDto [stringValue=" + stringValue + ", intValue=" + intValue + ", booleanValue=" + booleanValue + "]"; + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java b/jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java new file mode 100644 index 0000000000..ca29c98b9a --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java @@ -0,0 +1,8 @@ +package com.baeldung.jackson.dtos; + +import com.fasterxml.jackson.annotation.JsonIgnoreType; + +@JsonIgnoreType +public class MyMixInForIgnoreType { + // +} diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/User.java b/jackson/src/test/java/com/baeldung/jackson/dtos/User.java new file mode 100644 index 0000000000..2418e8070d --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/User.java @@ -0,0 +1,26 @@ +package com.baeldung.jackson.dtos; + +public class User { + public int id; + public String name; + + public User() { + super(); + } + + public User(final int id, final String name) { + this.id = id; + this.name = name; + } + + // API + + public int getId() { + return id; + } + + public String getName() { + return name; + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java b/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java similarity index 94% rename from jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java index 4e3aecd0d2..f573501e85 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.ignore; +package com.baeldung.jackson.dtos.ignore; import com.fasterxml.jackson.annotation.JsonIgnore; diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java b/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java similarity index 95% rename from jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java index d752e0576d..e7b8ea2a8e 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.ignore; +package com.baeldung.jackson.dtos.ignore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java b/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java similarity index 96% rename from jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java index 0e28e43024..bc443500a1 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.ignore; +package com.baeldung.jackson.dtos.ignore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreType.java b/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreType.java similarity index 96% rename from jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreType.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreType.java index 58876aec79..3c813145f6 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreType.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreType.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.ignore; +package com.baeldung.jackson.dtos.ignore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreUnknown.java b/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreUnknown.java similarity index 96% rename from jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreUnknown.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreUnknown.java index ca702343eb..c1174a12f5 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/ignore/MyDtoIgnoreUnknown.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreUnknown.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.ignore; +package com.baeldung.jackson.dtos.ignore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/MyDtoWithEnum.java b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/MyDtoWithEnum.java similarity index 96% rename from jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/MyDtoWithEnum.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/MyDtoWithEnum.java index aa05539b89..258eb6febd 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/MyDtoWithEnum.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/MyDtoWithEnum.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.withEnum; +package com.baeldung.jackson.dtos.withEnum; public class MyDtoWithEnum { diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/MyDtoWithEnumCustom.java b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/MyDtoWithEnumCustom.java similarity index 96% rename from jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/MyDtoWithEnumCustom.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/MyDtoWithEnumCustom.java index b58ea4bd15..676e22686e 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/MyDtoWithEnumCustom.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/MyDtoWithEnumCustom.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.withEnum; +package com.baeldung.jackson.dtos.withEnum; public class MyDtoWithEnumCustom { diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnum.java b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnum.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnum.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnum.java index 316fdb12e7..e0c9718330 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnum.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnum.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.withEnum; +package com.baeldung.jackson.dtos.withEnum; import com.fasterxml.jackson.annotation.JsonFormat; diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnumSimple.java b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnumSimple.java similarity index 92% rename from jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnumSimple.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnumSimple.java index b76a5740ec..477db67069 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnumSimple.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnumSimple.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.withEnum; +package com.baeldung.jackson.dtos.withEnum; public enum TypeEnumSimple { TYPE1(1, "Type A"), TYPE2(2, "Type 2"); diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnumWithCustomSerializer.java b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnumWithCustomSerializer.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnumWithCustomSerializer.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnumWithCustomSerializer.java index 7e004d2d7d..e7c2859dd1 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnumWithCustomSerializer.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnumWithCustomSerializer.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.withEnum; +package com.baeldung.jackson.dtos.withEnum; import com.fasterxml.jackson.databind.annotation.JsonSerialize; diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnumWithValue.java b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnumWithValue.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnumWithValue.java rename to jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnumWithValue.java index cf104df473..c5ddf222ff 100644 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeEnumWithValue.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeEnumWithValue.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.dtos.withEnum; +package com.baeldung.jackson.dtos.withEnum; import com.fasterxml.jackson.annotation.JsonValue; diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeSerializer.java b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeSerializer.java new file mode 100644 index 0000000000..fc5011137c --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/withEnum/TypeSerializer.java @@ -0,0 +1,32 @@ +package com.baeldung.jackson.dtos.withEnum; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class TypeSerializer extends StdSerializer { + + private static final long serialVersionUID = -7650668914169390772L; + + public TypeSerializer() { + this(null); + } + + public TypeSerializer(final Class t) { + super(t); + } + + @Override + public void serialize(final TypeEnumWithCustomSerializer value, final JsonGenerator generator, final SerializerProvider provider) throws IOException, JsonProcessingException { + generator.writeStartObject(); + generator.writeFieldName("id"); + generator.writeNumber(value.getId()); + generator.writeFieldName("name"); + generator.writeString(value.getName()); + generator.writeEndObject(); + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/Address.java b/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/Address.java new file mode 100644 index 0000000000..c2d2e84d45 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/Address.java @@ -0,0 +1,41 @@ +package com.baeldung.jackson.dynamicIgnore; + + +public class Address implements Hidable { + private String city; + private String country; + private boolean hidden; + + public Address(final String city, final String country, final boolean hidden) { + super(); + this.city = city; + this.country = country; + this.hidden = hidden; + } + + public String getCity() { + return city; + } + + public void setCity(final String city) { + this.city = city; + } + + public String getCountry() { + return country; + } + + public void setCountry(final String country) { + this.country = country; + } + + @Override + public boolean isHidden() { + return hidden; + } + + public void setHidden(final boolean hidden) { + this.hidden = hidden; + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/Hidable.java b/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/Hidable.java new file mode 100644 index 0000000000..edca786432 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/Hidable.java @@ -0,0 +1,9 @@ +package com.baeldung.jackson.dynamicIgnore; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + + +@JsonIgnoreProperties("hidden") +public interface Hidable { + boolean isHidden(); +} diff --git a/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/HidableSerializer.java b/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/HidableSerializer.java new file mode 100644 index 0000000000..46396dae2a --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/HidableSerializer.java @@ -0,0 +1,29 @@ +package com.baeldung.jackson.dynamicIgnore; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +public class HidableSerializer extends JsonSerializer { + + private JsonSerializer defaultSerializer; + + public HidableSerializer(final JsonSerializer serializer) { + defaultSerializer = serializer; + } + + @Override + public void serialize(final Hidable value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { + if (value.isHidden()) + return; + defaultSerializer.serialize(value, jgen, provider); + } + + @Override + public boolean isEmpty(final SerializerProvider provider, final Hidable value) { + return (value == null || value.isHidden()); + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/Person.java b/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/Person.java new file mode 100644 index 0000000000..366f611edf --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dynamicIgnore/Person.java @@ -0,0 +1,41 @@ +package com.baeldung.jackson.dynamicIgnore; + + +public class Person implements Hidable { + private String name; + private Address address; + private boolean hidden; + + public Person(final String name, final Address address, final boolean hidden) { + super(); + this.name = name; + this.address = address; + this.hidden = hidden; + } + + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(final Address address) { + this.address = address; + } + @Override + public boolean isHidden() { + return hidden; + } + + public void setHidden(final boolean hidden) { + this.hidden = hidden; + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/exception/User.java b/jackson/src/test/java/com/baeldung/jackson/exception/User.java new file mode 100644 index 0000000000..1d78e82bec --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/exception/User.java @@ -0,0 +1,11 @@ +package com.baeldung.jackson.exception; + +public class User { + public int id; + public String name; + + public User(final int id, final String name) { + this.id = id; + this.name = name; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/exception/UserWithConflict.java b/jackson/src/test/java/com/baeldung/jackson/exception/UserWithConflict.java similarity index 91% rename from jackson/src/test/java/org/baeldung/jackson/exception/UserWithConflict.java rename to jackson/src/test/java/com/baeldung/jackson/exception/UserWithConflict.java index 79d4199e91..01ff695475 100644 --- a/jackson/src/test/java/org/baeldung/jackson/exception/UserWithConflict.java +++ b/jackson/src/test/java/com/baeldung/jackson/exception/UserWithConflict.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.exception; +package com.baeldung.jackson.exception; public class UserWithConflict { public int id; diff --git a/jackson/src/test/java/org/baeldung/jackson/exception/UserWithPrivateFields.java b/jackson/src/test/java/com/baeldung/jackson/exception/UserWithPrivateFields.java similarity index 86% rename from jackson/src/test/java/org/baeldung/jackson/exception/UserWithPrivateFields.java rename to jackson/src/test/java/com/baeldung/jackson/exception/UserWithPrivateFields.java index 707623bbb2..f627975184 100644 --- a/jackson/src/test/java/org/baeldung/jackson/exception/UserWithPrivateFields.java +++ b/jackson/src/test/java/com/baeldung/jackson/exception/UserWithPrivateFields.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.exception; +package com.baeldung.jackson.exception; public class UserWithPrivateFields { int id; diff --git a/jackson/src/test/java/org/baeldung/jackson/exception/UserWithRoot.java b/jackson/src/test/java/com/baeldung/jackson/exception/UserWithRoot.java similarity index 89% rename from jackson/src/test/java/org/baeldung/jackson/exception/UserWithRoot.java rename to jackson/src/test/java/com/baeldung/jackson/exception/UserWithRoot.java index 2cf78e0365..d879c16e6a 100644 --- a/jackson/src/test/java/org/baeldung/jackson/exception/UserWithRoot.java +++ b/jackson/src/test/java/com/baeldung/jackson/exception/UserWithRoot.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.exception; +package com.baeldung.jackson.exception; import com.fasterxml.jackson.annotation.JsonRootName; diff --git a/jackson/src/test/java/com/baeldung/jackson/exception/Zoo.java b/jackson/src/test/java/com/baeldung/jackson/exception/Zoo.java new file mode 100644 index 0000000000..647b5955c0 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/exception/Zoo.java @@ -0,0 +1,22 @@ +package com.baeldung.jackson.exception; + +public class Zoo { + public Animal animal; + + public Zoo() { + } +} + +abstract class Animal { + public String name; + + public Animal() { + } +} + +class Cat extends Animal { + public int lives; + + public Cat() { + } +} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/exception/ZooConfigured.java b/jackson/src/test/java/com/baeldung/jackson/exception/ZooConfigured.java similarity index 91% rename from jackson/src/test/java/org/baeldung/jackson/exception/ZooConfigured.java rename to jackson/src/test/java/com/baeldung/jackson/exception/ZooConfigured.java index 776b702acb..f51b1e150a 100644 --- a/jackson/src/test/java/org/baeldung/jackson/exception/ZooConfigured.java +++ b/jackson/src/test/java/com/baeldung/jackson/exception/ZooConfigured.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.exception; +package com.baeldung.jackson.exception; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; diff --git a/jackson/src/test/java/com/baeldung/jackson/field/MyDto.java b/jackson/src/test/java/com/baeldung/jackson/field/MyDto.java new file mode 100644 index 0000000000..f19371937d --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/field/MyDto.java @@ -0,0 +1,47 @@ +package com.baeldung.jackson.field; + +public class MyDto { + + private String stringValue; + private int intValue; + private boolean booleanValue; + + public MyDto() { + super(); + } + + public MyDto(final String stringValue, final int intValue, final boolean booleanValue) { + super(); + + this.stringValue = stringValue; + this.intValue = intValue; + this.booleanValue = booleanValue; + } + + // API + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(final String stringValue) { + this.stringValue = stringValue; + } + + public int getIntValue() { + return intValue; + } + + public void setIntValue(final int intValue) { + this.intValue = intValue; + } + + public boolean getBooleanValue() { + return booleanValue; + } + + public void setBooleanValue(final boolean booleanValue) { + this.booleanValue = booleanValue; + } + +} diff --git a/jackson/src/test/java/org/baeldung/jackson/field/MyDtoAccessLevel.java b/jackson/src/test/java/com/baeldung/jackson/field/MyDtoAccessLevel.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/field/MyDtoAccessLevel.java rename to jackson/src/test/java/com/baeldung/jackson/field/MyDtoAccessLevel.java index c164b00e4a..df16720038 100644 --- a/jackson/src/test/java/org/baeldung/jackson/field/MyDtoAccessLevel.java +++ b/jackson/src/test/java/com/baeldung/jackson/field/MyDtoAccessLevel.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.field; +package com.baeldung.jackson.field; public class MyDtoAccessLevel { diff --git a/jackson/src/test/java/org/baeldung/jackson/field/MyDtoWithGetter.java b/jackson/src/test/java/com/baeldung/jackson/field/MyDtoWithGetter.java similarity index 91% rename from jackson/src/test/java/org/baeldung/jackson/field/MyDtoWithGetter.java rename to jackson/src/test/java/com/baeldung/jackson/field/MyDtoWithGetter.java index 0f15b2fcc3..4ea20b93c1 100644 --- a/jackson/src/test/java/org/baeldung/jackson/field/MyDtoWithGetter.java +++ b/jackson/src/test/java/com/baeldung/jackson/field/MyDtoWithGetter.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.field; +package com.baeldung.jackson.field; public class MyDtoWithGetter { diff --git a/jackson/src/test/java/org/baeldung/jackson/field/MyDtoWithSetter.java b/jackson/src/test/java/com/baeldung/jackson/field/MyDtoWithSetter.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/field/MyDtoWithSetter.java rename to jackson/src/test/java/com/baeldung/jackson/field/MyDtoWithSetter.java index e37793492e..fd3f6790a3 100644 --- a/jackson/src/test/java/org/baeldung/jackson/field/MyDtoWithSetter.java +++ b/jackson/src/test/java/com/baeldung/jackson/field/MyDtoWithSetter.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.field; +package com.baeldung.jackson.field; public class MyDtoWithSetter { diff --git a/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceAnnotationStructure.java b/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceAnnotationStructure.java new file mode 100644 index 0000000000..520929463c --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceAnnotationStructure.java @@ -0,0 +1,96 @@ +package com.baeldung.jackson.inheritance; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +public class IgnoranceAnnotationStructure { + public static abstract class Vehicle { + private String make; + private String model; + + protected Vehicle() { + } + + protected Vehicle(String make, String model) { + this.make = make; + this.model = model; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + } + + @JsonIgnoreProperties({ "model", "seatingCapacity" }) + public static abstract class Car extends Vehicle { + private int seatingCapacity; + @JsonIgnore + private double topSpeed; + + protected Car() { + } + + protected Car(String make, String model, int seatingCapacity, double topSpeed) { + super(make, model); + this.seatingCapacity = seatingCapacity; + this.topSpeed = topSpeed; + } + + public int getSeatingCapacity() { + return seatingCapacity; + } + + public void setSeatingCapacity(int seatingCapacity) { + this.seatingCapacity = seatingCapacity; + } + + public double getTopSpeed() { + return topSpeed; + } + + public void setTopSpeed(double topSpeed) { + this.topSpeed = topSpeed; + } + } + + public static class Sedan extends Car { + public Sedan() { + } + + public Sedan(String make, String model, int seatingCapacity, double topSpeed) { + super(make, model, seatingCapacity, topSpeed); + } + } + + public static class Crossover extends Car { + private double towingCapacity; + + public Crossover() { + } + + public Crossover(String make, String model, int seatingCapacity, double topSpeed, double towingCapacity) { + super(make, model, seatingCapacity, topSpeed); + this.towingCapacity = towingCapacity; + } + + public double getTowingCapacity() { + return towingCapacity; + } + + public void setTowingCapacity(double towingCapacity) { + this.towingCapacity = towingCapacity; + } + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceMixinOrIntrospection.java b/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceMixinOrIntrospection.java new file mode 100644 index 0000000000..52c0bbea5e --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceMixinOrIntrospection.java @@ -0,0 +1,91 @@ +package com.baeldung.jackson.inheritance; + +public class IgnoranceMixinOrIntrospection { + public static abstract class Vehicle { + private String make; + private String model; + + protected Vehicle() { + } + + protected Vehicle(String make, String model) { + this.make = make; + this.model = model; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + } + + public static abstract class Car extends Vehicle { + private int seatingCapacity; + private double topSpeed; + + protected Car() { + } + + protected Car(String make, String model, int seatingCapacity, double topSpeed) { + super(make, model); + this.seatingCapacity = seatingCapacity; + this.topSpeed = topSpeed; + } + + public int getSeatingCapacity() { + return seatingCapacity; + } + + public void setSeatingCapacity(int seatingCapacity) { + this.seatingCapacity = seatingCapacity; + } + + public double getTopSpeed() { + return topSpeed; + } + + public void setTopSpeed(double topSpeed) { + this.topSpeed = topSpeed; + } + } + + public static class Sedan extends Car { + public Sedan() { + } + + public Sedan(String make, String model, int seatingCapacity, double topSpeed) { + super(make, model, seatingCapacity, topSpeed); + } + } + + public static class Crossover extends Car { + private double towingCapacity; + + public Crossover() { + } + + public Crossover(String make, String model, int seatingCapacity, double topSpeed, double towingCapacity) { + super(make, model, seatingCapacity, topSpeed); + this.towingCapacity = towingCapacity; + } + + public double getTowingCapacity() { + return towingCapacity; + } + + public void setTowingCapacity(double towingCapacity) { + this.towingCapacity = towingCapacity; + } + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceTest.java b/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceTest.java new file mode 100644 index 0000000000..8d22f471a6 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/inheritance/IgnoranceTest.java @@ -0,0 +1,92 @@ +package com.baeldung.jackson.inheritance; + +import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.not; + +import org.junit.Test; + +import java.util.List; +import java.util.ArrayList; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.AnnotatedMember; +import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; + +public class IgnoranceTest { + private static abstract class CarMixIn { + @JsonIgnore + public String make; + @JsonIgnore + public String topSpeed; + } + + private static class IgnoranceIntrospector extends JacksonAnnotationIntrospector { + private static final long serialVersionUID = 1422295680188892323L; + + public boolean hasIgnoreMarker(AnnotatedMember m) { + return m.getDeclaringClass() == IgnoranceMixinOrIntrospection.Vehicle.class && m.getName() == "model" || m.getDeclaringClass() == IgnoranceMixinOrIntrospection.Car.class || m.getName() == "towingCapacity" || super.hasIgnoreMarker(m); + } + } + + @Test + public void givenAnnotations_whenIgnoringProperties_thenCorrect() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + + IgnoranceAnnotationStructure.Sedan sedan = new IgnoranceAnnotationStructure.Sedan("Mercedes-Benz", "S500", 5, 250.0); + IgnoranceAnnotationStructure.Crossover crossover = new IgnoranceAnnotationStructure.Crossover("BMW", "X6", 5, 250.0, 6000.0); + + List vehicles = new ArrayList<>(); + vehicles.add(sedan); + vehicles.add(crossover); + + String jsonDataString = mapper.writeValueAsString(vehicles); + + assertThat(jsonDataString, containsString("make")); + assertThat(jsonDataString, not(containsString("model"))); + assertThat(jsonDataString, not(containsString("seatingCapacity"))); + assertThat(jsonDataString, not(containsString("topSpeed"))); + assertThat(jsonDataString, containsString("towingCapacity")); + } + + @Test + public void givenMixIns_whenIgnoringProperties_thenCorrect() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + mapper.addMixIn(IgnoranceMixinOrIntrospection.Car.class, CarMixIn.class); + + String jsonDataString = instantiateAndSerializeObjects(mapper); + + assertThat(jsonDataString, not(containsString("make"))); + assertThat(jsonDataString, containsString("model")); + assertThat(jsonDataString, containsString("seatingCapacity")); + assertThat(jsonDataString, not(containsString("topSpeed"))); + assertThat(jsonDataString, containsString("towingCapacity")); + } + + @Test + public void givenIntrospection_whenIgnoringProperties_thenCorrect() throws JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new IgnoranceIntrospector()); + + String jsonDataString = instantiateAndSerializeObjects(mapper); + + assertThat(jsonDataString, containsString("make")); + assertThat(jsonDataString, not(containsString("model"))); + assertThat(jsonDataString, not(containsString("seatingCapacity"))); + assertThat(jsonDataString, not(containsString("topSpeed"))); + assertThat(jsonDataString, not(containsString("towingCapacity"))); + } + + private String instantiateAndSerializeObjects(ObjectMapper mapper) throws JsonProcessingException { + IgnoranceMixinOrIntrospection.Sedan sedan = new IgnoranceMixinOrIntrospection.Sedan("Mercedes-Benz", "S500", 5, 250.0); + IgnoranceMixinOrIntrospection.Crossover crossover = new IgnoranceMixinOrIntrospection.Crossover("BMW", "X6", 5, 250.0, 6000.0); + + List vehicles = new ArrayList<>(); + vehicles.add(sedan); + vehicles.add(crossover); + + return mapper.writeValueAsString(vehicles); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeConstructorStructure.java b/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeConstructorStructure.java new file mode 100644 index 0000000000..8a8db8ae47 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeConstructorStructure.java @@ -0,0 +1,92 @@ +package com.baeldung.jackson.inheritance; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class SubTypeConstructorStructure { + public static class Fleet { + private List vehicles; + + public List getVehicles() { + return vehicles; + } + + public void setVehicles(List vehicles) { + this.vehicles = vehicles; + } + } + + public static abstract class Vehicle { + private String make; + private String model; + + protected Vehicle(String make, String model) { + this.make = make; + this.model = model; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + } + + public static class Car extends Vehicle { + private int seatingCapacity; + private double topSpeed; + + @JsonCreator + public Car(@JsonProperty("make") String make, @JsonProperty("model") String model, @JsonProperty("seating") int seatingCapacity, @JsonProperty("topSpeed") double topSpeed) { + super(make, model); + this.seatingCapacity = seatingCapacity; + this.topSpeed = topSpeed; + } + + public int getSeatingCapacity() { + return seatingCapacity; + } + + public void setSeatingCapacity(int seatingCapacity) { + this.seatingCapacity = seatingCapacity; + } + + public double getTopSpeed() { + return topSpeed; + } + + public void setTopSpeed(double topSpeed) { + this.topSpeed = topSpeed; + } + } + + public static class Truck extends Vehicle { + private double payloadCapacity; + + @JsonCreator + public Truck(@JsonProperty("make") String make, @JsonProperty("model") String model, @JsonProperty("payload") double payloadCapacity) { + super(make, model); + this.payloadCapacity = payloadCapacity; + } + + public double getPayloadCapacity() { + return payloadCapacity; + } + + public void setPayloadCapacity(double payloadCapacity) { + this.payloadCapacity = payloadCapacity; + } + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeConversionStructure.java b/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeConversionStructure.java new file mode 100644 index 0000000000..346fd65eef --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeConversionStructure.java @@ -0,0 +1,87 @@ +package com.baeldung.jackson.inheritance; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class SubTypeConversionStructure { + public static abstract class Vehicle { + private String make; + private String model; + + protected Vehicle() { + } + + protected Vehicle(String make, String model) { + this.make = make; + this.model = model; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + } + + public static class Car extends Vehicle { + @JsonIgnore + private int seatingCapacity; + @JsonIgnore + private double topSpeed; + + public Car() { + } + + public Car(String make, String model, int seatingCapacity, double topSpeed) { + super(make, model); + this.seatingCapacity = seatingCapacity; + this.topSpeed = topSpeed; + } + + public int getSeatingCapacity() { + return seatingCapacity; + } + + public void setSeatingCapacity(int seatingCapacity) { + this.seatingCapacity = seatingCapacity; + } + + public double getTopSpeed() { + return topSpeed; + } + + public void setTopSpeed(double topSpeed) { + this.topSpeed = topSpeed; + } + } + + public static class Truck extends Vehicle { + @JsonIgnore + private double payloadCapacity; + + public Truck() { + } + + public Truck(String make, String model, double payloadCapacity) { + super(make, model); + this.payloadCapacity = payloadCapacity; + } + + public double getPayloadCapacity() { + return payloadCapacity; + } + + public void setPayloadCapacity(double payloadCapacity) { + this.payloadCapacity = payloadCapacity; + } + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeHandlingTest.java b/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeHandlingTest.java new file mode 100644 index 0000000000..2d4c8fe698 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/inheritance/SubTypeHandlingTest.java @@ -0,0 +1,43 @@ +package com.baeldung.jackson.inheritance; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import java.util.List; +import java.util.ArrayList; +import java.io.IOException; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class SubTypeHandlingTest { + @Test + public void givenSubTypes_whenConvertingObjects_thenDataValuesArePreserved() { + ObjectMapper mapper = new ObjectMapper(); + + SubTypeConversionStructure.Car car = new SubTypeConversionStructure.Car("Mercedes-Benz", "S500", 5, 250.0); + SubTypeConversionStructure.Truck truck = mapper.convertValue(car, SubTypeConversionStructure.Truck.class); + + assertEquals("Mercedes-Benz", truck.getMake()); + assertEquals("S500", truck.getModel()); + } + + @Test + public void givenSubType_whenNotUsingNoArgsConstructors_thenSucceed() throws IOException{ + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(); + + SubTypeConstructorStructure.Car car = new SubTypeConstructorStructure.Car("Mercedes-Benz", "S500", 5, 250.0); + SubTypeConstructorStructure.Truck truck = new SubTypeConstructorStructure.Truck("Isuzu", "NQR", 7500.0); + + List vehicles = new ArrayList<>(); + vehicles.add(car); + vehicles.add(truck); + + SubTypeConstructorStructure.Fleet serializedFleet = new SubTypeConstructorStructure.Fleet(); + serializedFleet.setVehicles(vehicles); + + String jsonDataString = mapper.writeValueAsString(serializedFleet); + mapper.readValue(jsonDataString, SubTypeConstructorStructure.Fleet.class); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoAnnotatedStructure.java b/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoAnnotatedStructure.java new file mode 100644 index 0000000000..cb552a7b80 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoAnnotatedStructure.java @@ -0,0 +1,102 @@ +package com.baeldung.jackson.inheritance; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonSubTypes.Type; + +public class TypeInfoAnnotatedStructure { + public static class Fleet { + private List vehicles; + + public List getVehicles() { + return vehicles; + } + + public void setVehicles(List vehicles) { + this.vehicles = vehicles; + } + } + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") + @JsonSubTypes({ @Type(value = Car.class, name = "car"), @Type(value = Truck.class, name = "truck") }) + public static abstract class Vehicle { + private String make; + private String model; + + protected Vehicle() { + } + + protected Vehicle(String make, String model) { + this.make = make; + this.model = model; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + } + + public static class Car extends Vehicle { + private int seatingCapacity; + private double topSpeed; + + public Car() { + } + + public Car(String make, String model, int seatingCapacity, double topSpeed) { + super(make, model); + this.seatingCapacity = seatingCapacity; + this.topSpeed = topSpeed; + } + + public int getSeatingCapacity() { + return seatingCapacity; + } + + public void setSeatingCapacity(int seatingCapacity) { + this.seatingCapacity = seatingCapacity; + } + + public double getTopSpeed() { + return topSpeed; + } + + public void setTopSpeed(double topSpeed) { + this.topSpeed = topSpeed; + } + } + + public static class Truck extends Vehicle { + private double payloadCapacity; + + public Truck() { + } + + public Truck(String make, String model, double payloadCapacity) { + super(make, model); + this.payloadCapacity = payloadCapacity; + } + + public double getPayloadCapacity() { + return payloadCapacity; + } + + public void setPayloadCapacity(double payloadCapacity) { + this.payloadCapacity = payloadCapacity; + } + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoInclusionTest.java b/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoInclusionTest.java new file mode 100644 index 0000000000..aefbc172d0 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoInclusionTest.java @@ -0,0 +1,57 @@ +package com.baeldung.jackson.inheritance; + +import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.instanceOf; + +import org.junit.Test; + +import java.util.List; +import java.util.ArrayList; +import java.io.IOException; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class TypeInfoInclusionTest { + @Test + public void givenTypeInfo_whenAnnotatingGlobally_thenTypesAreCorrectlyRecovered() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(); + + TypeInfoStructure.Car car = new TypeInfoStructure.Car("Mercedes-Benz", "S500", 5, 250.0); + TypeInfoStructure.Truck truck = new TypeInfoStructure.Truck("Isuzu", "NQR", 7500.0); + + List vehicles = new ArrayList<>(); + vehicles.add(car); + vehicles.add(truck); + + TypeInfoStructure.Fleet serializedFleet = new TypeInfoStructure.Fleet(); + serializedFleet.setVehicles(vehicles); + + String jsonDataString = mapper.writeValueAsString(serializedFleet); + TypeInfoStructure.Fleet deserializedFleet = mapper.readValue(jsonDataString, TypeInfoStructure.Fleet.class); + + assertThat(deserializedFleet.getVehicles().get(0), instanceOf(TypeInfoStructure.Car.class)); + assertThat(deserializedFleet.getVehicles().get(1), instanceOf(TypeInfoStructure.Truck.class)); + } + + @Test + public void givenTypeInfo_whenAnnotatingPerClass_thenTypesAreCorrectlyRecovered() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + + TypeInfoAnnotatedStructure.Car car = new TypeInfoAnnotatedStructure.Car("Mercedes-Benz", "S500", 5, 250.0); + TypeInfoAnnotatedStructure.Truck truck = new TypeInfoAnnotatedStructure.Truck("Isuzu", "NQR", 7500.0); + + List vehicles = new ArrayList<>(); + vehicles.add(car); + vehicles.add(truck); + + TypeInfoAnnotatedStructure.Fleet serializedFleet = new TypeInfoAnnotatedStructure.Fleet(); + serializedFleet.setVehicles(vehicles); + + String jsonDataString = mapper.writeValueAsString(serializedFleet); + TypeInfoAnnotatedStructure.Fleet deserializedFleet = mapper.readValue(jsonDataString, TypeInfoAnnotatedStructure.Fleet.class); + + assertThat(deserializedFleet.getVehicles().get(0), instanceOf(TypeInfoAnnotatedStructure.Car.class)); + assertThat(deserializedFleet.getVehicles().get(1), instanceOf(TypeInfoAnnotatedStructure.Truck.class)); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoStructure.java b/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoStructure.java new file mode 100644 index 0000000000..5c5186dfcc --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/inheritance/TypeInfoStructure.java @@ -0,0 +1,96 @@ +package com.baeldung.jackson.inheritance; + +import java.util.List; + +public class TypeInfoStructure { + public static class Fleet { + private List vehicles; + + public List getVehicles() { + return vehicles; + } + + public void setVehicles(List vehicles) { + this.vehicles = vehicles; + } + } + + public static abstract class Vehicle { + private String make; + private String model; + + protected Vehicle() { + } + + protected Vehicle(String make, String model) { + this.make = make; + this.model = model; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + } + + public static class Car extends Vehicle { + private int seatingCapacity; + private double topSpeed; + + public Car() { + } + + public Car(String make, String model, int seatingCapacity, double topSpeed) { + super(make, model); + this.seatingCapacity = seatingCapacity; + this.topSpeed = topSpeed; + } + + public int getSeatingCapacity() { + return seatingCapacity; + } + + public void setSeatingCapacity(int seatingCapacity) { + this.seatingCapacity = seatingCapacity; + } + + public double getTopSpeed() { + return topSpeed; + } + + public void setTopSpeed(double topSpeed) { + this.topSpeed = topSpeed; + } + } + + public static class Truck extends Vehicle { + private double payloadCapacity; + + public Truck() { + } + + public Truck(String make, String model, double payloadCapacity) { + super(make, model); + this.payloadCapacity = payloadCapacity; + } + + public double getPayloadCapacity() { + return payloadCapacity; + } + + public void setPayloadCapacity(double payloadCapacity) { + this.payloadCapacity = payloadCapacity; + } + } +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/jsonview/Item.java b/jackson/src/test/java/com/baeldung/jackson/jsonview/Item.java new file mode 100644 index 0000000000..26d20d4847 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/jsonview/Item.java @@ -0,0 +1,36 @@ +package com.baeldung.jackson.jsonview; + +import com.fasterxml.jackson.annotation.JsonView; + +public class Item { + @JsonView(Views.Public.class) + public int id; + + @JsonView(Views.Public.class) + public String itemName; + + @JsonView(Views.Internal.class) + public String ownerName; + + public Item() { + super(); + } + + public Item(final int id, final String itemName, final String ownerName) { + this.id = id; + this.itemName = itemName; + this.ownerName = ownerName; + } + + public int getId() { + return id; + } + + public String getItemName() { + return itemName; + } + + public String getOwnerName() { + return ownerName; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/jsonview/MyBeanSerializerModifier.java b/jackson/src/test/java/com/baeldung/jackson/jsonview/MyBeanSerializerModifier.java similarity index 95% rename from jackson/src/test/java/org/baeldung/jackson/jsonview/MyBeanSerializerModifier.java rename to jackson/src/test/java/com/baeldung/jackson/jsonview/MyBeanSerializerModifier.java index 0986e5ea76..3b94c13d8b 100644 --- a/jackson/src/test/java/org/baeldung/jackson/jsonview/MyBeanSerializerModifier.java +++ b/jackson/src/test/java/com/baeldung/jackson/jsonview/MyBeanSerializerModifier.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.jsonview; +package com.baeldung.jackson.jsonview; import java.util.List; diff --git a/jackson/src/test/java/org/baeldung/jackson/jsonview/UpperCasingWriter.java b/jackson/src/test/java/com/baeldung/jackson/jsonview/UpperCasingWriter.java similarity index 94% rename from jackson/src/test/java/org/baeldung/jackson/jsonview/UpperCasingWriter.java rename to jackson/src/test/java/com/baeldung/jackson/jsonview/UpperCasingWriter.java index 948fb36cda..3a69d66a05 100644 --- a/jackson/src/test/java/org/baeldung/jackson/jsonview/UpperCasingWriter.java +++ b/jackson/src/test/java/com/baeldung/jackson/jsonview/UpperCasingWriter.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.jsonview; +package com.baeldung.jackson.jsonview; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; diff --git a/jackson/src/test/java/com/baeldung/jackson/jsonview/User.java b/jackson/src/test/java/com/baeldung/jackson/jsonview/User.java new file mode 100644 index 0000000000..48353fe4e4 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/jsonview/User.java @@ -0,0 +1,27 @@ +package com.baeldung.jackson.jsonview; + +import com.fasterxml.jackson.annotation.JsonView; + +public class User { + public int id; + + @JsonView(Views.Public.class) + public String name; + + public User() { + super(); + } + + public User(final int id, final String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/jsonview/Views.java b/jackson/src/test/java/com/baeldung/jackson/jsonview/Views.java similarity index 75% rename from jackson/src/test/java/org/baeldung/jackson/jsonview/Views.java rename to jackson/src/test/java/com/baeldung/jackson/jsonview/Views.java index 0a430ad123..65950b7f9f 100644 --- a/jackson/src/test/java/org/baeldung/jackson/jsonview/Views.java +++ b/jackson/src/test/java/com/baeldung/jackson/jsonview/Views.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.jsonview; +package com.baeldung.jackson.jsonview; public class Views { public static class Public { diff --git a/jackson/src/test/java/org/baeldung/jackson/node/ExampleStructure.java b/jackson/src/test/java/com/baeldung/jackson/node/ExampleStructure.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/node/ExampleStructure.java rename to jackson/src/test/java/com/baeldung/jackson/node/ExampleStructure.java index 0eb15f3bb8..14f9024d0b 100644 --- a/jackson/src/test/java/org/baeldung/jackson/node/ExampleStructure.java +++ b/jackson/src/test/java/com/baeldung/jackson/node/ExampleStructure.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.node; +package com.baeldung.jackson.node; import java.io.IOException; import java.io.InputStream; diff --git a/jackson/src/test/java/org/baeldung/jackson/node/NodeBean.java b/jackson/src/test/java/com/baeldung/jackson/node/NodeBean.java similarity index 92% rename from jackson/src/test/java/org/baeldung/jackson/node/NodeBean.java rename to jackson/src/test/java/com/baeldung/jackson/node/NodeBean.java index 7d54a6140e..da5ffece51 100644 --- a/jackson/src/test/java/org/baeldung/jackson/node/NodeBean.java +++ b/jackson/src/test/java/com/baeldung/jackson/node/NodeBean.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.node; +package com.baeldung.jackson.node; public class NodeBean { private int id; diff --git a/jackson/src/test/java/org/baeldung/jackson/node/NodeOperationTest.java b/jackson/src/test/java/com/baeldung/jackson/node/NodeOperationTest.java similarity index 99% rename from jackson/src/test/java/org/baeldung/jackson/node/NodeOperationTest.java rename to jackson/src/test/java/com/baeldung/jackson/node/NodeOperationTest.java index c1398b2165..2fcb828613 100644 --- a/jackson/src/test/java/org/baeldung/jackson/node/NodeOperationTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/node/NodeOperationTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.node; +package com.baeldung.jackson.node; import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.assertEquals; diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java new file mode 100644 index 0000000000..a3d0b377c6 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java @@ -0,0 +1,44 @@ +package com.baeldung.jackson.objectmapper; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +public class CustomCarDeserializer extends StdDeserializer { + + private static final long serialVersionUID = -5918629454846356161L; + private final Logger Logger = LoggerFactory.getLogger(getClass()); + + public CustomCarDeserializer() { + this(null); + } + + public CustomCarDeserializer(final Class vc) { + super(vc); + } + + + + @Override + public Car deserialize(final JsonParser parser, final DeserializationContext deserializer) throws IOException { + final Car car = new Car(); + final ObjectCodec codec = parser.getCodec(); + final JsonNode node = codec.readTree(parser); + try { + final JsonNode colorNode = node.get("color"); + final String color = colorNode.asText(); + car.setColor(color); + } catch (final Exception e) { + Logger.debug("101_parse_exeption: unknown json."); + } + return car; + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java new file mode 100644 index 0000000000..37bae829b7 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java @@ -0,0 +1,31 @@ +package com.baeldung.jackson.objectmapper; + +import java.io.IOException; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class CustomCarSerializer extends StdSerializer +{ + + private static final long serialVersionUID = 1396140685442227917L; + + public CustomCarSerializer() { + this(null); + } + + public CustomCarSerializer(final Class t) { + super(t); + } + + @Override + public void serialize(final Car car, final JsonGenerator jsonGenerator, final SerializerProvider serializer) throws IOException, JsonProcessingException + { + jsonGenerator.writeStartObject(); + jsonGenerator.writeStringField("model: ", car.getType()); + jsonGenerator.writeEndObject(); + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestJavaReadWriteJsonExample.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestJavaReadWriteJsonExample.java new file mode 100644 index 0000000000..54ddf469c8 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestJavaReadWriteJsonExample.java @@ -0,0 +1,68 @@ +package com.baeldung.jackson.objectmapper; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +public class TestJavaReadWriteJsonExample { + final String EXAMPLE_JSON = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; + final String LOCAL_JSON = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"BMW\" }]"; + + @Test + public void whenWriteJavaToJson_thanCorrect() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = new Car("yellow", "renault"); + final String carAsString = objectMapper.writeValueAsString(car); + assertThat(carAsString, containsString("yellow")); + assertThat(carAsString, containsString("renault")); + } + + @Test + public void whenReadJsonToJava_thanCorrect() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = objectMapper.readValue(EXAMPLE_JSON, Car.class); + assertNotNull(car); + assertThat(car.getColor(), containsString("Black")); + } + + @Test + public void whenReadJsonToJsonNode_thanCorrect() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final JsonNode jsonNode = objectMapper.readTree(EXAMPLE_JSON); + assertNotNull(jsonNode); + assertThat(jsonNode.get("color").asText(), containsString("Black")); + } + + @Test + public void whenReadJsonToList_thanCorrect() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final List listCar = objectMapper.readValue(LOCAL_JSON, new TypeReference>() { + + }); + for (final Car car : listCar) { + assertNotNull(car); + assertThat(car.getType(), equalTo("BMW")); + } + } + + @Test + public void whenReadJsonToMap_thanCorrect() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Map map = objectMapper.readValue(EXAMPLE_JSON, new TypeReference>() { + }); + assertNotNull(map); + for (final String key : map.keySet()) { + assertNotNull(key); + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestSerializationDeserializationFeature.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestSerializationDeserializationFeature.java new file mode 100644 index 0000000000..96918f4c28 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/TestSerializationDeserializationFeature.java @@ -0,0 +1,84 @@ +package com.baeldung.jackson.objectmapper; + +import com.baeldung.jackson.objectmapper.dto.Car; +import com.baeldung.jackson.objectmapper.dto.Request; +import com.fasterxml.jackson.core.Version; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.junit.Test; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +public class TestSerializationDeserializationFeature { + final String EXAMPLE_JSON = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }"; + final String JSON_CAR = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }"; + final String JSON_ARRAY = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"BMW\" }]"; + + @Test + public void whenFailOnUnkownPropertiesFalse_thanJsonReadCorrectly() throws Exception { + + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + final Car car = objectMapper.readValue(JSON_CAR, Car.class); + final JsonNode jsonNodeRoot = objectMapper.readTree(JSON_CAR); + final JsonNode jsonNodeYear = jsonNodeRoot.get("year"); + final String year = jsonNodeYear.asText(); + + assertNotNull(car); + assertThat(car.getColor(), equalTo("Black")); + assertThat(year, containsString("1970")); + } + + @Test + public void whenCustomSerializerDeserializer_thanReadWriteCorrect() throws Exception { + final ObjectMapper mapper = new ObjectMapper(); + final SimpleModule serializerModule = new SimpleModule("CustomSerializer", new Version(1, 0, 0, null, null, null)); + serializerModule.addSerializer(Car.class, new CustomCarSerializer()); + mapper.registerModule(serializerModule); + final Car car = new Car("yellow", "renault"); + final String carJson = mapper.writeValueAsString(car); + assertThat(carJson, containsString("renault")); + assertThat(carJson, containsString("model")); + + final SimpleModule deserializerModule = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null)); + deserializerModule.addDeserializer(Car.class, new CustomCarDeserializer()); + mapper.registerModule(deserializerModule); + final Car carResult = mapper.readValue(EXAMPLE_JSON, Car.class); + assertNotNull(carResult); + assertThat(carResult.getColor(), equalTo("Black")); + } + + @Test + public void whenDateFormatSet_thanSerializedAsExpected() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + final Car car = new Car("yellow", "renault"); + final Request request = new Request(); + request.setCar(car); + request.setDatePurchased(new Date()); + final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z"); + objectMapper.setDateFormat(df); + final String carAsString = objectMapper.writeValueAsString(request); + assertNotNull(carAsString); + assertThat(carAsString, containsString("datePurchased")); + } + + @Test + public void whenUseJavaArrayForJsonArrayTrue_thanJsonReadAsArray() throws Exception { + final ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); + final Car[] cars = objectMapper.readValue(JSON_ARRAY, Car[].class); + for (final Car car : cars) { + assertNotNull(car); + assertThat(car.getType(), equalTo("BMW")); + } + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java new file mode 100644 index 0000000000..bf4309439b --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java @@ -0,0 +1,31 @@ +package com.baeldung.jackson.objectmapper.dto; + +public class Car { + + private String color; + private String type; + + public Car() { + } + + public Car(final String color, final String type) { + this.color = color; + this.type = type; + } + + public String getColor() { + return color; + } + + public void setColor(final String color) { + this.color = color; + } + + public String getType() { + return type; + } + + public void setType(final String type) { + this.type = type; + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java b/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java new file mode 100644 index 0000000000..2a4cce0fdd --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java @@ -0,0 +1,24 @@ +package com.baeldung.jackson.objectmapper.dto; + +import java.util.Date; + +public class Request { + Car car; + Date datePurchased; + + public Car getCar() { + return car; + } + + public void setCar(final Car car) { + this.car = car; + } + + public Date getDatePurchased() { + return datePurchased; + } + + public void setDatePurchased(final Date datePurchased) { + this.datePurchased = datePurchased; + } +} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java similarity index 97% rename from jackson/src/test/java/org/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java rename to jackson/src/test/java/com/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java index 58dcec51f6..a68af20f15 100644 --- a/jackson/src/test/java/org/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/sandbox/JacksonPrettyPrintUnitTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.sandbox; +package com.baeldung.jackson.sandbox; import java.io.File; import java.io.IOException; diff --git a/jackson/src/test/java/com/baeldung/jackson/sandbox/SandboxTest.java b/jackson/src/test/java/com/baeldung/jackson/sandbox/SandboxTest.java new file mode 100644 index 0000000000..958a7eec98 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/sandbox/SandboxTest.java @@ -0,0 +1,28 @@ +package com.baeldung.jackson.sandbox; + +import java.io.IOException; + +import org.junit.Test; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class SandboxTest { + + @Test + public final void whenDeserializing_thenCorrect() throws JsonParseException, JsonMappingException, IOException { + final TestElement testElement = new TestElement(); + testElement.setX(10); + testElement.setY("adasd"); + final ObjectMapper om = new ObjectMapper(); + om.setVisibilityChecker(om.getSerializationConfig().getDefaultVisibilityChecker().withFieldVisibility(JsonAutoDetect.Visibility.ANY).withGetterVisibility(JsonAutoDetect.Visibility.NONE)); + + final String serialized = om.writeValueAsString(testElement); + System.err.println(serialized); + } + + // + +} diff --git a/jackson/src/test/java/org/baeldung/jackson/sandbox/TestElement.java b/jackson/src/test/java/com/baeldung/jackson/sandbox/TestElement.java similarity index 88% rename from jackson/src/test/java/org/baeldung/jackson/sandbox/TestElement.java rename to jackson/src/test/java/com/baeldung/jackson/sandbox/TestElement.java index 3b6a852b6b..82f53fcf4a 100644 --- a/jackson/src/test/java/org/baeldung/jackson/sandbox/TestElement.java +++ b/jackson/src/test/java/com/baeldung/jackson/sandbox/TestElement.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.sandbox; +package com.baeldung.jackson.sandbox; public class TestElement { diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java b/jackson/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java new file mode 100644 index 0000000000..b5624c566a --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java @@ -0,0 +1,32 @@ +package com.baeldung.jackson.serialization; + +import java.io.IOException; + +import com.baeldung.jackson.dtos.Item; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class ItemSerializer extends StdSerializer { + + private static final long serialVersionUID = 6739170890621978901L; + + public ItemSerializer() { + this(null); + } + + public ItemSerializer(final Class t) { + super(t); + } + + @Override + public final void serialize(final Item value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeStartObject(); + jgen.writeNumberField("id", value.id); + jgen.writeStringField("itemName", value.itemName); + jgen.writeNumberField("owner", value.owner.id); + jgen.writeEndObject(); + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/ItemSerializerOnClass.java b/jackson/src/test/java/com/baeldung/jackson/serialization/ItemSerializerOnClass.java new file mode 100644 index 0000000000..1fdf44e17c --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/serialization/ItemSerializerOnClass.java @@ -0,0 +1,32 @@ +package com.baeldung.jackson.serialization; + +import java.io.IOException; + +import com.baeldung.jackson.dtos.ItemWithSerializer; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class ItemSerializerOnClass extends StdSerializer { + + private static final long serialVersionUID = -1760959597313610409L; + + public ItemSerializerOnClass() { + this(null); + } + + public ItemSerializerOnClass(final Class t) { + super(t); + } + + @Override + public final void serialize(final ItemWithSerializer value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeStartObject(); + jgen.writeNumberField("id", value.id); + jgen.writeStringField("itemName", value.itemName); + jgen.writeNumberField("owner", value.owner.id); + jgen.writeEndObject(); + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java b/jackson/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java new file mode 100644 index 0000000000..d0b2d7f5e9 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java @@ -0,0 +1,27 @@ +package com.baeldung.jackson.serialization; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class MyDtoNullKeySerializer extends StdSerializer { + + private static final long serialVersionUID = -4478531309177369056L; + + public MyDtoNullKeySerializer() { + this(null); + } + + public MyDtoNullKeySerializer(final Class t) { + super(t); + } + + @Override + public void serialize(final Object value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeFieldName(""); + } + +} diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonAnnotationTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationTest.java similarity index 84% rename from jackson/src/test/java/org/baeldung/jackson/test/JacksonAnnotationTest.java rename to jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationTest.java index c188e9bce1..d854d89b5f 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonAnnotationTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; @@ -12,33 +12,32 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; -import org.baeldung.jackson.annotation.BeanWithCreator; -import org.baeldung.jackson.annotation.BeanWithCustomAnnotation; -import org.baeldung.jackson.annotation.BeanWithFilter; -import org.baeldung.jackson.annotation.BeanWithGetter; -import org.baeldung.jackson.annotation.BeanWithIgnore; -import org.baeldung.jackson.annotation.BeanWithInject; -import org.baeldung.jackson.annotation.ExtendableBean; -import org.baeldung.jackson.annotation.MyBean; -import org.baeldung.jackson.annotation.PrivateBean; -import org.baeldung.jackson.annotation.RawBean; -import org.baeldung.jackson.annotation.UnwrappedUser; -import org.baeldung.jackson.annotation.UserWithIgnoreType; -import org.baeldung.jackson.annotation.Zoo; -import org.baeldung.jackson.bidirection.ItemWithIdentity; -import org.baeldung.jackson.bidirection.ItemWithRef; -import org.baeldung.jackson.bidirection.UserWithIdentity; -import org.baeldung.jackson.bidirection.UserWithRef; -import org.baeldung.jackson.date.EventWithFormat; -import org.baeldung.jackson.date.EventWithSerializer; -import org.baeldung.jackson.dtos.MyMixInForString; -import org.baeldung.jackson.dtos.User; -import org.baeldung.jackson.dtos.withEnum.TypeEnumWithValue; -import org.baeldung.jackson.exception.UserWithRoot; -import org.baeldung.jackson.jsonview.Item; -import org.baeldung.jackson.jsonview.Views; import org.junit.Test; +import com.baeldung.jackson.annotation.BeanWithCreator; +import com.baeldung.jackson.annotation.BeanWithCustomAnnotation; +import com.baeldung.jackson.annotation.BeanWithFilter; +import com.baeldung.jackson.annotation.BeanWithGetter; +import com.baeldung.jackson.annotation.BeanWithIgnore; +import com.baeldung.jackson.annotation.BeanWithInject; +import com.baeldung.jackson.annotation.ExtendableBean; +import com.baeldung.jackson.annotation.MyBean; +import com.baeldung.jackson.annotation.PrivateBean; +import com.baeldung.jackson.annotation.RawBean; +import com.baeldung.jackson.annotation.UnwrappedUser; +import com.baeldung.jackson.annotation.UserWithIgnoreType; +import com.baeldung.jackson.annotation.Zoo; +import com.baeldung.jackson.bidirection.ItemWithIdentity; +import com.baeldung.jackson.bidirection.ItemWithRef; +import com.baeldung.jackson.bidirection.UserWithIdentity; +import com.baeldung.jackson.bidirection.UserWithRef; +import com.baeldung.jackson.date.EventWithFormat; +import com.baeldung.jackson.date.EventWithSerializer; +import com.baeldung.jackson.dtos.MyMixInForIgnoreType; +import com.baeldung.jackson.dtos.withEnum.TypeEnumWithValue; +import com.baeldung.jackson.exception.UserWithRoot; +import com.baeldung.jackson.jsonview.Item; +import com.baeldung.jackson.jsonview.Views; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.InjectableValues; @@ -126,7 +125,7 @@ public class JacksonAnnotationTest { public void whenDeserializingUsingJsonCreator_thenCorrect() throws JsonProcessingException, IOException { final String json = "{\"id\":1,\"theName\":\"My bean\"}"; - final BeanWithCreator bean = new ObjectMapper().reader(BeanWithCreator.class).readValue(json); + final BeanWithCreator bean = new ObjectMapper().readerFor(BeanWithCreator.class).readValue(json); assertEquals("My bean", bean.name); } @@ -135,7 +134,7 @@ public class JacksonAnnotationTest { final String json = "{\"name\":\"My bean\"}"; final InjectableValues inject = new InjectableValues.Std().addValue(int.class, 1); - final BeanWithInject bean = new ObjectMapper().reader(inject).withType(BeanWithInject.class).readValue(json); + final BeanWithInject bean = new ObjectMapper().reader(inject).forType(BeanWithInject.class).readValue(json); assertEquals("My bean", bean.name); assertEquals(1, bean.id); } @@ -144,7 +143,7 @@ public class JacksonAnnotationTest { public void whenDeserializingUsingJsonAnySetter_thenCorrect() throws JsonProcessingException, IOException { final String json = "{\"name\":\"My bean\",\"attr2\":\"val2\",\"attr1\":\"val1\"}"; - final ExtendableBean bean = new ObjectMapper().reader(ExtendableBean.class).readValue(json); + final ExtendableBean bean = new ObjectMapper().readerFor(ExtendableBean.class).readValue(json); assertEquals("My bean", bean.name); assertEquals("val2", bean.getProperties().get("attr2")); } @@ -153,7 +152,7 @@ public class JacksonAnnotationTest { public void whenDeserializingUsingJsonSetter_thenCorrect() throws JsonProcessingException, IOException { final String json = "{\"id\":1,\"name\":\"My bean\"}"; - final BeanWithGetter bean = new ObjectMapper().reader(BeanWithGetter.class).readValue(json); + final BeanWithGetter bean = new ObjectMapper().readerFor(BeanWithGetter.class).readValue(json); assertEquals("My bean", bean.getTheName()); } @@ -163,7 +162,7 @@ public class JacksonAnnotationTest { final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); - final EventWithSerializer event = new ObjectMapper().reader(EventWithSerializer.class).readValue(json); + final EventWithSerializer event = new ObjectMapper().readerFor(EventWithSerializer.class).readValue(json); assertEquals("20-12-2014 02:30:00", df.format(event.eventDate)); } @@ -234,7 +233,7 @@ public class JacksonAnnotationTest { public void whenDeserializingPolymorphic_thenCorrect() throws JsonProcessingException, IOException { final String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}"; - final Zoo zoo = new ObjectMapper().reader().withType(Zoo.class).readValue(json); + final Zoo zoo = new ObjectMapper().readerFor(Zoo.class).readValue(json); assertEquals("lacy", zoo.animal.name); assertEquals(Zoo.Cat.class, zoo.animal.getClass()); @@ -249,7 +248,7 @@ public class JacksonAnnotationTest { assertThat(result, containsString("My bean")); assertThat(result, containsString("1")); - final BeanWithGetter resultBean = new ObjectMapper().reader(BeanWithGetter.class).readValue(result); + final BeanWithGetter resultBean = new ObjectMapper().readerFor(BeanWithGetter.class).readValue(result); assertEquals("My bean", resultBean.getTheName()); } @@ -337,18 +336,19 @@ public class JacksonAnnotationTest { assertThat(result, not(containsString("dateCreated"))); } + // @Ignore("Jackson 2.7.1-1 seems to have changed the API regarding mixins") @Test public void whenSerializingUsingMixInAnnotation_thenCorrect() throws JsonProcessingException { - final User user = new User(1, "John"); + final com.baeldung.jackson.dtos.Item item = new com.baeldung.jackson.dtos.Item(1, "book", null); - String result = new ObjectMapper().writeValueAsString(user); - assertThat(result, containsString("John")); + String result = new ObjectMapper().writeValueAsString(item); + assertThat(result, containsString("owner")); final ObjectMapper mapper = new ObjectMapper(); - mapper.addMixInAnnotations(String.class, MyMixInForString.class); + mapper.addMixIn(com.baeldung.jackson.dtos.User.class, MyMixInForIgnoreType.class); - result = mapper.writeValueAsString(user); - assertThat(result, not(containsString("John"))); + result = mapper.writeValueAsString(item); + assertThat(result, not(containsString("owner"))); } @Test diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonBidirectionRelationTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonBidirectionRelationTest.java similarity index 84% rename from jackson/src/test/java/org/baeldung/jackson/test/JacksonBidirectionRelationTest.java rename to jackson/src/test/java/com/baeldung/jackson/test/JacksonBidirectionRelationTest.java index f7f687da96..db8507a4b0 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonBidirectionRelationTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonBidirectionRelationTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; @@ -7,21 +7,21 @@ import static org.junit.Assert.assertThat; import java.io.IOException; -import org.baeldung.jackson.bidirection.Item; -import org.baeldung.jackson.bidirection.ItemWithIdentity; -import org.baeldung.jackson.bidirection.ItemWithIgnore; -import org.baeldung.jackson.bidirection.ItemWithRef; -import org.baeldung.jackson.bidirection.ItemWithSerializer; -import org.baeldung.jackson.bidirection.ItemWithView; -import org.baeldung.jackson.bidirection.User; -import org.baeldung.jackson.bidirection.UserWithIdentity; -import org.baeldung.jackson.bidirection.UserWithIgnore; -import org.baeldung.jackson.bidirection.UserWithRef; -import org.baeldung.jackson.bidirection.UserWithSerializer; -import org.baeldung.jackson.bidirection.UserWithView; -import org.baeldung.jackson.jsonview.Views; import org.junit.Test; +import com.baeldung.jackson.bidirection.Item; +import com.baeldung.jackson.bidirection.ItemWithIdentity; +import com.baeldung.jackson.bidirection.ItemWithIgnore; +import com.baeldung.jackson.bidirection.ItemWithRef; +import com.baeldung.jackson.bidirection.ItemWithSerializer; +import com.baeldung.jackson.bidirection.ItemWithView; +import com.baeldung.jackson.bidirection.User; +import com.baeldung.jackson.bidirection.UserWithIdentity; +import com.baeldung.jackson.bidirection.UserWithIgnore; +import com.baeldung.jackson.bidirection.UserWithRef; +import com.baeldung.jackson.bidirection.UserWithSerializer; +import com.baeldung.jackson.bidirection.UserWithView; +import com.baeldung.jackson.jsonview.Views; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -93,7 +93,7 @@ public class JacksonBidirectionRelationTest { public void givenBidirectionRelation_whenDeserializingUsingIdentity_thenCorrect() throws JsonProcessingException, IOException { final String json = "{\"id\":2,\"itemName\":\"book\",\"owner\":{\"id\":1,\"name\":\"John\",\"userItems\":[2]}}"; - final ItemWithIdentity item = new ObjectMapper().reader(ItemWithIdentity.class).readValue(json); + final ItemWithIdentity item = new ObjectMapper().readerFor(ItemWithIdentity.class).readValue(json); assertEquals(2, item.id); assertEquals("book", item.itemName); @@ -104,7 +104,7 @@ public class JacksonBidirectionRelationTest { public void givenBidirectionRelation_whenUsingCustomDeserializer_thenCorrect() throws JsonProcessingException, IOException { final String json = "{\"id\":2,\"itemName\":\"book\",\"owner\":{\"id\":1,\"name\":\"John\",\"userItems\":[2]}}"; - final ItemWithSerializer item = new ObjectMapper().reader(ItemWithSerializer.class).readValue(json); + final ItemWithSerializer item = new ObjectMapper().readerFor(ItemWithSerializer.class).readValue(json); assertEquals(2, item.id); assertEquals("book", item.itemName); assertEquals("John", item.owner.name); diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonCollectionDeserializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonCollectionDeserializationUnitTest.java similarity index 97% rename from jackson/src/test/java/org/baeldung/jackson/test/JacksonCollectionDeserializationUnitTest.java rename to jackson/src/test/java/com/baeldung/jackson/test/JacksonCollectionDeserializationUnitTest.java index c3d8153546..cd166386e6 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonCollectionDeserializationUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonCollectionDeserializationUnitTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertThat; @@ -7,7 +7,7 @@ import java.io.IOException; import java.util.LinkedHashMap; import java.util.List; -import org.baeldung.jackson.dtos.MyDto; +import com.baeldung.jackson.dtos.MyDto; import org.junit.Test; import com.fasterxml.jackson.core.JsonParseException; diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonDateTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/test/JacksonDateTest.java rename to jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java index fc7f7730b8..d8357f8500 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonDateTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; @@ -11,15 +11,15 @@ import java.time.LocalDateTime; import java.util.Date; import java.util.TimeZone; -import org.baeldung.jackson.date.Event; -import org.baeldung.jackson.date.EventWithFormat; -import org.baeldung.jackson.date.EventWithJodaTime; -import org.baeldung.jackson.date.EventWithLocalDateTime; -import org.baeldung.jackson.date.EventWithSerializer; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.junit.Test; +import com.baeldung.jackson.date.Event; +import com.baeldung.jackson.date.EventWithFormat; +import com.baeldung.jackson.date.EventWithJodaTime; +import com.baeldung.jackson.date.EventWithLocalDateTime; +import com.baeldung.jackson.date.EventWithSerializer; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; @@ -128,7 +128,7 @@ public class JacksonDateTest { final ObjectMapper mapper = new ObjectMapper(); mapper.setDateFormat(df); - final Event event = mapper.reader(Event.class).readValue(json); + final Event event = mapper.readerFor(Event.class).readValue(json); assertEquals("20-12-2014 02:30:00", df.format(event.eventDate)); } @@ -139,7 +139,7 @@ public class JacksonDateTest { final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); final ObjectMapper mapper = new ObjectMapper(); - final EventWithSerializer event = mapper.reader(EventWithSerializer.class).readValue(json); + final EventWithSerializer event = mapper.readerFor(EventWithSerializer.class).readValue(json); assertEquals("20-12-2014 02:30:00", df.format(event.eventDate)); } diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDeserializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDeserializationUnitTest.java new file mode 100644 index 0000000000..45d957b90b --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDeserializationUnitTest.java @@ -0,0 +1,168 @@ +package com.baeldung.jackson.test; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +import java.io.IOException; + +import com.baeldung.jackson.deserialization.ItemDeserializer; +import com.baeldung.jackson.dtos.Item; +import com.baeldung.jackson.dtos.ItemWithSerializer; +import com.baeldung.jackson.dtos.MyDto; +import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreUnknown; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; +import com.fasterxml.jackson.databind.module.SimpleModule; + +public class JacksonDeserializationUnitTest { + + @Test + public final void whenDeserializingAJsonToAClass_thenCorrect() throws JsonParseException, JsonMappingException, IOException { + final String jsonAsString = "{\"stringValue\":\"a\",\"intValue\":1,\"booleanValue\":true}"; + final ObjectMapper mapper = new ObjectMapper(); + + final MyDto readValue = mapper.readValue(jsonAsString, MyDto.class); + + assertNotNull(readValue); + assertThat(readValue.getStringValue(), equalTo("a")); + } + + @Test + public final void givenNotAllFieldsHaveValuesInJson_whenDeserializingAJsonToAClass_thenCorrect() throws JsonParseException, JsonMappingException, IOException { + final String jsonAsString = "{\"stringValue\":\"a\",\"booleanValue\":true}"; + final ObjectMapper mapper = new ObjectMapper(); + + final MyDto readValue = mapper.readValue(jsonAsString, MyDto.class); + + assertNotNull(readValue); + assertThat(readValue.getStringValue(), equalTo("a")); + assertThat(readValue.isBooleanValue(), equalTo(true)); + } + + // tests - json with unknown fields + + @Test(expected = UnrecognizedPropertyException.class) + public final void givenJsonHasUnknownValues_whenDeserializingAJsonToAClass_thenExceptionIsThrown() throws JsonParseException, JsonMappingException, IOException { + final String jsonAsString = "{\"stringValue\":\"a\",\"intValue\":1,\"booleanValue\":true,\"stringValue2\":\"something\"}"; + final ObjectMapper mapper = new ObjectMapper(); + + final MyDto readValue = mapper.readValue(jsonAsString, MyDto.class); + + assertNotNull(readValue); + assertThat(readValue.getStringValue(), equalTo("a")); + assertThat(readValue.isBooleanValue(), equalTo(true)); + assertThat(readValue.getIntValue(), equalTo(1)); + } + + @Test + public final void givenJsonHasUnknownValuesButJacksonIsIgnoringUnknownFields_whenDeserializing_thenCorrect() throws JsonParseException, JsonMappingException, IOException { + final String jsonAsString = // @formatter:off + "{\"stringValue\":\"a\"," + + "\"intValue\":1," + + "\"booleanValue\":true," + + "\"stringValue2\":\"something\"}"; // @formatter:on + final ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + final MyDto readValue = mapper.readValue(jsonAsString, MyDto.class); + + assertNotNull(readValue); + assertThat(readValue.getStringValue(), equalTo("a")); + assertThat(readValue.isBooleanValue(), equalTo(true)); + assertThat(readValue.getIntValue(), equalTo(1)); + } + + @Test + public final void givenJsonHasUnknownValuesButUnknownFieldsAreIgnoredOnClass_whenDeserializing_thenCorrect() throws JsonParseException, JsonMappingException, IOException { + final String jsonAsString = // @formatter:off + "{\"stringValue\":\"a\"," + + "\"intValue\":1," + + "\"booleanValue\":true," + + "\"stringValue2\":\"something\"}"; // @formatter:on + final ObjectMapper mapper = new ObjectMapper(); + + final MyDtoIgnoreUnknown readValue = mapper.readValue(jsonAsString, MyDtoIgnoreUnknown.class); + + assertNotNull(readValue); + assertThat(readValue.getStringValue(), equalTo("a")); + assertThat(readValue.isBooleanValue(), equalTo(true)); + assertThat(readValue.getIntValue(), equalTo(1)); + } + + // to JsonNode + + @Test + public final void whenParsingJsonStringIntoJsonNode_thenCorrect() throws JsonParseException, IOException { + final String jsonString = "{\"k1\":\"v1\",\"k2\":\"v2\"}"; + + final ObjectMapper mapper = new ObjectMapper(); + final JsonNode actualObj = mapper.readTree(jsonString); + + assertNotNull(actualObj); + } + + @Test + public final void givenUsingLowLevelDetails_whenParsingJsonStringIntoJsonNode_thenCorrect() throws JsonParseException, IOException { + final String jsonString = "{\"k1\":\"v1\",\"k2\":\"v2\"}"; + + final ObjectMapper mapper = new ObjectMapper(); + final JsonFactory factory = mapper.getFactory(); + final JsonParser parser = factory.createParser(jsonString); + final JsonNode actualObj = mapper.readTree(parser); + + assertNotNull(actualObj); + } + + @Test + public final void givenTheJsonNode_whenRetrievingDataFromId_thenCorrect() throws JsonParseException, IOException { + final String jsonString = "{\"k1\":\"v1\",\"k2\":\"v2\"}"; + final ObjectMapper mapper = new ObjectMapper(); + final JsonNode actualObj = mapper.readTree(jsonString); + + // When + final JsonNode jsonNode1 = actualObj.get("k1"); + assertThat(jsonNode1.textValue(), equalTo("v1")); + } + + // custom deserialization + + @Test + public final void whenDeserializingTheStandardRepresentation_thenCorrect() throws JsonParseException, JsonMappingException, IOException { + final String json = "{\"id\":1,\"itemName\":\"theItem\",\"owner\":{\"id\":2,\"name\":\"theUser\"}}"; + + final Item readValue = new ObjectMapper().readValue(json, Item.class); + assertThat(readValue, notNullValue()); + } + + @Test + public final void whenDeserializingANonStandardRepresentation_thenCorrect() throws JsonParseException, JsonMappingException, IOException { + final String json = "{\"id\":1,\"itemName\":\"theItem\",\"createdBy\":2}"; + final ObjectMapper mapper = new ObjectMapper(); + + final SimpleModule module = new SimpleModule(); + module.addDeserializer(Item.class, new ItemDeserializer()); + mapper.registerModule(module); + + final Item readValue = mapper.readValue(json, Item.class); + assertThat(readValue, notNullValue()); + } + + @Test + public final void givenDeserializerIsOnClass_whenDeserializingCustomRepresentation_thenCorrect() throws JsonParseException, JsonMappingException, IOException { + final String json = "{\"id\":1,\"itemName\":\"theItem\",\"owner\":2}"; + + final ItemWithSerializer readValue = new ObjectMapper().readValue(json, ItemWithSerializer.class); + assertThat(readValue, notNullValue()); + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDynamicIgnoreTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDynamicIgnoreTest.java new file mode 100644 index 0000000000..16a55f442a --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDynamicIgnoreTest.java @@ -0,0 +1,100 @@ +package com.baeldung.jackson.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import com.baeldung.jackson.dynamicIgnore.Address; +import com.baeldung.jackson.dynamicIgnore.HidableSerializer; +import com.baeldung.jackson.dynamicIgnore.Person; +import com.baeldung.jackson.dynamicIgnore.Hidable; +import org.junit.Before; +import org.junit.Test; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationConfig; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; + +public class JacksonDynamicIgnoreTest { + + private ObjectMapper mapper = new ObjectMapper(); + + @Before + public void setUp() { + mapper.setSerializationInclusion(Include.NON_EMPTY); + mapper.registerModule(new SimpleModule() { + @Override + public void setupModule(final SetupContext context) { + super.setupModule(context); + context.addBeanSerializerModifier(new BeanSerializerModifier() { + @Override + public JsonSerializer modifySerializer(final SerializationConfig config, final BeanDescription beanDesc, final JsonSerializer serializer) { + if (Hidable.class.isAssignableFrom(beanDesc.getBeanClass())) { + return new HidableSerializer((JsonSerializer) serializer); + } + return serializer; + } + }); + } + }); + } + + @Test + public void whenNotHidden_thenCorrect() throws JsonProcessingException { + final Address ad = new Address("ny", "usa", false); + final Person person = new Person("john", ad, false); + final String result = mapper.writeValueAsString(person); + + assertTrue(result.contains("name")); + assertTrue(result.contains("john")); + assertTrue(result.contains("address")); + assertTrue(result.contains("usa")); + + System.out.println("Not Hidden = " + result); + } + + @Test + public void whenAddressHidden_thenCorrect() throws JsonProcessingException { + final Address ad = new Address("ny", "usa", true); + final Person person = new Person("john", ad, false); + final String result = mapper.writeValueAsString(person); + + assertTrue(result.contains("name")); + assertTrue(result.contains("john")); + assertFalse(result.contains("address")); + assertFalse(result.contains("usa")); + + System.out.println("Address Hidden = " + result); + } + + @Test + public void whenAllHidden_thenCorrect() throws JsonProcessingException { + final Address ad = new Address("ny", "usa", false); + final Person person = new Person("john", ad, true); + final String result = mapper.writeValueAsString(person); + + assertTrue(result.length() == 0); + + System.out.println("All Hidden = " + result); + } + + @Test + public void whenSerializeList_thenCorrect() throws JsonProcessingException { + final Address ad1 = new Address("tokyo", "jp", true); + final Address ad2 = new Address("london", "uk", false); + final Address ad3 = new Address("ny", "usa", false); + final Person p1 = new Person("john", ad1, false); + final Person p2 = new Person("tom", ad2, true); + final Person p3 = new Person("adam", ad3, false); + + final String result = mapper.writeValueAsString(Arrays.asList(p1, p2, p3)); + + System.out.println(result); + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonExceptionsTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonExceptionsTest.java similarity index 80% rename from jackson/src/test/java/org/baeldung/jackson/test/JacksonExceptionsTest.java rename to jackson/src/test/java/com/baeldung/jackson/test/JacksonExceptionsTest.java index aab7f9409d..d9b8d1cc18 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonExceptionsTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonExceptionsTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; @@ -7,13 +7,13 @@ import static org.junit.Assert.assertThat; import java.io.IOException; import java.util.List; -import org.baeldung.jackson.dtos.User; -import org.baeldung.jackson.exception.UserWithPrivateFields; -import org.baeldung.jackson.exception.UserWithRoot; -import org.baeldung.jackson.exception.Zoo; -import org.baeldung.jackson.exception.ZooConfigured; import org.junit.Test; +import com.baeldung.jackson.exception.User; +import com.baeldung.jackson.exception.UserWithPrivateFields; +import com.baeldung.jackson.exception.UserWithRoot; +import com.baeldung.jackson.exception.Zoo; +import com.baeldung.jackson.exception.ZooConfigured; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.core.JsonFactory; @@ -34,7 +34,7 @@ public class JacksonExceptionsTest { final String json = "{\"animal\":{\"name\":\"lacy\"}}"; final ObjectMapper mapper = new ObjectMapper(); - mapper.reader().withType(Zoo.class).readValue(json); + mapper.reader().forType(Zoo.class).readValue(json); } @Test @@ -42,7 +42,7 @@ public class JacksonExceptionsTest { final String json = "{\"animal\":{\"name\":\"lacy\"}}"; final ObjectMapper mapper = new ObjectMapper(); - mapper.reader().withType(ZooConfigured.class).readValue(json); + mapper.reader().forType(ZooConfigured.class).readValue(json); } // JsonMappingException: No serializer found for class @@ -71,7 +71,7 @@ public class JacksonExceptionsTest { final String json = "{\"id\":1,\"name\":\"John\"}"; final ObjectMapper mapper = new ObjectMapper(); - mapper.reader().withType(org.baeldung.jackson.exception.User.class).readValue(json); + mapper.reader().forType(User.class).readValue(json); } @Test @@ -79,7 +79,7 @@ public class JacksonExceptionsTest { final String json = "{\"id\":1,\"name\":\"John\"}"; final ObjectMapper mapper = new ObjectMapper(); - final User user = mapper.reader().withType(User.class).readValue(json); + final com.baeldung.jackson.dtos.User user = mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json); assertEquals("John", user.name); } @@ -91,7 +91,7 @@ public class JacksonExceptionsTest { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); - mapper.reader().withType(User.class).readValue(json); + mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json); } @Test @@ -101,7 +101,7 @@ public class JacksonExceptionsTest { final ObjectMapper mapper = new ObjectMapper(); mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); - final UserWithRoot user = mapper.reader().withType(UserWithRoot.class).readValue(json); + final UserWithRoot user = mapper.reader().forType(UserWithRoot.class).readValue(json); assertEquals("John", user.name); } @@ -111,7 +111,7 @@ public class JacksonExceptionsTest { final String json = "[{\"id\":1,\"name\":\"John\"},{\"id\":2,\"name\":\"Adam\"}]"; final ObjectMapper mapper = new ObjectMapper(); - mapper.reader().withType(User.class).readValue(json); + mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json); } @Test @@ -119,7 +119,7 @@ public class JacksonExceptionsTest { final String json = "[{\"id\":1,\"name\":\"John\"},{\"id\":2,\"name\":\"Adam\"}]"; final ObjectMapper mapper = new ObjectMapper(); - final List users = mapper.reader().withType(new TypeReference>() { + final List users = mapper.reader().forType(new TypeReference>() { }).readValue(json); assertEquals(2, users.size()); @@ -131,7 +131,7 @@ public class JacksonExceptionsTest { final String json = "{\"id\":1,\"name\":\"John\", \"checked\":true}"; final ObjectMapper mapper = new ObjectMapper(); - mapper.reader().withType(User.class).readValue(json); + mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json); } @Test @@ -141,7 +141,7 @@ public class JacksonExceptionsTest { final ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - final User user = mapper.reader().withType(User.class).readValue(json); + final com.baeldung.jackson.dtos.User user = mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json); assertEquals("John", user.name); } @@ -151,7 +151,7 @@ public class JacksonExceptionsTest { final String json = "{'id':1,'name':'John'}"; final ObjectMapper mapper = new ObjectMapper(); - mapper.reader().withType(User.class).readValue(json); + mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json); } @Test @@ -162,7 +162,7 @@ public class JacksonExceptionsTest { factory.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES); final ObjectMapper mapper = new ObjectMapper(factory); - final User user = mapper.reader().withType(User.class).readValue(json); + final com.baeldung.jackson.dtos.User user = mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json); assertEquals("John", user.name); } diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonFieldUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonFieldUnitTest.java similarity index 95% rename from jackson/src/test/java/org/baeldung/jackson/test/JacksonFieldUnitTest.java rename to jackson/src/test/java/com/baeldung/jackson/test/JacksonFieldUnitTest.java index 53933215f5..ccc5905e88 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonFieldUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonFieldUnitTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -8,9 +8,9 @@ import static org.junit.Assert.assertThat; import java.io.IOException; -import org.baeldung.jackson.field.MyDtoAccessLevel; -import org.baeldung.jackson.field.MyDtoWithSetter; -import org.baeldung.jackson.field.MyDtoWithGetter; +import com.baeldung.jackson.field.MyDtoAccessLevel; +import com.baeldung.jackson.field.MyDtoWithSetter; +import com.baeldung.jackson.field.MyDtoWithGetter; import org.junit.Test; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonJsonViewTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonJsonViewTest.java similarity index 91% rename from jackson/src/test/java/org/baeldung/jackson/test/JacksonJsonViewTest.java rename to jackson/src/test/java/com/baeldung/jackson/test/JacksonJsonViewTest.java index 276db9261c..477b0132e2 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonJsonViewTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonJsonViewTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; @@ -7,12 +7,12 @@ import static org.junit.Assert.assertThat; import java.io.IOException; -import org.baeldung.jackson.jsonview.Item; -import org.baeldung.jackson.jsonview.MyBeanSerializerModifier; -import org.baeldung.jackson.jsonview.User; -import org.baeldung.jackson.jsonview.Views; import org.junit.Test; +import com.baeldung.jackson.jsonview.Item; +import com.baeldung.jackson.jsonview.MyBeanSerializerModifier; +import com.baeldung.jackson.jsonview.User; +import com.baeldung.jackson.jsonview.Views; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -66,7 +66,7 @@ public class JacksonJsonViewTest { final ObjectMapper mapper = new ObjectMapper(); - final User user = mapper.readerWithView(Views.Public.class).withType(User.class).readValue(json); + final User user = mapper.readerWithView(Views.Public.class).forType(User.class).readValue(json); assertEquals(1, user.getId()); assertEquals("John", user.getName()); } diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonSerializationEnumsUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationEnumsUnitTest.java similarity index 87% rename from jackson/src/test/java/org/baeldung/jackson/test/JacksonSerializationEnumsUnitTest.java rename to jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationEnumsUnitTest.java index d64834078a..78c6316aa6 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonSerializationEnumsUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationEnumsUnitTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; @@ -6,12 +6,12 @@ import static org.junit.Assert.assertThat; import java.io.IOException; -import org.baeldung.jackson.dtos.withEnum.MyDtoWithEnum; -import org.baeldung.jackson.dtos.withEnum.MyDtoWithEnumCustom; -import org.baeldung.jackson.dtos.withEnum.TypeEnum; -import org.baeldung.jackson.dtos.withEnum.TypeEnumSimple; -import org.baeldung.jackson.dtos.withEnum.TypeEnumWithCustomSerializer; -import org.baeldung.jackson.dtos.withEnum.TypeEnumWithValue; +import com.baeldung.jackson.dtos.withEnum.MyDtoWithEnum; +import com.baeldung.jackson.dtos.withEnum.TypeEnum; +import com.baeldung.jackson.dtos.withEnum.TypeEnumSimple; +import com.baeldung.jackson.dtos.withEnum.TypeEnumWithValue; +import com.baeldung.jackson.dtos.withEnum.MyDtoWithEnumCustom; +import com.baeldung.jackson.dtos.withEnum.TypeEnumWithCustomSerializer; import org.junit.Test; import com.fasterxml.jackson.core.JsonParseException; diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java similarity index 93% rename from jackson/src/test/java/org/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java rename to jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java index 64614fb854..71499b8a24 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; @@ -8,16 +8,17 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import org.baeldung.jackson.dtos.MyDto; -import org.baeldung.jackson.dtos.MyDtoIncludeNonDefault; -import org.baeldung.jackson.dtos.MyDtoWithFilter; -import org.baeldung.jackson.dtos.MyMixInForString; -import org.baeldung.jackson.dtos.ignore.MyDtoIgnoreField; -import org.baeldung.jackson.dtos.ignore.MyDtoIgnoreFieldByName; -import org.baeldung.jackson.dtos.ignore.MyDtoIgnoreNull; -import org.baeldung.jackson.serialization.MyDtoNullKeySerializer; import org.junit.Test; +import com.baeldung.jackson.dtos.MyDto; +import com.baeldung.jackson.dtos.MyDtoIncludeNonDefault; +import com.baeldung.jackson.dtos.MyDtoWithFilter; +import com.baeldung.jackson.dtos.MyDtoWithSpecialField; +import com.baeldung.jackson.dtos.MyMixInForIgnoreType; +import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreField; +import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreFieldByName; +import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreNull; +import com.baeldung.jackson.serialization.MyDtoNullKeySerializer; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParseException; @@ -84,11 +85,12 @@ public class JacksonSerializationIgnoreUnitTest { System.out.println(dtoAsString); } + // @Ignore("Jackson 2.7.1-1 seems to have changed the API for this case") @Test public final void givenFieldTypeIsIgnored_whenDtoIsSerialized_thenCorrect() throws JsonParseException, IOException { final ObjectMapper mapper = new ObjectMapper(); - mapper.addMixInAnnotations(String.class, MyMixInForString.class); - final MyDto dtoObject = new MyDto(); + mapper.addMixIn(String[].class, MyMixInForIgnoreType.class); + final MyDtoWithSpecialField dtoObject = new MyDtoWithSpecialField(); dtoObject.setBooleanValue(true); final String dtoAsString = mapper.writeValueAsString(dtoObject); diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonSerializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java similarity index 92% rename from jackson/src/test/java/org/baeldung/jackson/test/JacksonSerializationUnitTest.java rename to jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java index 4a34f168c7..563dda9eb6 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonSerializationUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; @@ -8,14 +8,14 @@ import static org.junit.Assert.assertThat; import java.io.IOException; import java.util.List; -import org.baeldung.jackson.dtos.Item; -import org.baeldung.jackson.dtos.ItemWithSerializer; -import org.baeldung.jackson.dtos.MyDto; -import org.baeldung.jackson.dtos.MyDtoFieldNameChanged; -import org.baeldung.jackson.dtos.MyDtoNoAccessors; -import org.baeldung.jackson.dtos.MyDtoNoAccessorsAndFieldVisibility; -import org.baeldung.jackson.dtos.User; -import org.baeldung.jackson.serialization.ItemSerializer; +import com.baeldung.jackson.dtos.MyDtoFieldNameChanged; +import com.baeldung.jackson.dtos.User; +import com.baeldung.jackson.dtos.Item; +import com.baeldung.jackson.dtos.ItemWithSerializer; +import com.baeldung.jackson.dtos.MyDto; +import com.baeldung.jackson.dtos.MyDtoNoAccessors; +import com.baeldung.jackson.dtos.MyDtoNoAccessorsAndFieldVisibility; +import com.baeldung.jackson.serialization.ItemSerializer; import org.junit.Test; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; diff --git a/jackson/src/test/java/org/baeldung/jackson/test/UnitTestSuite.java b/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java similarity index 78% rename from jackson/src/test/java/org/baeldung/jackson/test/UnitTestSuite.java rename to jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java index 3bc5715e2a..d47b6e217a 100644 --- a/jackson/src/test/java/org/baeldung/jackson/test/UnitTestSuite.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java @@ -1,7 +1,7 @@ -package org.baeldung.jackson.test; +package com.baeldung.jackson.test; -import org.baeldung.jackson.sandbox.JacksonPrettyPrintUnitTest; -import org.baeldung.jackson.sandbox.SandboxTest; +import com.baeldung.jackson.sandbox.JacksonPrettyPrintUnitTest; +import com.baeldung.jackson.sandbox.SandboxTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; diff --git a/jackson/src/test/java/com/baeldung/jackson/try1/IEntity.java b/jackson/src/test/java/com/baeldung/jackson/try1/IEntity.java new file mode 100644 index 0000000000..27e0a71c9d --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/try1/IEntity.java @@ -0,0 +1,5 @@ +package com.baeldung.jackson.try1; + +public interface IEntity { + public int getId(); +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/try1/JacksonDeserializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/try1/JacksonDeserializationUnitTest.java new file mode 100644 index 0000000000..9fc195a8aa --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/try1/JacksonDeserializationUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.jackson.try1; + +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; + +import java.io.IOException; + +import com.baeldung.jackson.dtos.ItemWithSerializer; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JacksonDeserializationUnitTest { + + @Test + public final void givenDeserializerIsOnClass_whenDeserializingCustomRepresentation_thenCorrect() throws JsonParseException, JsonMappingException, IOException { + final String json = "{\"id\":1,\"itemName\":\"theItem\",\"owner\":2}"; + + final ItemWithSerializer readValue = new ObjectMapper().readValue(json, ItemWithSerializer.class); + assertThat(readValue, notNullValue()); + } + +} diff --git a/jackson/src/test/java/org/baeldung/jackson/try1/RestLoaderRequest.java b/jackson/src/test/java/com/baeldung/jackson/try1/RestLoaderRequest.java similarity index 96% rename from jackson/src/test/java/org/baeldung/jackson/try1/RestLoaderRequest.java rename to jackson/src/test/java/com/baeldung/jackson/try1/RestLoaderRequest.java index 171f4c1e14..7ef8864a63 100644 --- a/jackson/src/test/java/org/baeldung/jackson/try1/RestLoaderRequest.java +++ b/jackson/src/test/java/com/baeldung/jackson/try1/RestLoaderRequest.java @@ -1,4 +1,4 @@ -package org.baeldung.jackson.try1; +package com.baeldung.jackson.try1; import java.io.Serializable; diff --git a/jackson/src/test/java/com/baeldung/jackson/try1/RestLoaderRequestDeserializer.java b/jackson/src/test/java/com/baeldung/jackson/try1/RestLoaderRequestDeserializer.java new file mode 100644 index 0000000000..529c05ddcc --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/try1/RestLoaderRequestDeserializer.java @@ -0,0 +1,46 @@ +package com.baeldung.jackson.try1; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +public class RestLoaderRequestDeserializer extends StdDeserializer> { + private static final long serialVersionUID = -4245207329377196889L; + + public RestLoaderRequestDeserializer() { + this(null); + } + + public RestLoaderRequestDeserializer(final Class vc) { + super(vc); + } + + @Override + public RestLoaderRequest deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException { + try { + final ObjectCodec objectCodec = jp.getCodec(); + final JsonNode node = objectCodec.readTree(jp); + final String className = node.get("className").textValue(); + final String fieldName = node.get("fieldName").textValue(); + + final Class clazz = Class.forName(className); + + final JsonNode rawEntityNode = node.get("entity"); + // How to deserialize rawEntityNode to T based on className ? + + final RestLoaderRequest request = new RestLoaderRequest(); + request.setClassName(className); + request.setFieldName(fieldName); + } catch (final ClassNotFoundException e) { + e.printStackTrace(); + } + + return null; + } + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/xml/TestXMLSerializeDeserialize.java b/jackson/src/test/java/com/baeldung/jackson/xml/TestXMLSerializeDeserialize.java new file mode 100644 index 0000000000..92d0bd13d4 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/xml/TestXMLSerializeDeserialize.java @@ -0,0 +1,86 @@ +package com.baeldung.jackson.xml; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; + +public class TestXMLSerializeDeserialize { + + @Test + public void whenJavaSerializedToXmlStr_thenCorrect() throws JsonProcessingException { + XmlMapper xmlMapper = new XmlMapper(); + String xml = xmlMapper.writeValueAsString(new SimpleBean()); + assertNotNull(xml); + } + + @Test + public void whenJavaSerializedToXmlFile_thenCorrect() throws IOException { + XmlMapper xmlMapper = new XmlMapper(); + xmlMapper.writeValue(new File("target/simple_bean.xml"), new SimpleBean()); + File file = new File("target/simple_bean.xml"); + assertNotNull(file); + } + + @Test + public void whenJavaGotFromXmlStr_thenCorrect() throws IOException { + XmlMapper xmlMapper = new XmlMapper(); + SimpleBean value = xmlMapper.readValue( + "12", SimpleBean.class); + assertTrue(value.getX() == 1 && value.getY() == 2); + } + + @Test + public void whenJavaGotFromXmlFile_thenCorrect() throws IOException { + File file = new File("src/test/resources/simple_bean.xml"); + XmlMapper xmlMapper = new XmlMapper(); + String xml = inputStreamToString(new FileInputStream(file)); + SimpleBean value = xmlMapper.readValue(xml, SimpleBean.class); + assertTrue(value.getX() == 1 && value.getY() == 2); + } + + private static String inputStreamToString(InputStream is) throws IOException { + BufferedReader br; + StringBuilder sb = new StringBuilder(); + + String line; + br = new BufferedReader(new InputStreamReader(is)); + while ((line = br.readLine()) != null) { + sb.append(line); + } + br.close(); + return sb.toString(); + } +} + +class SimpleBean { + private int x = 1; + private int y = 2; + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + +} diff --git a/jackson/src/test/java/org/baeldung/jackson/annotation/Zoo.java b/jackson/src/test/java/org/baeldung/jackson/annotation/Zoo.java deleted file mode 100644 index d59be09f12..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/annotation/Zoo.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.baeldung.jackson.annotation; - -import com.fasterxml.jackson.annotation.JsonSubTypes; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.fasterxml.jackson.annotation.JsonTypeInfo.As; -import com.fasterxml.jackson.annotation.JsonTypeName; - -public class Zoo { - public Animal animal; - - public Zoo() { - - } - - public Zoo(final Animal animal) { - this.animal = animal; - } - - @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type") - @JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "dog"), @JsonSubTypes.Type(value = Cat.class, name = "cat") }) - public static class Animal { - public String name; - - public Animal() { - } - - public Animal(final String name) { - this.name = name; - } - } - - @JsonTypeName("dog") - public static class Dog extends Animal { - public double barkVolume; - - public Dog() { - } - - public Dog(final String name) { - this.name = name; - } - } - - @JsonTypeName("cat") - public static class Cat extends Animal { - boolean likesCream; - public int lives; - - public Cat() { - } - - public Cat(final String name) { - this.name = name; - } - } -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/CustomListDeserializer.java b/jackson/src/test/java/org/baeldung/jackson/bidirection/CustomListDeserializer.java deleted file mode 100644 index cc4e1d5589..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/CustomListDeserializer.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.baeldung.jackson.bidirection; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; - -public class CustomListDeserializer extends JsonDeserializer> { - - @Override - public List deserialize(final JsonParser jsonparser, final DeserializationContext context) throws IOException, JsonProcessingException { - return new ArrayList(); - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/CustomListSerializer.java b/jackson/src/test/java/org/baeldung/jackson/bidirection/CustomListSerializer.java deleted file mode 100644 index 545f7e18c1..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/CustomListSerializer.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.baeldung.jackson.bidirection; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -public class CustomListSerializer extends JsonSerializer> { - - @Override - public void serialize(final List items, final JsonGenerator generator, final SerializerProvider provider) throws IOException, JsonProcessingException { - final List ids = new ArrayList(); - for (final ItemWithSerializer item : items) { - ids.add(item.id); - } - generator.writeObject(ids); - } -} diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/Item.java b/jackson/src/test/java/org/baeldung/jackson/bidirection/Item.java deleted file mode 100644 index 223721dc62..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/Item.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.baeldung.jackson.bidirection; - -public class Item { - public int id; - public String itemName; - public User owner; - - public Item() { - super(); - } - - public Item(final int id, final String itemName, final User owner) { - this.id = id; - this.itemName = itemName; - this.owner = owner; - } -} diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithSerializer.java b/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithSerializer.java deleted file mode 100644 index d9d9612677..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/ItemWithSerializer.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.baeldung.jackson.bidirection; - -public class ItemWithSerializer { - public int id; - public String itemName; - public UserWithSerializer owner; - - public ItemWithSerializer() { - super(); - } - - public ItemWithSerializer(final int id, final String itemName, final UserWithSerializer owner) { - this.id = id; - this.itemName = itemName; - this.owner = owner; - } -} diff --git a/jackson/src/test/java/org/baeldung/jackson/bidirection/User.java b/jackson/src/test/java/org/baeldung/jackson/bidirection/User.java deleted file mode 100644 index a92dff4052..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/bidirection/User.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.baeldung.jackson.bidirection; - -import java.util.ArrayList; -import java.util.List; - -public class User { - public int id; - public String name; - public List userItems; - - public User() { - super(); - } - - public User(final int id, final String name) { - this.id = id; - this.name = name; - userItems = new ArrayList(); - } - - public void addItem(final Item item) { - userItems.add(item); - } -} diff --git a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateDeserializer.java b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateDeserializer.java deleted file mode 100644 index eb1866026f..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateDeserializer.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.baeldung.jackson.date; - -import java.io.IOException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; - -public class CustomDateDeserializer extends JsonDeserializer { - - private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); - - @Override - public Date deserialize(final JsonParser jsonparser, final DeserializationContext context) throws IOException, JsonProcessingException { - final String date = jsonparser.getText(); - try { - return formatter.parse(date); - } catch (final ParseException e) { - throw new RuntimeException(e); - } - } - -} diff --git a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateSerializer.java b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateSerializer.java deleted file mode 100644 index 40aad21482..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateSerializer.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.baeldung.jackson.date; - -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -public class CustomDateSerializer extends JsonSerializer { - - private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); - - @Override - public void serialize(final Date value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { - gen.writeString(formatter.format(value)); - } -} diff --git a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateTimeSerializer.java b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateTimeSerializer.java deleted file mode 100644 index 9f2a290bc4..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateTimeSerializer.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.baeldung.jackson.date; - -import java.io.IOException; - -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -public class CustomDateTimeSerializer extends JsonSerializer { - - private static DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"); - - @Override - public void serialize(final DateTime value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { - gen.writeString(formatter.print(value)); - } -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/date/CustomLocalDateTimeSerializer.java b/jackson/src/test/java/org/baeldung/jackson/date/CustomLocalDateTimeSerializer.java deleted file mode 100644 index b1e6a8ba86..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/date/CustomLocalDateTimeSerializer.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.baeldung.jackson.date; - -import java.io.IOException; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -public class CustomLocalDateTimeSerializer extends JsonSerializer { - - private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); - - @Override - public void serialize(final LocalDateTime value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { - gen.writeString(formatter.format(value)); - } -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/deserialization/ItemDeserializer.java b/jackson/src/test/java/org/baeldung/jackson/deserialization/ItemDeserializer.java deleted file mode 100644 index baf5b945e7..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/deserialization/ItemDeserializer.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.baeldung.jackson.deserialization; - -import java.io.IOException; - -import org.baeldung.jackson.dtos.Item; -import org.baeldung.jackson.dtos.User; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.IntNode; - -public class ItemDeserializer extends JsonDeserializer { - - /** - * {"id":1,"itemNr":"theItem","owner":2} - */ - @Override - public Item deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException { - final JsonNode node = jp.getCodec().readTree(jp); - final int id = (Integer) ((IntNode) node.get("id")).numberValue(); - final String itemName = node.get("itemName").asText(); - final int userId = (Integer) ((IntNode) node.get("createdBy")).numberValue(); - - return new Item(id, itemName, new User(userId, null)); - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/deserialization/ItemDeserializerOnClass.java b/jackson/src/test/java/org/baeldung/jackson/deserialization/ItemDeserializerOnClass.java deleted file mode 100644 index 346f75db07..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/deserialization/ItemDeserializerOnClass.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.baeldung.jackson.deserialization; - -import java.io.IOException; - -import org.baeldung.jackson.dtos.ItemWithSerializer; -import org.baeldung.jackson.dtos.User; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.IntNode; - -public class ItemDeserializerOnClass extends JsonDeserializer { - - /** - * {"id":1,"itemNr":"theItem","owner":2} - */ - @Override - public ItemWithSerializer deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException { - final JsonNode node = jp.getCodec().readTree(jp); - final int id = (Integer) ((IntNode) node.get("id")).numberValue(); - final String itemName = node.get("itemName").asText(); - final int userId = (Integer) ((IntNode) node.get("owner")).numberValue(); - - return new ItemWithSerializer(id, itemName, new User(userId, null)); - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/deserialization/JacksonDeserializeTest.java b/jackson/src/test/java/org/baeldung/jackson/deserialization/JacksonDeserializeTest.java new file mode 100644 index 0000000000..71d5ad3d81 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/deserialization/JacksonDeserializeTest.java @@ -0,0 +1,40 @@ +package org.baeldung.jackson.deserialization; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.baeldung.jackson.entities.Movie; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +public class JacksonDeserializeTest { + + @Test + public void whenSimpleDeserialize_thenCorrect() throws IOException { + + String jsonInput = "{\"imdbId\":\"tt0472043\",\"actors\":[{\"imdbId\":\"nm2199632\",\"dateOfBirth\":\"1982-09-21T12:00:00+01:00\",\"filmography\":[\"Apocalypto\",\"Beatdown\",\"Wind Walkers\"]}]}"; + ObjectMapper mapper = new ObjectMapper(); + Movie movie = mapper.readValue(jsonInput, Movie.class); + + String expectedOutput = "Movie [imdbId=tt0472043, director=null, actors=[ActorJackson [imdbId=nm2199632, dateOfBirth=Tue Sep 21 04:00:00 PDT 1982, filmography=[Apocalypto, Beatdown, Wind Walkers]]]]"; + Assert.assertEquals(movie.toString(), expectedOutput); + } + + @Test + public void whenCustomDeserialize_thenCorrect() throws IOException { + + String jsonInput = "{\"imdbId\":\"tt0472043\",\"director\":\"Mel Gibson\",\"actors\":[{\"imdbId\":\"nm2199632\",\"dateOfBirth\":\"1982-09-21T12:00:00+01:00\",\"filmography\":[\"Apocalypto\",\"Beatdown\",\"Wind Walkers\"]}]}"; + + ObjectMapper mapper = new ObjectMapper(); + final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + mapper.setDateFormat(df); + + Movie movie = mapper.readValue(jsonInput, Movie.class); + + String expectedOutput = "Movie [imdbId=tt0472043, director=Mel Gibson, actors=[ActorJackson [imdbId=nm2199632, dateOfBirth=Tue Sep 21 12:00:00 PDT 1982, filmography=[Apocalypto, Beatdown, Wind Walkers]]]]"; + Assert.assertEquals(movie.toString(), expectedOutput); + } + +} diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/Item.java b/jackson/src/test/java/org/baeldung/jackson/dtos/Item.java deleted file mode 100644 index 1dd840372a..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/Item.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.baeldung.jackson.dtos; - -public class Item { - public int id; - public String itemName; - public User owner; - - public Item() { - super(); - } - - public Item(final int id, final String itemName, final User owner) { - this.id = id; - this.itemName = itemName; - this.owner = owner; - } - - // API - - public int getId() { - return id; - } - - public String getItemName() { - return itemName; - } - - public User getOwner() { - return owner; - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/ItemWithSerializer.java b/jackson/src/test/java/org/baeldung/jackson/dtos/ItemWithSerializer.java deleted file mode 100644 index 6dadfa4908..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/ItemWithSerializer.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.baeldung.jackson.dtos; - -import org.baeldung.jackson.deserialization.ItemDeserializerOnClass; -import org.baeldung.jackson.serialization.ItemSerializerOnClass; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -@JsonSerialize(using = ItemSerializerOnClass.class) -@JsonDeserialize(using = ItemDeserializerOnClass.class) -public class ItemWithSerializer { - public final int id; - public final String itemName; - public final User owner; - - public ItemWithSerializer(final int id, final String itemName, final User owner) { - this.id = id; - this.itemName = itemName; - this.owner = owner; - } - - // API - - public int getId() { - return id; - } - - public String getItemName() { - return itemName; - } - - public User getOwner() { - return owner; - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDto.java b/jackson/src/test/java/org/baeldung/jackson/dtos/MyDto.java deleted file mode 100644 index 668eea3fcc..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/MyDto.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.baeldung.jackson.dtos; - -public class MyDto { - - private String stringValue; - private int intValue; - private boolean booleanValue; - - public MyDto() { - super(); - } - - public MyDto(final String stringValue, final int intValue, final boolean booleanValue) { - super(); - - this.stringValue = stringValue; - this.intValue = intValue; - this.booleanValue = booleanValue; - } - - // API - - public String getStringValue() { - return stringValue; - } - - public void setStringValue(final String stringValue) { - this.stringValue = stringValue; - } - - public int getIntValue() { - return intValue; - } - - public void setIntValue(final int intValue) { - this.intValue = intValue; - } - - public boolean isBooleanValue() { - return booleanValue; - } - - public void setBooleanValue(final boolean booleanValue) { - this.booleanValue = booleanValue; - } - - // - - @Override - public String toString() { - return "MyDto [stringValue=" + stringValue + ", intValue=" + intValue + ", booleanValue=" + booleanValue + "]"; - } - -} diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/MyMixInForString.java b/jackson/src/test/java/org/baeldung/jackson/dtos/MyMixInForString.java deleted file mode 100644 index 3d5228139e..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/MyMixInForString.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.baeldung.jackson.dtos; - -import com.fasterxml.jackson.annotation.JsonIgnoreType; - -@JsonIgnoreType -public class MyMixInForString { - // -} diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/User.java b/jackson/src/test/java/org/baeldung/jackson/dtos/User.java deleted file mode 100644 index cef29f11b4..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/User.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.baeldung.jackson.dtos; - -public class User { - public int id; - public String name; - - public User() { - super(); - } - - public User(final int id, final String name) { - this.id = id; - this.name = name; - } - - // API - - public int getId() { - return id; - } - - public String getName() { - return name; - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeSerializer.java b/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeSerializer.java deleted file mode 100644 index 8aa7e5c551..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/dtos/withEnum/TypeSerializer.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.baeldung.jackson.dtos.withEnum; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -public class TypeSerializer extends JsonSerializer { - - @Override - public void serialize(final TypeEnumWithCustomSerializer value, final JsonGenerator generator, final SerializerProvider provider) throws IOException, JsonProcessingException { - generator.writeStartObject(); - generator.writeFieldName("id"); - generator.writeNumber(value.getId()); - generator.writeFieldName("name"); - generator.writeString(value.getName()); - generator.writeEndObject(); - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/exception/User.java b/jackson/src/test/java/org/baeldung/jackson/exception/User.java deleted file mode 100644 index 764d5872ad..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/exception/User.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.baeldung.jackson.exception; - -public class User { - public int id; - public String name; - - public User(final int id, final String name) { - this.id = id; - this.name = name; - } -} diff --git a/jackson/src/test/java/org/baeldung/jackson/exception/Zoo.java b/jackson/src/test/java/org/baeldung/jackson/exception/Zoo.java deleted file mode 100644 index 79c24569f2..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/exception/Zoo.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.baeldung.jackson.exception; - -public class Zoo { - public Animal animal; - - public Zoo() { - } -} - -abstract class Animal { - public String name; - - public Animal() { - } -} - -class Cat extends Animal { - public int lives; - - public Cat() { - } -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/field/MyDto.java b/jackson/src/test/java/org/baeldung/jackson/field/MyDto.java deleted file mode 100644 index edfc9d2f91..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/field/MyDto.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.baeldung.jackson.field; - -public class MyDto { - - private String stringValue; - private int intValue; - private boolean booleanValue; - - public MyDto() { - super(); - } - - public MyDto(final String stringValue, final int intValue, final boolean booleanValue) { - super(); - - this.stringValue = stringValue; - this.intValue = intValue; - this.booleanValue = booleanValue; - } - - // API - - public String getStringValue() { - return stringValue; - } - - public void setStringValue(final String stringValue) { - this.stringValue = stringValue; - } - - public int getIntValue() { - return intValue; - } - - public void setIntValue(final int intValue) { - this.intValue = intValue; - } - - public boolean getBooleanValue() { - return booleanValue; - } - - public void setBooleanValue(final boolean booleanValue) { - this.booleanValue = booleanValue; - } - -} diff --git a/jackson/src/test/java/org/baeldung/jackson/jsonview/Item.java b/jackson/src/test/java/org/baeldung/jackson/jsonview/Item.java deleted file mode 100644 index 5705f810af..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/jsonview/Item.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.baeldung.jackson.jsonview; - -import com.fasterxml.jackson.annotation.JsonView; - -public class Item { - @JsonView(Views.Public.class) - public int id; - - @JsonView(Views.Public.class) - public String itemName; - - @JsonView(Views.Internal.class) - public String ownerName; - - public Item() { - super(); - } - - public Item(final int id, final String itemName, final String ownerName) { - this.id = id; - this.itemName = itemName; - this.ownerName = ownerName; - } - - public int getId() { - return id; - } - - public String getItemName() { - return itemName; - } - - public String getOwnerName() { - return ownerName; - } -} diff --git a/jackson/src/test/java/org/baeldung/jackson/jsonview/User.java b/jackson/src/test/java/org/baeldung/jackson/jsonview/User.java deleted file mode 100644 index 5850dcbe84..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/jsonview/User.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.baeldung.jackson.jsonview; - -import com.fasterxml.jackson.annotation.JsonView; - -public class User { - public int id; - - @JsonView(Views.Public.class) - public String name; - - public User() { - super(); - } - - public User(final int id, final String name) { - this.id = id; - this.name = name; - } - - public int getId() { - return id; - } - - public String getName() { - return name; - } -} diff --git a/jackson/src/test/java/org/baeldung/jackson/sandbox/SandboxTest.java b/jackson/src/test/java/org/baeldung/jackson/sandbox/SandboxTest.java deleted file mode 100644 index 19491377e8..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/sandbox/SandboxTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.baeldung.jackson.sandbox; - -import java.io.IOException; - -import org.junit.Test; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class SandboxTest { - - @Test - public final void whenDeserializing_thenCorrect() throws JsonParseException, JsonMappingException, IOException { - final TestElement testElement = new TestElement(); - testElement.setX(10); - testElement.setY("adasd"); - final ObjectMapper om = new ObjectMapper(); - om.setVisibilityChecker(om.getSerializationConfig().getDefaultVisibilityChecker().withFieldVisibility(JsonAutoDetect.Visibility.ANY).withGetterVisibility(JsonAutoDetect.Visibility.NONE)); - - final String serialized = om.writeValueAsString(testElement); - System.err.println(serialized); - } - - // - -} diff --git a/jackson/src/test/java/org/baeldung/jackson/serialization/ItemSerializer.java b/jackson/src/test/java/org/baeldung/jackson/serialization/ItemSerializer.java deleted file mode 100644 index 7a1362a416..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/serialization/ItemSerializer.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.jackson.serialization; - -import java.io.IOException; - -import org.baeldung.jackson.dtos.Item; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -public class ItemSerializer extends JsonSerializer { - - @Override - public final void serialize(final Item value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { - jgen.writeStartObject(); - jgen.writeNumberField("id", value.id); - jgen.writeStringField("itemName", value.itemName); - jgen.writeNumberField("owner", value.owner.id); - jgen.writeEndObject(); - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/serialization/ItemSerializerOnClass.java b/jackson/src/test/java/org/baeldung/jackson/serialization/ItemSerializerOnClass.java deleted file mode 100644 index 44060cabb9..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/serialization/ItemSerializerOnClass.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.jackson.serialization; - -import java.io.IOException; - -import org.baeldung.jackson.dtos.ItemWithSerializer; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -public class ItemSerializerOnClass extends JsonSerializer { - - @Override - public final void serialize(final ItemWithSerializer value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { - jgen.writeStartObject(); - jgen.writeNumberField("id", value.id); - jgen.writeStringField("itemName", value.itemName); - jgen.writeNumberField("owner", value.owner.id); - jgen.writeEndObject(); - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/serialization/JacksonSerializeTest.java b/jackson/src/test/java/org/baeldung/jackson/serialization/JacksonSerializeTest.java new file mode 100644 index 0000000000..6c8aa90fae --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/serialization/JacksonSerializeTest.java @@ -0,0 +1,60 @@ +package org.baeldung.jackson.serialization; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; + +import org.baeldung.jackson.entities.ActorJackson; +import org.baeldung.jackson.entities.Movie; +import org.baeldung.jackson.entities.MovieWithNullValue; +import org.baeldung.jackson.serialization.ActorJacksonSerializer; +import org.junit.Assert; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.module.SimpleModule; + +public class JacksonSerializeTest { + + @Test + public void whenSimpleSerialize_thenCorrect() throws JsonProcessingException, ParseException { + + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); + + ActorJackson rudyYoungblood = new ActorJackson("nm2199632", sdf.parse("21-09-1982"), Arrays.asList("Apocalypto", "Beatdown", "Wind Walkers")); + Movie movie = new Movie("tt0472043", "Mel Gibson", Arrays.asList(rudyYoungblood)); + + ObjectMapper mapper = new ObjectMapper(); + String jsonResult = mapper.writeValueAsString(movie); + + String expectedOutput = "{\"imdbId\":\"tt0472043\",\"director\":\"Mel Gibson\",\"actors\":[{\"imdbId\":\"nm2199632\",\"dateOfBirth\":401439600000,\"filmography\":[\"Apocalypto\",\"Beatdown\",\"Wind Walkers\"]}]}"; + Assert.assertEquals(jsonResult, expectedOutput); + } + + @Test + public void whenCustomSerialize_thenCorrect() throws ParseException, IOException { + + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); + + ActorJackson rudyYoungblood = new ActorJackson("nm2199632", sdf.parse("21-09-1982"), Arrays.asList("Apocalypto", "Beatdown", "Wind Walkers")); + MovieWithNullValue movieWithNullValue = new MovieWithNullValue(null, "Mel Gibson", Arrays.asList(rudyYoungblood)); + + SimpleModule module = new SimpleModule(); + module.addSerializer(new ActorJacksonSerializer(ActorJackson.class)); + ObjectMapper mapper = new ObjectMapper(); + + String jsonResult = mapper.registerModule(module).writer(new DefaultPrettyPrinter()).writeValueAsString(movieWithNullValue); + + Object json = mapper.readValue("{\"actors\":[{\"imdbId\":\"nm2199632\",\"dateOfBirth\":\"21-09-1982\",\"N° Film: \":3,\"filmography\":\"Apocalypto-Beatdown-Wind Walkers\"}],\"imdbID\":null}", Object.class); + String expectedOutput = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT).writeValueAsString(json); + + Assert.assertEquals(jsonResult, expectedOutput); + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/serialization/MyDtoNullKeySerializer.java b/jackson/src/test/java/org/baeldung/jackson/serialization/MyDtoNullKeySerializer.java deleted file mode 100644 index 8219abaddf..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/serialization/MyDtoNullKeySerializer.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.baeldung.jackson.serialization; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -public class MyDtoNullKeySerializer extends JsonSerializer { - - @Override - public void serialize(final Object value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { - jgen.writeFieldName(""); - } - -} diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonDeserializationUnitTest.java b/jackson/src/test/java/org/baeldung/jackson/test/JacksonDeserializationUnitTest.java deleted file mode 100644 index 2ecca664a4..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/test/JacksonDeserializationUnitTest.java +++ /dev/null @@ -1,168 +0,0 @@ -package org.baeldung.jackson.test; - -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - -import java.io.IOException; - -import org.baeldung.jackson.deserialization.ItemDeserializer; -import org.baeldung.jackson.dtos.Item; -import org.baeldung.jackson.dtos.ItemWithSerializer; -import org.baeldung.jackson.dtos.MyDto; -import org.baeldung.jackson.dtos.ignore.MyDtoIgnoreUnknown; -import org.junit.Test; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; -import com.fasterxml.jackson.databind.module.SimpleModule; - -public class JacksonDeserializationUnitTest { - - @Test - public final void whenDeserializingAJsonToAClass_thenCorrect() throws JsonParseException, JsonMappingException, IOException { - final String jsonAsString = "{\"stringValue\":\"a\",\"intValue\":1,\"booleanValue\":true}"; - final ObjectMapper mapper = new ObjectMapper(); - - final MyDto readValue = mapper.readValue(jsonAsString, MyDto.class); - - assertNotNull(readValue); - assertThat(readValue.getStringValue(), equalTo("a")); - } - - @Test - public final void givenNotAllFieldsHaveValuesInJson_whenDeserializingAJsonToAClass_thenCorrect() throws JsonParseException, JsonMappingException, IOException { - final String jsonAsString = "{\"stringValue\":\"a\",\"booleanValue\":true}"; - final ObjectMapper mapper = new ObjectMapper(); - - final MyDto readValue = mapper.readValue(jsonAsString, MyDto.class); - - assertNotNull(readValue); - assertThat(readValue.getStringValue(), equalTo("a")); - assertThat(readValue.isBooleanValue(), equalTo(true)); - } - - // tests - json with unknown fields - - @Test(expected = UnrecognizedPropertyException.class) - public final void givenJsonHasUnknownValues_whenDeserializingAJsonToAClass_thenExceptionIsThrown() throws JsonParseException, JsonMappingException, IOException { - final String jsonAsString = "{\"stringValue\":\"a\",\"intValue\":1,\"booleanValue\":true,\"stringValue2\":\"something\"}"; - final ObjectMapper mapper = new ObjectMapper(); - - final MyDto readValue = mapper.readValue(jsonAsString, MyDto.class); - - assertNotNull(readValue); - assertThat(readValue.getStringValue(), equalTo("a")); - assertThat(readValue.isBooleanValue(), equalTo(true)); - assertThat(readValue.getIntValue(), equalTo(1)); - } - - @Test - public final void givenJsonHasUnknownValuesButJacksonIsIgnoringUnknownFields_whenDeserializing_thenCorrect() throws JsonParseException, JsonMappingException, IOException { - final String jsonAsString = // @formatter:off - "{\"stringValue\":\"a\"," + - "\"intValue\":1," + - "\"booleanValue\":true," + - "\"stringValue2\":\"something\"}"; // @formatter:on - final ObjectMapper mapper = new ObjectMapper(); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - - final MyDto readValue = mapper.readValue(jsonAsString, MyDto.class); - - assertNotNull(readValue); - assertThat(readValue.getStringValue(), equalTo("a")); - assertThat(readValue.isBooleanValue(), equalTo(true)); - assertThat(readValue.getIntValue(), equalTo(1)); - } - - @Test - public final void givenJsonHasUnknownValuesButUnknownFieldsAreIgnoredOnClass_whenDeserializing_thenCorrect() throws JsonParseException, JsonMappingException, IOException { - final String jsonAsString = // @formatter:off - "{\"stringValue\":\"a\"," + - "\"intValue\":1," + - "\"booleanValue\":true," + - "\"stringValue2\":\"something\"}"; // @formatter:on - final ObjectMapper mapper = new ObjectMapper(); - - final MyDtoIgnoreUnknown readValue = mapper.readValue(jsonAsString, MyDtoIgnoreUnknown.class); - - assertNotNull(readValue); - assertThat(readValue.getStringValue(), equalTo("a")); - assertThat(readValue.isBooleanValue(), equalTo(true)); - assertThat(readValue.getIntValue(), equalTo(1)); - } - - // to JsonNode - - @Test - public final void whenParsingJsonStringIntoJsonNode_thenCorrect() throws JsonParseException, IOException { - final String jsonString = "{\"k1\":\"v1\",\"k2\":\"v2\"}"; - - final ObjectMapper mapper = new ObjectMapper(); - final JsonNode actualObj = mapper.readTree(jsonString); - - assertNotNull(actualObj); - } - - @Test - public final void givenUsingLowLevelDetails_whenParsingJsonStringIntoJsonNode_thenCorrect() throws JsonParseException, IOException { - final String jsonString = "{\"k1\":\"v1\",\"k2\":\"v2\"}"; - - final ObjectMapper mapper = new ObjectMapper(); - final JsonFactory factory = mapper.getFactory(); - final JsonParser parser = factory.createParser(jsonString); - final JsonNode actualObj = mapper.readTree(parser); - - assertNotNull(actualObj); - } - - @Test - public final void givenTheJsonNode_whenRetrievingDataFromId_thenCorrect() throws JsonParseException, IOException { - final String jsonString = "{\"k1\":\"v1\",\"k2\":\"v2\"}"; - final ObjectMapper mapper = new ObjectMapper(); - final JsonNode actualObj = mapper.readTree(jsonString); - - // When - final JsonNode jsonNode1 = actualObj.get("k1"); - assertThat(jsonNode1.textValue(), equalTo("v1")); - } - - // custom deserialization - - @Test - public final void whenDeserializingTheStandardRepresentation_thenCorrect() throws JsonParseException, JsonMappingException, IOException { - final String json = "{\"id\":1,\"itemName\":\"theItem\",\"owner\":{\"id\":2,\"name\":\"theUser\"}}"; - - final Item readValue = new ObjectMapper().readValue(json, Item.class); - assertThat(readValue, notNullValue()); - } - - @Test - public final void whenDeserializingANonStandardRepresentation_thenCorrect() throws JsonParseException, JsonMappingException, IOException { - final String json = "{\"id\":1,\"itemName\":\"theItem\",\"createdBy\":2}"; - final ObjectMapper mapper = new ObjectMapper(); - - final SimpleModule module = new SimpleModule(); - module.addDeserializer(Item.class, new ItemDeserializer()); - mapper.registerModule(module); - - final Item readValue = mapper.readValue(json, Item.class); - assertThat(readValue, notNullValue()); - } - - @Test - public final void givenDeserializerIsOnClass_whenDeserializingCustomRepresentation_thenCorrect() throws JsonParseException, JsonMappingException, IOException { - final String json = "{\"id\":1,\"itemName\":\"theItem\",\"owner\":2}"; - - final ItemWithSerializer readValue = new ObjectMapper().readValue(json, ItemWithSerializer.class); - assertThat(readValue, notNullValue()); - } - -} diff --git a/jackson/src/test/java/org/baeldung/jackson/try1/IEntity.java b/jackson/src/test/java/org/baeldung/jackson/try1/IEntity.java deleted file mode 100644 index ce4c83729a..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/try1/IEntity.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.baeldung.jackson.try1; - -public interface IEntity { - public int getId(); -} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/try1/JacksonDeserializationUnitTest.java b/jackson/src/test/java/org/baeldung/jackson/try1/JacksonDeserializationUnitTest.java deleted file mode 100644 index 673577cf6f..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/try1/JacksonDeserializationUnitTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.baeldung.jackson.try1; - -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; - -import java.io.IOException; - -import org.baeldung.jackson.dtos.ItemWithSerializer; -import org.junit.Test; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class JacksonDeserializationUnitTest { - - @Test - public final void givenDeserializerIsOnClass_whenDeserializingCustomRepresentation_thenCorrect() throws JsonParseException, JsonMappingException, IOException { - final String json = "{\"id\":1,\"itemName\":\"theItem\",\"owner\":2}"; - - final ItemWithSerializer readValue = new ObjectMapper().readValue(json, ItemWithSerializer.class); - assertThat(readValue, notNullValue()); - } - -} diff --git a/jackson/src/test/java/org/baeldung/jackson/try1/RestLoaderRequestDeserializer.java b/jackson/src/test/java/org/baeldung/jackson/try1/RestLoaderRequestDeserializer.java deleted file mode 100644 index 6110e8b0e0..0000000000 --- a/jackson/src/test/java/org/baeldung/jackson/try1/RestLoaderRequestDeserializer.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.baeldung.jackson.try1; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.ObjectCodec; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -public class RestLoaderRequestDeserializer extends JsonDeserializer> { - - @Override - public RestLoaderRequest deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException { - try { - final ObjectCodec objectCodec = jp.getCodec(); - final JsonNode node = objectCodec.readTree(jp); - final String className = node.get("className").textValue(); - final String fieldName = node.get("fieldName").textValue(); - - final Class clazz = Class.forName(className); - - final JsonNode rawEntityNode = node.get("entity"); - // How to deserialize rawEntityNode to T based on className ? - - final RestLoaderRequest request = new RestLoaderRequest(); - request.setClassName(className); - request.setFieldName(fieldName); - } catch (final ClassNotFoundException e) { - e.printStackTrace(); - } - - return null; - } - -} \ No newline at end of file diff --git a/jackson/src/test/resources/simple_bean.xml b/jackson/src/test/resources/simple_bean.xml new file mode 100644 index 0000000000..7829ea35a4 --- /dev/null +++ b/jackson/src/test/resources/simple_bean.xml @@ -0,0 +1,4 @@ + + 1 + 2 + \ No newline at end of file diff --git a/java-cassandra/pom.xml b/java-cassandra/pom.xml new file mode 100644 index 0000000000..265a230eb4 --- /dev/null +++ b/java-cassandra/pom.xml @@ -0,0 +1,102 @@ + + 4.0.0 + com.baeldung + cassandra-java-client + 1.0.0-SNAPSHOT + + cassandra-java-client + + + UTF-8 + + + 1.7.21 + 1.1.7 + + + 1.3 + 4.12 + 1.10.19 + 6.8 + 3.5.1 + + + 3.5.1 + + + 3.1.0 + + + + + + com.datastax.cassandra + cassandra-driver-core + ${cassandra-driver-core.version} + true + + + + + org.cassandraunit + cassandra-unit + 3.0.0.1 + + + + + com.google.guava + guava + 19.0 + + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + + junit + junit + ${junit.version} + test + + + + + java-cassandra + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + + diff --git a/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraClient.java b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraClient.java new file mode 100644 index 0000000000..c67a2c2ddb --- /dev/null +++ b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraClient.java @@ -0,0 +1,44 @@ +package com.baeldung.cassandra.java.client; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.cassandra.java.client.domain.Book; +import com.baeldung.cassandra.java.client.repository.BookRepository; +import com.baeldung.cassandra.java.client.repository.KeyspaceRepository; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.utils.UUIDs; + +public class CassandraClient { + private static final Logger LOG = LoggerFactory.getLogger(CassandraClient.class); + + public static void main(String args[]) { + CassandraConnector connector = new CassandraConnector(); + connector.connect("127.0.0.1", null); + Session session = connector.getSession(); + + KeyspaceRepository sr = new KeyspaceRepository(session); + sr.createKeyspace("library", "SimpleStrategy", 1); + sr.useKeyspace("library"); + + BookRepository br = new BookRepository(session); + br.createTable(); + br.alterTablebooks("publisher", "text"); + + br.createTableBooksByTitle(); + + Book book = new Book(UUIDs.timeBased(), "Effective Java", "Joshua Bloch", "Programming"); + br.insertBookBatch(book); + + br.selectAll().forEach(o -> LOG.info("Title in books: " + o.getTitle())); + br.selectAllBookByTitle().forEach(o -> LOG.info("Title in booksByTitle: " + o.getTitle())); + + br.deletebookByTitle("Effective Java"); + br.deleteTable("books"); + br.deleteTable("booksByTitle"); + + sr.deleteKeyspace("library"); + + connector.close(); + } +} diff --git a/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraConnector.java b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraConnector.java new file mode 100644 index 0000000000..e035335ca0 --- /dev/null +++ b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraConnector.java @@ -0,0 +1,51 @@ +package com.baeldung.cassandra.java.client; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.Cluster.Builder; +import com.datastax.driver.core.Host; +import com.datastax.driver.core.Metadata; +import com.datastax.driver.core.Session; + +/** + * + * This is an implementation of a simple Java client. + * + */ +public class CassandraConnector { + private static final Logger LOG = LoggerFactory.getLogger(CassandraConnector.class); + + private Cluster cluster; + + private Session session; + + public void connect(final String node, final Integer port) { + + Builder b = Cluster.builder().addContactPoint(node); + + if (port != null) { + b.withPort(port); + } + cluster = b.build(); + + Metadata metadata = cluster.getMetadata(); + LOG.info("Cluster name: " + metadata.getClusterName()); + + for (Host host : metadata.getAllHosts()) { + LOG.info("Datacenter: " + host.getDatacenter() + " Host: " + host.getAddress() + " Rack: " + host.getRack()); + } + + session = cluster.connect(); + } + + public Session getSession() { + return this.session; + } + + public void close() { + session.close(); + cluster.close(); + } +} diff --git a/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/domain/Book.java b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/domain/Book.java new file mode 100644 index 0000000000..e6c7753eb3 --- /dev/null +++ b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/domain/Book.java @@ -0,0 +1,66 @@ +package com.baeldung.cassandra.java.client.domain; + +import java.util.UUID; + +public class Book { + + private UUID id; + + private String title; + + private String author; + + private String subject; + + private String publisher; + + Book() { + } + + public Book(UUID id, String title, String author, String subject) { + this.id = id; + this.title = title; + this.author = author; + this.subject = subject; + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getPublisher() { + return publisher; + } + + public void setPublisher(String publisher) { + this.publisher = publisher; + } +} diff --git a/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/BookRepository.java b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/BookRepository.java new file mode 100644 index 0000000000..31e2969e01 --- /dev/null +++ b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/BookRepository.java @@ -0,0 +1,177 @@ +package com.baeldung.cassandra.java.client.repository; + +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.cassandra.java.client.domain.Book; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; + +public class BookRepository { + + private static final String TABLE_NAME = "books"; + + private static final String TABLE_NAME_BY_TITLE = TABLE_NAME + "ByTitle"; + + private Session session; + + public BookRepository(Session session) { + this.session = session; + } + + /** + * Creates the books table. + */ + public void createTable() { + StringBuilder sb = new StringBuilder("CREATE TABLE IF NOT EXISTS ").append(TABLE_NAME).append("(").append("id uuid PRIMARY KEY, ").append("title text,").append("author text,").append("subject text);"); + + final String query = sb.toString(); + session.execute(query); + } + + /** + * Creates the books table. + */ + public void createTableBooksByTitle() { + StringBuilder sb = new StringBuilder("CREATE TABLE IF NOT EXISTS ").append(TABLE_NAME_BY_TITLE).append("(").append("id uuid, ").append("title text,").append("PRIMARY KEY (title, id));"); + + final String query = sb.toString(); + session.execute(query); + } + + /** + * Alters the table books and adds an extra column. + */ + public void alterTablebooks(String columnName, String columnType) { + StringBuilder sb = new StringBuilder("ALTER TABLE ").append(TABLE_NAME).append(" ADD ").append(columnName).append(" ").append(columnType).append(";"); + + final String query = sb.toString(); + session.execute(query); + } + + /** + * Insert a row in the table books. + * + * @param book + */ + public void insertbook(Book book) { + StringBuilder sb = new StringBuilder("INSERT INTO ").append(TABLE_NAME).append("(id, title, author, subject) ").append("VALUES (").append(book.getId()).append(", '").append(book.getTitle()).append("', '").append(book.getAuthor()).append("', '") + .append(book.getSubject()).append("');"); + + final String query = sb.toString(); + session.execute(query); + } + + /** + * Insert a row in the table booksByTitle. + * @param book + */ + public void insertbookByTitle(Book book) { + StringBuilder sb = new StringBuilder("INSERT INTO ").append(TABLE_NAME_BY_TITLE).append("(id, title) ").append("VALUES (").append(book.getId()).append(", '").append(book.getTitle()).append("');"); + + final String query = sb.toString(); + session.execute(query); + } + + /** + * Insert a book into two identical tables using a batch query. + * + * @param book + */ + public void insertBookBatch(Book book) { + StringBuilder sb = new StringBuilder("BEGIN BATCH ") + .append("INSERT INTO ").append(TABLE_NAME).append("(id, title, author, subject) ") + .append("VALUES (").append(book.getId()).append(", '").append(book.getTitle()).append("', '").append(book.getAuthor()).append("', '") + .append(book.getSubject()).append("');") + .append("INSERT INTO ").append(TABLE_NAME_BY_TITLE).append("(id, title) ") + .append("VALUES (").append(book.getId()).append(", '").append(book.getTitle()).append("');") + .append("APPLY BATCH;"); + + final String query = sb.toString(); + session.execute(query); + } + + /** + * Select book by id. + * + * @return + */ + public Book selectByTitle(String title) { + StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME_BY_TITLE).append(" WHERE title = '").append(title).append("';"); + + final String query = sb.toString(); + + ResultSet rs = session.execute(query); + + List books = new ArrayList(); + + for (Row r : rs) { + Book s = new Book(r.getUUID("id"), r.getString("title"), null, null); + books.add(s); + } + + return books.get(0); + } + + /** + * Select all books from books + * + * @return + */ + public List selectAll() { + StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME); + + final String query = sb.toString(); + ResultSet rs = session.execute(query); + + List books = new ArrayList(); + + for (Row r : rs) { + Book book = new Book(r.getUUID("id"), r.getString("title"), r.getString("author"), r.getString("subject")); + books.add(book); + } + return books; + } + + /** + * Select all books from booksByTitle + * @return + */ + public List selectAllBookByTitle() { + StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME_BY_TITLE); + + final String query = sb.toString(); + ResultSet rs = session.execute(query); + + List books = new ArrayList(); + + for (Row r : rs) { + Book book = new Book(r.getUUID("id"), r.getString("title"), null, null); + books.add(book); + } + return books; + } + + /** + * Delete a book by title. + */ + public void deletebookByTitle(String title) { + StringBuilder sb = new StringBuilder("DELETE FROM ").append(TABLE_NAME_BY_TITLE).append(" WHERE title = '").append(title).append("';"); + + final String query = sb.toString(); + session.execute(query); + } + + /** + * Delete table. + * + * @param tableName the name of the table to delete. + */ + public void deleteTable(String tableName) { + StringBuilder sb = new StringBuilder("DROP TABLE IF EXISTS ").append(tableName); + + final String query = sb.toString(); + session.execute(query); + } +} diff --git a/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepository.java b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepository.java new file mode 100644 index 0000000000..f15558f040 --- /dev/null +++ b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepository.java @@ -0,0 +1,49 @@ +package com.baeldung.cassandra.java.client.repository; + +import com.datastax.driver.core.Session; + +/** + * Repository to handle the Cassandra schema. + * + */ +public class KeyspaceRepository { + private Session session; + + public KeyspaceRepository(Session session) { + this.session = session; + } + + /** + * Method used to create any keyspace - schema. + * + * @param schemaName the name of the schema. + * @param replicatioonStrategy the replication strategy. + * @param numberOfReplicas the number of replicas. + * + */ + public void createKeyspace(String keyspaceName, String replicatioonStrategy, int numberOfReplicas) { + StringBuilder sb = new StringBuilder("CREATE KEYSPACE IF NOT EXISTS ").append(keyspaceName).append(" WITH replication = {").append("'class':'").append(replicatioonStrategy).append("','replication_factor':").append(numberOfReplicas).append("};"); + + final String query = sb.toString(); + + session.execute(query); + } + + public void useKeyspace(String keyspace) { + session.execute("USE " + keyspace); + } + + /** + * Method used to delete the specified schema. + * It results in the immediate, irreversable removal of the keyspace, including all tables and data contained in the keyspace. + * + * @param schemaName the name of the keyspace to delete. + */ + public void deleteKeyspace(String keyspaceName) { + StringBuilder sb = new StringBuilder("DROP KEYSPACE ").append(keyspaceName); + + final String query = sb.toString(); + + session.execute(query); + } +} diff --git a/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/BookRepositoryIntegrationTest.java b/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/BookRepositoryIntegrationTest.java new file mode 100644 index 0000000000..62eae94c7c --- /dev/null +++ b/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/BookRepositoryIntegrationTest.java @@ -0,0 +1,174 @@ +package com.baeldung.cassandra.java.client.repository; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.cassandra.exceptions.ConfigurationException; +import org.apache.thrift.transport.TTransportException; +import org.cassandraunit.utils.EmbeddedCassandraServerHelper; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.cassandra.java.client.CassandraConnector; +import com.baeldung.cassandra.java.client.domain.Book; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.exceptions.InvalidQueryException; +import com.datastax.driver.core.utils.UUIDs; + +public class BookRepositoryIntegrationTest { + + private KeyspaceRepository schemaRepository; + + private BookRepository bookRepository; + + private Session session; + + final String KEYSPACE_NAME = "testLibrary"; + final String BOOKS = "books"; + final String BOOKS_BY_TITLE = "booksByTitle"; + + @BeforeClass + public static void init() throws ConfigurationException, TTransportException, IOException, InterruptedException { + // Start an embedded Cassandra Server + EmbeddedCassandraServerHelper.startEmbeddedCassandra(20000L); + } + + @Before + public void connect() { + CassandraConnector client = new CassandraConnector(); + client.connect("127.0.0.1", 9142); + this.session = client.getSession(); + schemaRepository = new KeyspaceRepository(session); + schemaRepository.createKeyspace(KEYSPACE_NAME, "SimpleStrategy", 1); + schemaRepository.useKeyspace(KEYSPACE_NAME); + bookRepository = new BookRepository(session); + } + + @Test + public void whenCreatingATable_thenCreatedCorrectly() { + bookRepository.deleteTable(BOOKS); + bookRepository.createTable(); + + ResultSet result = session.execute("SELECT * FROM " + KEYSPACE_NAME + "." + BOOKS + ";"); + + // Collect all the column names in one list. + List columnNames = result.getColumnDefinitions().asList().stream().map(cl -> cl.getName()).collect(Collectors.toList()); + assertEquals(columnNames.size(), 4); + assertTrue(columnNames.contains("id")); + assertTrue(columnNames.contains("title")); + assertTrue(columnNames.contains("author")); + assertTrue(columnNames.contains("subject")); + } + + @Test + public void whenAlteringTable_thenAddedColumnExists() { + bookRepository.deleteTable(BOOKS); + bookRepository.createTable(); + + bookRepository.alterTablebooks("publisher", "text"); + + ResultSet result = session.execute("SELECT * FROM " + KEYSPACE_NAME + "." + BOOKS + ";"); + + boolean columnExists = result.getColumnDefinitions().asList().stream().anyMatch(cl -> cl.getName().equals("publisher")); + assertTrue(columnExists); + } + + @Test + public void whenAddingANewBook_thenBookExists() { + bookRepository.deleteTable(BOOKS_BY_TITLE); + bookRepository.createTableBooksByTitle(); + + String title = "Effective Java"; + String author = "Joshua Bloch"; + Book book = new Book(UUIDs.timeBased(), title, author, "Programming"); + bookRepository.insertbookByTitle(book); + + Book savedBook = bookRepository.selectByTitle(title); + assertEquals(book.getTitle(), savedBook.getTitle()); + } + + @Test + public void whenAddingANewBookBatch_ThenBookAddedInAllTables() { + // Create table books + bookRepository.deleteTable(BOOKS); + bookRepository.createTable(); + + // Create table booksByTitle + bookRepository.deleteTable(BOOKS_BY_TITLE); + bookRepository.createTableBooksByTitle(); + + String title = "Effective Java"; + String author = "Joshua Bloch"; + Book book = new Book(UUIDs.timeBased(), title, author, "Programming"); + bookRepository.insertBookBatch(book); + + List books = bookRepository.selectAll(); + + assertEquals(1, books.size()); + assertTrue(books.stream().anyMatch(b -> b.getTitle().equals("Effective Java"))); + + List booksByTitle = bookRepository.selectAllBookByTitle(); + + assertEquals(1, booksByTitle.size()); + assertTrue(booksByTitle.stream().anyMatch(b -> b.getTitle().equals("Effective Java"))); + } + + @Test + public void whenSelectingAll_thenReturnAllRecords() { + bookRepository.deleteTable(BOOKS); + bookRepository.createTable(); + + Book book = new Book(UUIDs.timeBased(), "Effective Java", "Joshua Bloch", "Programming"); + bookRepository.insertbook(book); + + book = new Book(UUIDs.timeBased(), "Clean Code", "Robert C. Martin", "Programming"); + bookRepository.insertbook(book); + + List books = bookRepository.selectAll(); + + assertEquals(2, books.size()); + assertTrue(books.stream().anyMatch(b -> b.getTitle().equals("Effective Java"))); + assertTrue(books.stream().anyMatch(b -> b.getTitle().equals("Clean Code"))); + } + + @Test + public void whenDeletingABookByTitle_thenBookIsDeleted() { + bookRepository.deleteTable(BOOKS_BY_TITLE); + bookRepository.createTableBooksByTitle(); + + Book book = new Book(UUIDs.timeBased(), "Effective Java", "Joshua Bloch", "Programming"); + bookRepository.insertbookByTitle(book); + + book = new Book(UUIDs.timeBased(), "Clean Code", "Robert C. Martin", "Programming"); + bookRepository.insertbookByTitle(book); + + bookRepository.deletebookByTitle("Clean Code"); + + List books = bookRepository.selectAllBookByTitle(); + assertEquals(1, books.size()); + assertTrue(books.stream().anyMatch(b -> b.getTitle().equals("Effective Java"))); + assertFalse(books.stream().anyMatch(b -> b.getTitle().equals("Clean Code"))); + + } + + @Test(expected = InvalidQueryException.class) + public void whenDeletingATable_thenUnconfiguredTable() { + bookRepository.createTable(); + bookRepository.deleteTable(BOOKS); + + session.execute("SELECT * FROM " + KEYSPACE_NAME + "." + BOOKS + ";"); + } + + @AfterClass + public static void cleanup() { + EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); + } +} diff --git a/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepositoryIntegrationTest.java b/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepositoryIntegrationTest.java new file mode 100644 index 0000000000..9df46b3176 --- /dev/null +++ b/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepositoryIntegrationTest.java @@ -0,0 +1,77 @@ +package com.baeldung.cassandra.java.client.repository; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.cassandra.exceptions.ConfigurationException; +import org.apache.thrift.transport.TTransportException; +import org.cassandraunit.utils.EmbeddedCassandraServerHelper; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.baeldung.cassandra.java.client.CassandraConnector; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Session; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class KeyspaceRepositoryIntegrationTest { + + private KeyspaceRepository schemaRepository; + + private Session session; + + @BeforeClass + public static void init() throws ConfigurationException, TTransportException, IOException, InterruptedException { + // Start an embedded Cassandra Server + EmbeddedCassandraServerHelper.startEmbeddedCassandra(20000L); + } + + @Before + public void connect() { + CassandraConnector client = new CassandraConnector(); + client.connect("127.0.0.1", 9142); + this.session = client.getSession(); + schemaRepository = new KeyspaceRepository(session); + } + + @Test + public void whenCreatingAKeyspace_thenCreated() { + String keyspaceName = "testBaeldungKeyspace"; + schemaRepository.createKeyspace(keyspaceName, "SimpleStrategy", 1); + + // ResultSet result = session.execute("SELECT * FROM system_schema.keyspaces WHERE keyspace_name = 'testBaeldungKeyspace';"); + + ResultSet result = session.execute("SELECT * FROM system_schema.keyspaces;"); + + // Check if the Keyspace exists in the returned keyspaces. + List matchedKeyspaces = result.all().stream().filter(r -> r.getString(0).equals(keyspaceName.toLowerCase())).map(r -> r.getString(0)).collect(Collectors.toList()); + assertEquals(matchedKeyspaces.size(), 1); + assertTrue(matchedKeyspaces.get(0).equals(keyspaceName.toLowerCase())); + } + + @Test + public void whenDeletingAKeyspace_thenDoesNotExist() { + String keyspaceName = "testBaeldungKeyspace"; + + // schemaRepository.createKeyspace(keyspaceName, "SimpleStrategy", 1); + schemaRepository.deleteKeyspace(keyspaceName); + + ResultSet result = session.execute("SELECT * FROM system_schema.keyspaces;"); + boolean isKeyspaceCreated = result.all().stream().anyMatch(r -> r.getString(0).equals(keyspaceName.toLowerCase())); + assertFalse(isKeyspaceCreated); + } + + @AfterClass + public static void cleanup() { + EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); + } +} diff --git a/javaxval/bin/pom.xml b/javaxval/bin/pom.xml index 592f3c3431..7606f0d072 100644 --- a/javaxval/bin/pom.xml +++ b/javaxval/bin/pom.xml @@ -1,7 +1,7 @@ 4.0.0 - org.baeldung + com.baeldung javaxval 0.1-SNAPSHOT diff --git a/javaxval/pom.xml b/javaxval/pom.xml index 592f3c3431..493119d92e 100644 --- a/javaxval/pom.xml +++ b/javaxval/pom.xml @@ -1,51 +1,47 @@ - - 4.0.0 - org.baeldung - javaxval - 0.1-SNAPSHOT + + 4.0.0 + com.baeldung + javaxval + 0.1-SNAPSHOT + - + + junit + junit + 4.12 + + + javax.validation + validation-api + 1.1.0.Final + - - junit - junit - 4.12 - + + org.hibernate + hibernate-validator + 5.2.1.Final + - - javax.validation - validation-api - 1.1.0.Final - + + org.hibernate + hibernate-validator-annotation-processor + 5.2.1.Final + - - org.hibernate - hibernate-validator - 5.2.1.Final - + + javax.el + javax.el-api + 2.2.4 + - - org.hibernate - hibernate-validator-annotation-processor - 5.2.1.Final - - - - javax.el - javax.el-api - 2.2.4 - - - - org.glassfish.web - javax.el - 2.2.4 - - - + + org.glassfish.web + javax.el + 2.2.4 + + \ No newline at end of file diff --git a/jee7schedule/pom.xml b/jee7schedule/pom.xml new file mode 100644 index 0000000000..627b8723e3 --- /dev/null +++ b/jee7schedule/pom.xml @@ -0,0 +1,311 @@ + + + 4.0.0 + + com.baeldung + jee7schedule + 1.0-SNAPSHOT + JavaEE 7 Arquillian Archetype Sample + war + + + 1.7 + 3.0.0 + + 4.11 + 7.0 + + 1.1.4.Final + + 8.0.0.Final + + + + ${maven.min.version} + + + + + + org.jboss.arquillian + arquillian-bom + ${version.arquillian_core} + import + pom + + + + + + + javax + javaee-api + ${version.javaee_api} + provided + + + + junit + junit + ${version.junit} + test + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + com.jayway.awaitility + awaitility + 1.6.0 + test + + + + org.jboss.shrinkwrap.resolver + shrinkwrap-resolver-impl-maven + test + jar + + + + org.jboss.shrinkwrap.resolver + shrinkwrap-resolver-impl-maven-archive + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${java.min.version} + ${java.min.version} + + + + org.apache.maven.plugins + maven-war-plugin + 2.1.1 + + false + + + + + + + + + wildfly-managed-arquillian + + true + + + standalone-full.xml + ${project.build.directory}/wildfly-${version.wildfly} + + + + io.undertow + undertow-websockets-jsr + 1.0.0.Beta25 + test + + + org.jboss.resteasy + resteasy-client + 3.0.5.Final + test + + + org.jboss.resteasy + resteasy-jaxb-provider + 3.0.5.Final + test + + + org.jboss.resteasy + resteasy-json-p-provider + 3.0.5.Final + test + + + org.wildfly + wildfly-arquillian-container-managed + ${version.wildfly} + test + + + + + + maven-dependency-plugin + 2.8 + + ${maven.test.skip} + + + + unpack + process-test-classes + + unpack + + + + + org.wildfly + wildfly-dist + ${version.wildfly} + zip + false + ${project.build.directory} + + + + + + + + maven-surefire-plugin + 2.17 + + + ${project.build.directory}/wildfly-${version.wildfly} + + + + + + + + wildfly-remote-arquillian + + + io.undertow + undertow-websockets-jsr + 1.0.0.Beta25 + test + + + org.jboss.resteasy + resteasy-client + 3.0.5.Final + test + + + org.jboss.resteasy + resteasy-jaxb-provider + 3.0.5.Final + test + + + org.jboss.resteasy + resteasy-json-p-provider + 3.0.5.Final + test + + + org.wildfly + wildfly-arquillian-container-remote + ${version.wildfly} + test + + + + + glassfish-embedded-arquillian + + + org.glassfish.main.extras + glassfish-embedded-all + 4.0 + test + + + org.glassfish + javax.json + 1.0.4 + test + + + org.glassfish.tyrus + tyrus-client + 1.3 + test + + + org.glassfish.tyrus + tyrus-container-grizzly-client + 1.3 + test + + + org.glassfish.jersey.core + jersey-client + 2.4 + test + + + org.jboss.arquillian.container + arquillian-glassfish-embedded-3.1 + 1.0.0.CR4 + test + + + + + glassfish-remote-arquillian + + + org.glassfish + javax.json + 1.0.4 + test + + + org.glassfish.tyrus + tyrus-client + 1.3 + test + + + org.glassfish.tyrus + tyrus-container-grizzly-client + 1.3 + test + + + org.glassfish.jersey.core + jersey-client + 2.4 + test + + + org.glassfish.jersey.media + jersey-media-json-jackson + 2.4 + test + + + org.glassfish.jersey.media + jersey-media-json-processing + 2.4 + test + + + org.jboss.arquillian.container + arquillian-glassfish-remote-3.1 + 1.0.0.CR4 + test + + + + + diff --git a/jee7schedule/src/main/java/com/baeldung/timer/AutomaticTimerBean.java b/jee7schedule/src/main/java/com/baeldung/timer/AutomaticTimerBean.java new file mode 100644 index 0000000000..373d962f02 --- /dev/null +++ b/jee7schedule/src/main/java/com/baeldung/timer/AutomaticTimerBean.java @@ -0,0 +1,27 @@ +package com.baeldung.timer; + +import javax.ejb.Schedule; +import javax.ejb.Singleton; +import javax.ejb.Startup; +import javax.enterprise.event.Event; +import javax.inject.Inject; +import java.util.Date; + + +@Startup +@Singleton +public class AutomaticTimerBean { + + + @Inject + Event event; + + /** + * This method will be called every 10 second and will fire an @TimerEvent + */ + @Schedule(hour = "*", minute = "*", second = "*/10", info = "Every 10 second timer") + public void printDate() { + event.fire(new TimerEvent("TimerEvent sent at :" + new Date())); + } + +} diff --git a/jee7schedule/src/main/java/com/baeldung/timer/FixedDelayTimerBean.java b/jee7schedule/src/main/java/com/baeldung/timer/FixedDelayTimerBean.java new file mode 100644 index 0000000000..a466682dea --- /dev/null +++ b/jee7schedule/src/main/java/com/baeldung/timer/FixedDelayTimerBean.java @@ -0,0 +1,20 @@ +package com.baeldung.timer; + +import javax.ejb.*; + +/** + * Created by ccristianchiovari on 5/2/16. + */ +@Singleton +public class FixedDelayTimerBean { + + @EJB + private WorkerBean workerBean; + + @Lock(LockType.READ) + @Schedule(second = "*/5", minute = "*", hour = "*", persistent = false) + public void atSchedule() throws InterruptedException { + workerBean.doTimerWork(); + } + +} \ No newline at end of file diff --git a/jee7schedule/src/main/java/com/baeldung/timer/ProgrammaticAtFixedRateTimerBean.java b/jee7schedule/src/main/java/com/baeldung/timer/ProgrammaticAtFixedRateTimerBean.java new file mode 100644 index 0000000000..c1c210c8ac --- /dev/null +++ b/jee7schedule/src/main/java/com/baeldung/timer/ProgrammaticAtFixedRateTimerBean.java @@ -0,0 +1,31 @@ +package com.baeldung.timer; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import javax.ejb.*; +import javax.enterprise.event.Event; +import javax.inject.Inject; + +/** + * author: Cristian Chiovari + */ +@Startup +@Singleton +public class ProgrammaticAtFixedRateTimerBean { + + @Inject + Event event; + + @Resource + TimerService timerService; + + @PostConstruct + public void initialize() { + timerService.createTimer(0,1000, "Every second timer"); + } + + @Timeout + public void programmaticTimout(Timer timer) { + event.fire(new TimerEvent(timer.getInfo().toString())); + } +} diff --git a/jee7schedule/src/main/java/com/baeldung/timer/ProgrammaticTimerBean.java b/jee7schedule/src/main/java/com/baeldung/timer/ProgrammaticTimerBean.java new file mode 100644 index 0000000000..d2dba1239f --- /dev/null +++ b/jee7schedule/src/main/java/com/baeldung/timer/ProgrammaticTimerBean.java @@ -0,0 +1,39 @@ +package com.baeldung.timer; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import javax.ejb.*; +import javax.enterprise.event.Event; +import javax.inject.Inject; + +/** + * author: Jacek Jackowiak + */ +@Startup +@Singleton +public class ProgrammaticTimerBean { + + @Inject + Event event; + + @Resource + TimerService timerService; + + @PostConstruct + public void initialize() { + ScheduleExpression scheduleExpression = new ScheduleExpression() + .hour("*") + .minute("*") + .second("*/5"); + + TimerConfig timerConfig = new TimerConfig(); + timerConfig.setInfo("Every 5 second timer"); + + timerService.createCalendarTimer(scheduleExpression, timerConfig); + } + + @Timeout + public void programmaticTimout(Timer timer) { + event.fire(new TimerEvent(timer.getInfo().toString())); + } +} diff --git a/jee7schedule/src/main/java/com/baeldung/timer/ProgrammaticWithInitialFixedDelayTimerBean.java b/jee7schedule/src/main/java/com/baeldung/timer/ProgrammaticWithInitialFixedDelayTimerBean.java new file mode 100644 index 0000000000..9a1ebcdc57 --- /dev/null +++ b/jee7schedule/src/main/java/com/baeldung/timer/ProgrammaticWithInitialFixedDelayTimerBean.java @@ -0,0 +1,31 @@ +package com.baeldung.timer; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import javax.ejb.*; +import javax.enterprise.event.Event; +import javax.inject.Inject; + +/** + * author: Cristian Chiovari + */ +@Startup +@Singleton +public class ProgrammaticWithInitialFixedDelayTimerBean { + + @Inject + Event event; + + @Resource + TimerService timerService; + + @PostConstruct + public void initialize() { + timerService.createTimer(10000l,5000l, "Delay 10 seconds then every 5 second timer"); + } + + @Timeout + public void programmaticTimout(Timer timer) { + event.fire(new TimerEvent(timer.getInfo().toString())); + } +} diff --git a/jee7schedule/src/main/java/com/baeldung/timer/ScheduleTimerBean.java b/jee7schedule/src/main/java/com/baeldung/timer/ScheduleTimerBean.java new file mode 100644 index 0000000000..09fb95c889 --- /dev/null +++ b/jee7schedule/src/main/java/com/baeldung/timer/ScheduleTimerBean.java @@ -0,0 +1,27 @@ +package com.baeldung.timer; + +import javax.ejb.Schedule; +import javax.ejb.Singleton; +import javax.ejb.Startup; +import javax.ejb.Timer; +import javax.enterprise.event.Event; +import javax.inject.Inject; + + +@Startup +@Singleton +public class ScheduleTimerBean { + + @Inject + Event event; + + @Schedule(hour = "*", minute = "*", second = "*/5", info = "Every 5 second timer") + public void automaticallyScheduled(Timer timer) { + fireEvent(timer); + } + + + private void fireEvent(Timer timer) { + event.fire(new TimerEvent(timer.getInfo().toString())); + } +} diff --git a/jee7schedule/src/main/java/com/baeldung/timer/TimerEvent.java b/jee7schedule/src/main/java/com/baeldung/timer/TimerEvent.java new file mode 100644 index 0000000000..e430cfc1b1 --- /dev/null +++ b/jee7schedule/src/main/java/com/baeldung/timer/TimerEvent.java @@ -0,0 +1,27 @@ +package com.baeldung.timer; + +public class TimerEvent { + + private String eventInfo; + private long time = System.currentTimeMillis(); + + public TimerEvent(String s) { + this.eventInfo = s; + } + + public long getTime() { + return time; + } + + public String getEventInfo() { + return eventInfo; + } + + @Override + public String toString() { + return "TimerEvent {" + + "eventInfo='" + eventInfo + '\'' + + ", time=" + time + + '}'; + } +} diff --git a/jee7schedule/src/main/java/com/baeldung/timer/TimerEventListener.java b/jee7schedule/src/main/java/com/baeldung/timer/TimerEventListener.java new file mode 100644 index 0000000000..c89677213a --- /dev/null +++ b/jee7schedule/src/main/java/com/baeldung/timer/TimerEventListener.java @@ -0,0 +1,26 @@ +package com.baeldung.timer; + +import javax.ejb.Singleton; +import javax.ejb.Startup; +import javax.enterprise.event.Observes; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * This class will listen to all TimerEvent and will collect them + */ +@Startup +@Singleton +public class TimerEventListener { + + final List events = new CopyOnWriteArrayList<>(); + + public void listen(@Observes TimerEvent event) { + System.out.println("event = " + event); + events.add(event); + } + + public List getEvents() { + return events; + } +} diff --git a/jee7schedule/src/main/java/com/baeldung/timer/WorkerBean.java b/jee7schedule/src/main/java/com/baeldung/timer/WorkerBean.java new file mode 100644 index 0000000000..c1f781e95e --- /dev/null +++ b/jee7schedule/src/main/java/com/baeldung/timer/WorkerBean.java @@ -0,0 +1,33 @@ +package com.baeldung.timer; + +import javax.ejb.Lock; +import javax.ejb.LockType; +import javax.ejb.Singleton; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Created by cristianchiovari on 5/2/16. + */ +@Singleton +public class WorkerBean { + + private AtomicBoolean busy = new AtomicBoolean(false); + + @Lock(LockType.READ) + public void doTimerWork() throws InterruptedException { + + System.out.println("Timer method called but not started yet !"); + + if (!busy.compareAndSet(false, true)) { + return; + } + + try { + System.out.println("Timer work started"); + Thread.sleep(12000); + System.out.println("Timer work done"); + } finally { + busy.set(false); + } + } +} \ No newline at end of file diff --git a/core-java/src/main/resources/fileToMove.txt b/jee7schedule/src/main/webapp/WEB-INF/beans.xml similarity index 100% rename from core-java/src/main/resources/fileToMove.txt rename to jee7schedule/src/main/webapp/WEB-INF/beans.xml diff --git a/jee7schedule/src/test/java/com/baeldung/timer/AutomaticTimerBeanTest.java b/jee7schedule/src/test/java/com/baeldung/timer/AutomaticTimerBeanTest.java new file mode 100644 index 0000000000..df922b28df --- /dev/null +++ b/jee7schedule/src/test/java/com/baeldung/timer/AutomaticTimerBeanTest.java @@ -0,0 +1,66 @@ +package com.baeldung.timer; + +import com.jayway.awaitility.Awaitility; +import org.hamcrest.Matchers; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.resolver.api.maven.Maven; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.inject.Inject; +import java.io.File; +import java.util.concurrent.TimeUnit; + +import static com.jayway.awaitility.Awaitility.await; +import static com.jayway.awaitility.Awaitility.to; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + + +@RunWith(Arquillian.class) +public class AutomaticTimerBeanTest { + + //the @AutomaticTimerBean has a method called every 10 seconds + //testing the difference ==> 100000 + final static long TIMEOUT = 10000l; + + //the tolerance accepted , so if between two consecutive calls there has to be at least 9 or max 11 seconds. + //because the timer service is not intended for real-time applications so it will not be exactly 10 seconds + final static long TOLERANCE = 1000l; + + @Inject + TimerEventListener timerEventListener; + + @Deployment + public static WebArchive deploy() { + File[] jars = Maven.resolver().loadPomFromFile("pom.xml") + .resolve("com.jayway.awaitility:awaitility") + .withTransitivity().asFile(); + + //only @AutomaticTimerBean is deployed not the other timers + return ShrinkWrap.create(WebArchive.class) + .addAsLibraries(jars) + .addClasses(WithinWindowMatcher.class, TimerEvent.class, TimerEventListener.class, AutomaticTimerBean.class); + } + + + + @Test + public void should_receive_two_pings() { + Awaitility.setDefaultTimeout(30, TimeUnit.SECONDS); + //the test will wait here until two events are triggered + await().untilCall(to(timerEventListener.getEvents()).size(), equalTo(2)); + + TimerEvent firstEvent = timerEventListener.getEvents().get(0); + TimerEvent secondEvent = timerEventListener.getEvents().get(1); + + long delay = secondEvent.getTime() - firstEvent.getTime(); + System.out.println("Actual timeout = " + delay); + + //ensure that the delay between the events is more or less 10 seconds (no real time precision) + assertThat(delay, Matchers.is(WithinWindowMatcher.withinWindow(TIMEOUT, TOLERANCE))); + } +} diff --git a/jee7schedule/src/test/java/com/baeldung/timer/ProgrammaticAtFixedRateTimerBeanTest.java b/jee7schedule/src/test/java/com/baeldung/timer/ProgrammaticAtFixedRateTimerBeanTest.java new file mode 100644 index 0000000000..76c0e3e5b8 --- /dev/null +++ b/jee7schedule/src/test/java/com/baeldung/timer/ProgrammaticAtFixedRateTimerBeanTest.java @@ -0,0 +1,56 @@ +package com.baeldung.timer; + +import com.jayway.awaitility.Awaitility; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.resolver.api.maven.Maven; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.inject.Inject; +import java.io.File; +import java.util.concurrent.TimeUnit; + +import static com.jayway.awaitility.Awaitility.await; +import static com.jayway.awaitility.Awaitility.to; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + + +@RunWith(Arquillian.class) +public class ProgrammaticAtFixedRateTimerBeanTest { + + final static long TIMEOUT = 1000; + final static long TOLERANCE = 500l; + + @Inject + TimerEventListener timerEventListener; + + @Deployment + public static WebArchive deploy() { + File[] jars = Maven.resolver().loadPomFromFile("pom.xml") + .resolve("com.jayway.awaitility:awaitility") + .withTransitivity().asFile(); + + return ShrinkWrap.create(WebArchive.class) + .addAsLibraries(jars) + .addClasses(WithinWindowMatcher.class, TimerEvent.class, TimerEventListener.class, ProgrammaticAtFixedRateTimerBean.class); + } + + @Test + public void should_receive_ten_pings() { + + Awaitility.setDefaultTimeout(30, TimeUnit.SECONDS); + + await().untilCall(to(timerEventListener.getEvents()).size(), equalTo(10)); + TimerEvent firstEvent = timerEventListener.getEvents().get(0); + TimerEvent secondEvent = timerEventListener.getEvents().get(1); + + long delay = secondEvent.getTime() - firstEvent.getTime(); + System.out.println("Actual timeout = " + delay); + assertThat(delay, is(WithinWindowMatcher.withinWindow(TIMEOUT, TOLERANCE))); + } +} \ No newline at end of file diff --git a/jee7schedule/src/test/java/com/baeldung/timer/ProgrammaticTimerBeanTest.java b/jee7schedule/src/test/java/com/baeldung/timer/ProgrammaticTimerBeanTest.java new file mode 100644 index 0000000000..f93ba61fe3 --- /dev/null +++ b/jee7schedule/src/test/java/com/baeldung/timer/ProgrammaticTimerBeanTest.java @@ -0,0 +1,53 @@ +package com.baeldung.timer; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.resolver.api.maven.Maven; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.inject.Inject; +import java.io.File; + +import static com.jayway.awaitility.Awaitility.await; +import static com.jayway.awaitility.Awaitility.to; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + + +@RunWith(Arquillian.class) +public class ProgrammaticTimerBeanTest { + + final static long TIMEOUT = 5000l; + final static long TOLERANCE = 1000l; + + @Inject + TimerEventListener timerEventListener; + + @Deployment + public static WebArchive deploy() { + File[] jars = Maven.resolver().loadPomFromFile("pom.xml") + .resolve("com.jayway.awaitility:awaitility") + .withTransitivity().asFile(); + + return ShrinkWrap.create(WebArchive.class) + .addAsLibraries(jars) + .addClasses(WithinWindowMatcher.class, TimerEvent.class, TimerEventListener.class, ProgrammaticTimerBean.class); + } + + @Test + public void should_receive_two_pings() { + + await().untilCall(to(timerEventListener.getEvents()).size(), equalTo(2)); + + TimerEvent firstEvent = timerEventListener.getEvents().get(0); + TimerEvent secondEvent = timerEventListener.getEvents().get(1); + + long delay = secondEvent.getTime() - firstEvent.getTime(); + System.out.println("Actual timeout = " + delay); + assertThat(delay, is(WithinWindowMatcher.withinWindow(TIMEOUT, TOLERANCE))); + } +} \ No newline at end of file diff --git a/jee7schedule/src/test/java/com/baeldung/timer/ProgrammaticWithFixedDelayTimerBeanTest.java b/jee7schedule/src/test/java/com/baeldung/timer/ProgrammaticWithFixedDelayTimerBeanTest.java new file mode 100644 index 0000000000..6764aa386d --- /dev/null +++ b/jee7schedule/src/test/java/com/baeldung/timer/ProgrammaticWithFixedDelayTimerBeanTest.java @@ -0,0 +1,61 @@ +package com.baeldung.timer; + +import com.jayway.awaitility.Awaitility; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.resolver.api.maven.Maven; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.inject.Inject; +import java.io.File; +import java.util.concurrent.TimeUnit; + +import static com.jayway.awaitility.Awaitility.await; +import static com.jayway.awaitility.Awaitility.to; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; + + +@RunWith(Arquillian.class) +public class ProgrammaticWithFixedDelayTimerBeanTest { + + final static long TIMEOUT = 15000l; + final static long TOLERANCE = 1000l; + + @Inject + TimerEventListener timerEventListener; + + @Deployment + public static WebArchive deploy() { + File[] jars = Maven.resolver().loadPomFromFile("pom.xml") + .resolve("com.jayway.awaitility:awaitility") + .withTransitivity().asFile(); + + return ShrinkWrap.create(WebArchive.class) + .addAsLibraries(jars) + .addClasses(WithinWindowMatcher.class, TimerEvent.class, TimerEventListener.class, ProgrammaticWithInitialFixedDelayTimerBean.class); + } + + @Test + public void should_receive_two_pings() { + + Awaitility.setDefaultTimeout(30, TimeUnit.SECONDS); + + // 10 seconds pause so we get the startTime and it will trigger first event + long startTime = System.currentTimeMillis(); + + await().untilCall(to(timerEventListener.getEvents()).size(), equalTo(2)); + TimerEvent firstEvent = timerEventListener.getEvents().get(0); + TimerEvent secondEvent = timerEventListener.getEvents().get(1); + + long delay = secondEvent.getTime() - startTime; + System.out.println("Actual timeout = " + delay); + + //apx 15 seconds = 10 delay + 2 timers (first after a pause of 10 seconds and the next others every 5 seconds) + assertThat(delay, is(WithinWindowMatcher.withinWindow(TIMEOUT, TOLERANCE))); + } +} \ No newline at end of file diff --git a/jee7schedule/src/test/java/com/baeldung/timer/ScheduleTimerBeanTest.java b/jee7schedule/src/test/java/com/baeldung/timer/ScheduleTimerBeanTest.java new file mode 100644 index 0000000000..7a5b043101 --- /dev/null +++ b/jee7schedule/src/test/java/com/baeldung/timer/ScheduleTimerBeanTest.java @@ -0,0 +1,59 @@ +package com.baeldung.timer; + +import com.jayway.awaitility.Awaitility; +import org.hamcrest.Matchers; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.resolver.api.maven.Maven; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.inject.Inject; +import java.io.File; +import java.util.concurrent.TimeUnit; + +import static com.jayway.awaitility.Awaitility.await; +import static com.jayway.awaitility.Awaitility.to; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + + +@RunWith(Arquillian.class) +public class ScheduleTimerBeanTest { + + final static long TIMEOUT = 5000l; + final static long TOLERANCE = 1000l; + + @Inject + TimerEventListener timerEventListener; + + @Deployment + public static WebArchive deploy() { + File[] jars = Maven.resolver().loadPomFromFile("pom.xml") + .resolve("com.jayway.awaitility:awaitility") + .withTransitivity().asFile(); + + return ShrinkWrap.create(WebArchive.class) + .addAsLibraries(jars) + .addClasses(WithinWindowMatcher.class, TimerEvent.class, TimerEventListener.class, ScheduleTimerBean.class); + } + + @Test + public void should_receive_three_pings() { + + Awaitility.setDefaultTimeout(30, TimeUnit.SECONDS); + await().untilCall(to(timerEventListener.getEvents()).size(), equalTo(3)); + + TimerEvent firstEvent = timerEventListener.getEvents().get(0); + TimerEvent secondEvent = timerEventListener.getEvents().get(1); + TimerEvent thirdEvent = timerEventListener.getEvents().get(2); + + long delay = secondEvent.getTime() - firstEvent.getTime(); + assertThat(delay, Matchers.is(WithinWindowMatcher.withinWindow(TIMEOUT, TOLERANCE))); + delay = thirdEvent.getTime() - secondEvent.getTime(); + assertThat(delay, Matchers.is(WithinWindowMatcher.withinWindow(TIMEOUT, TOLERANCE))); + + } +} diff --git a/jee7schedule/src/test/java/com/baeldung/timer/WithinWindowMatcher.java b/jee7schedule/src/test/java/com/baeldung/timer/WithinWindowMatcher.java new file mode 100644 index 0000000000..91adca6042 --- /dev/null +++ b/jee7schedule/src/test/java/com/baeldung/timer/WithinWindowMatcher.java @@ -0,0 +1,30 @@ +package com.baeldung.timer; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; + +class WithinWindowMatcher extends BaseMatcher { + private final long timeout; + private final long tolerance; + + public WithinWindowMatcher(long timeout, long tolerance) { + this.timeout = timeout; + this.tolerance = tolerance; + } + + @Override + public boolean matches(Object item) { + final Long actual = (Long) item; + return Math.abs(actual - timeout) < tolerance; + } + + @Override + public void describeTo(Description description) { + //To change body of implemented methods use File | Settings | File Templates. + } + + public static Matcher withinWindow(final long timeout, final long tolerance) { + return new WithinWindowMatcher(timeout, tolerance); + } +} diff --git a/jjwt/.gitignore b/jjwt/.gitignore new file mode 100644 index 0000000000..f83e8cf07c --- /dev/null +++ b/jjwt/.gitignore @@ -0,0 +1,3 @@ +.idea +target +*.iml diff --git a/jjwt/README.md b/jjwt/README.md new file mode 100644 index 0000000000..47b51038a8 --- /dev/null +++ b/jjwt/README.md @@ -0,0 +1,45 @@ +## JWT Fun + +This tutorial walks you through the various features supported by the [JJWT](https://github.com/jwtk/jjwt) library - a fluent interface Java JWT building and parsing library. + +### Build and Run + +It's super easy to build and exercise this tutorial. + +``` +mvn clean install +java -jar target/*.jar +``` + +That's it! + +You can hit the home endpoint with your favorite command-line http client. My favorite is: [httpie](https://github.com/jkbrzt/httpie) + +`http localhost:8080` + +``` +Available commands (assumes httpie - https://github.com/jkbrzt/httpie): + + http http://localhost:8080/ + This usage message + + http http://localhost:8080/static-builder + build JWT from hardcoded claims + + http POST http://localhost:8080/dynamic-builder-general claim-1=value-1 ... [claim-n=value-n] + build JWT from passed in claims (using general claims map) + + http POST http://localhost:8080/dynamic-builder-specific claim-1=value-1 ... [claim-n=value-n] + build JWT from passed in claims (using specific claims methods) + + http POST http://localhost:8080/dynamic-builder-compress claim-1=value-1 ... [claim-n=value-n] + build DEFLATE compressed JWT from passed in claims + + http http://localhost:8080/parser?jwt= + Parse passed in JWT + + http http://localhost:8080/parser-enforce?jwt= + Parse passed in JWT enforcing the 'iss' registered claim and the 'hasMotorcycle' custom claim +``` + +The Baeldung post that compliments this repo can be found [here](http://www.baeldung.com/) \ No newline at end of file diff --git a/jjwt/pom.xml b/jjwt/pom.xml new file mode 100644 index 0000000000..24f1c5c5ab --- /dev/null +++ b/jjwt/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + io.jsonwebtoken + jjwtfun + 0.0.1-SNAPSHOT + jar + + jjwtfun + Exercising the JJWT + + + org.springframework.boot + spring-boot-starter-parent + 1.3.5.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-devtools + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.boot + spring-boot-starter-test + test + + + + io.jsonwebtoken + jjwt + 0.6.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/JJWTFunApplication.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/JJWTFunApplication.java new file mode 100644 index 0000000000..5c106aac70 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/JJWTFunApplication.java @@ -0,0 +1,12 @@ +package io.jsonwebtoken.jjwtfun; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class JJWTFunApplication { + + public static void main(String[] args) { + SpringApplication.run(JJWTFunApplication.class, args); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java new file mode 100644 index 0000000000..7d88835243 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/CSRFConfig.java @@ -0,0 +1,21 @@ +package io.jsonwebtoken.jjwtfun.config; + +import io.jsonwebtoken.jjwtfun.service.SecretService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.web.csrf.CsrfTokenRepository; + +@Configuration +public class CSRFConfig { + + @Autowired + SecretService secretService; + + @Bean + @ConditionalOnMissingBean + public CsrfTokenRepository jwtCsrfTokenRepository() { + return new JWTCsrfTokenRepository(secretService.getHS256SecretBytes()); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java new file mode 100644 index 0000000000..bf88b8aff1 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/JWTCsrfTokenRepository.java @@ -0,0 +1,68 @@ +package io.jsonwebtoken.jjwtfun.config; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.csrf.CsrfTokenRepository; +import org.springframework.security.web.csrf.DefaultCsrfToken; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.util.Date; +import java.util.UUID; + +public class JWTCsrfTokenRepository implements CsrfTokenRepository { + + private static final String DEFAULT_CSRF_TOKEN_ATTR_NAME = CSRFConfig.class.getName().concat(".CSRF_TOKEN"); + + private static final Logger log = LoggerFactory.getLogger(JWTCsrfTokenRepository.class); + private byte[] secret; + + public JWTCsrfTokenRepository(byte[] secret) { + this.secret = secret; + } + + @Override + public CsrfToken generateToken(HttpServletRequest request) { + String id = UUID.randomUUID().toString().replace("-", ""); + + Date now = new Date(); + Date exp = new Date(System.currentTimeMillis() + (1000*30)); // 30 seconds + + String token = Jwts.builder() + .setId(id) + .setIssuedAt(now) + .setNotBefore(now) + .setExpiration(exp) + .signWith(SignatureAlgorithm.HS256, secret) + .compact(); + + return new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", token); + } + + @Override + public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) { + if (token == null) { + HttpSession session = request.getSession(false); + if (session != null) { + session.removeAttribute(DEFAULT_CSRF_TOKEN_ATTR_NAME); + } + } + else { + HttpSession session = request.getSession(); + session.setAttribute(DEFAULT_CSRF_TOKEN_ATTR_NAME, token); + } + } + + @Override + public CsrfToken loadToken(HttpServletRequest request) { + HttpSession session = request.getSession(false); + if (session == null || "GET".equals(request.getMethod())) { + return null; + } + return (CsrfToken) session.getAttribute(DEFAULT_CSRF_TOKEN_ATTR_NAME); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java new file mode 100644 index 0000000000..94e2c6ddc5 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/config/WebSecurityConfig.java @@ -0,0 +1,85 @@ +package io.jsonwebtoken.jjwtfun.config; + +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.jjwtfun.service.SecretService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.csrf.CsrfFilter; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.csrf.CsrfTokenRepository; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Arrays; + +@Configuration +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + CsrfTokenRepository jwtCsrfTokenRepository; + + @Autowired + SecretService secretService; + + // ordered so we can use binary search below + private String[] ignoreCsrfAntMatchers = { + "/dynamic-builder-compress", + "/dynamic-builder-general", + "/dynamic-builder-specific", + "/set-secrets" + }; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .addFilterAfter(new JwtCsrfValidatorFilter(), CsrfFilter.class) + .csrf() + .csrfTokenRepository(jwtCsrfTokenRepository) + .ignoringAntMatchers(ignoreCsrfAntMatchers) + .and().authorizeRequests() + .antMatchers("/**") + .permitAll(); + } + + private class JwtCsrfValidatorFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + // NOTE: A real implementation should have a nonce cache so the token cannot be reused + + CsrfToken token = (CsrfToken) request.getAttribute("_csrf"); + + if ( + // only care if it's a POST + "POST".equals(request.getMethod()) && + // ignore if the request path is in our list + Arrays.binarySearch(ignoreCsrfAntMatchers, request.getServletPath()) < 0 && + // make sure we have a token + token != null + ) { + // CsrfFilter already made sure the token matched. Here, we'll make sure it's not expired + try { + Jwts.parser() + .setSigningKeyResolver(secretService.getSigningKeyResolver()) + .parseClaimsJws(token.getToken()); + } catch (JwtException e) { + // most likely an ExpiredJwtException, but this will handle any + request.setAttribute("exception", e); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + RequestDispatcher dispatcher = request.getRequestDispatcher("expired-jwt"); + dispatcher.forward(request, response); + } + } + + filterChain.doFilter(request, response); + } + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/BaseController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/BaseController.java new file mode 100644 index 0000000000..e1e195c6ab --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/BaseController.java @@ -0,0 +1,23 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.SignatureException; +import io.jsonwebtoken.jjwtfun.model.JwtResponse; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; + +public class BaseController { + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler({SignatureException.class, MalformedJwtException.class, JwtException.class}) + public JwtResponse exception(Exception e) { + JwtResponse response = new JwtResponse(); + response.setStatus(JwtResponse.Status.ERROR); + response.setMessage(e.getMessage()); + response.setExceptionType(e.getClass().getName()); + + return response; + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java new file mode 100644 index 0000000000..c03c63dd80 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/DynamicJWTController.java @@ -0,0 +1,108 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import io.jsonwebtoken.JwtBuilder; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.impl.compression.CompressionCodecs; +import io.jsonwebtoken.jjwtfun.model.JwtResponse; +import io.jsonwebtoken.jjwtfun.service.SecretService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.UnsupportedEncodingException; +import java.time.Instant; +import java.util.Date; +import java.util.Map; + +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +@RestController +public class DynamicJWTController extends BaseController { + + @Autowired + SecretService secretService; + + @RequestMapping(value = "/dynamic-builder-general", method = POST) + public JwtResponse dynamicBuilderGeneric(@RequestBody Map claims) throws UnsupportedEncodingException { + String jws = Jwts.builder() + .setClaims(claims) + .signWith( + SignatureAlgorithm.HS256, + secretService.getHS256SecretBytes() + ) + .compact(); + return new JwtResponse(jws); + } + + @RequestMapping(value = "/dynamic-builder-compress", method = POST) + public JwtResponse dynamicBuildercompress(@RequestBody Map claims) throws UnsupportedEncodingException { + String jws = Jwts.builder() + .setClaims(claims) + .compressWith(CompressionCodecs.DEFLATE) + .signWith( + SignatureAlgorithm.HS256, + secretService.getHS256SecretBytes() + ) + .compact(); + return new JwtResponse(jws); + } + + @RequestMapping(value = "/dynamic-builder-specific", method = POST) + public JwtResponse dynamicBuilderSpecific(@RequestBody Map claims) throws UnsupportedEncodingException { + JwtBuilder builder = Jwts.builder(); + + claims.forEach((key, value) -> { + switch (key) { + case "iss": + ensureType(key, value, String.class); + builder.setIssuer((String) value); + break; + case "sub": + ensureType(key, value, String.class); + builder.setSubject((String) value); + break; + case "aud": + ensureType(key, value, String.class); + builder.setAudience((String) value); + break; + case "exp": + ensureType(key, value, Long.class); + builder.setExpiration(Date.from(Instant.ofEpochSecond(Long.parseLong(value.toString())))); + break; + case "nbf": + ensureType(key, value, Long.class); + builder.setNotBefore(Date.from(Instant.ofEpochSecond(Long.parseLong(value.toString())))); + break; + case "iat": + ensureType(key, value, Long.class); + builder.setIssuedAt(Date.from(Instant.ofEpochSecond(Long.parseLong(value.toString())))); + break; + case "jti": + ensureType(key, value, String.class); + builder.setId((String) value); + break; + default: + builder.claim(key, value); + } + }); + + builder.signWith(SignatureAlgorithm.HS256, secretService.getHS256SecretBytes()); + + return new JwtResponse(builder.compact()); + } + + private void ensureType(String registeredClaim, Object value, Class expectedType) { + boolean isCorrectType = + expectedType.isInstance(value) || + expectedType == Long.class && value instanceof Integer; + + if (!isCorrectType) { + String msg = "Expected type: " + expectedType.getCanonicalName() + " for registered claim: '" + + registeredClaim + "', but got value: " + value + " of type: " + value.getClass().getCanonicalName(); + throw new JwtException(msg); + } + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java new file mode 100644 index 0000000000..54123c63cb --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/FormController.java @@ -0,0 +1,29 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +@Controller +public class FormController { + + @RequestMapping(value = "/jwt-csrf-form", method = GET) + public String csrfFormGet() { + return "jwt-csrf-form"; + } + + @RequestMapping(value = "/jwt-csrf-form", method = POST) + public String csrfFormPost(@RequestParam(name = "_csrf") String csrf, Model model) { + model.addAttribute("csrf", csrf); + return "jwt-csrf-form-result"; + } + + @RequestMapping("/expired-jwt") + public String expiredJwt() { + return "expired-jwt"; + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java new file mode 100644 index 0000000000..57cd14385e --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/HomeController.java @@ -0,0 +1,32 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; + +@RestController +public class HomeController { + + @RequestMapping("/") + public String home(HttpServletRequest req) { + String requestUrl = getUrl(req); + return "Available commands (assumes httpie - https://github.com/jkbrzt/httpie):\n\n" + + " http " + requestUrl + "/\n\tThis usage message\n\n" + + " http " + requestUrl + "/static-builder\n\tbuild JWT from hardcoded claims\n\n" + + " http POST " + requestUrl + "/dynamic-builder-general claim-1=value-1 ... [claim-n=value-n]\n\tbuild JWT from passed in claims (using general claims map)\n\n" + + " http POST " + requestUrl + "/dynamic-builder-specific claim-1=value-1 ... [claim-n=value-n]\n\tbuild JWT from passed in claims (using specific claims methods)\n\n" + + " http POST " + requestUrl + "/dynamic-builder-compress claim-1=value-1 ... [claim-n=value-n]\n\tbuild DEFLATE compressed JWT from passed in claims\n\n" + + " http " + requestUrl + "/parser?jwt=\n\tParse passed in JWT\n\n" + + " http " + requestUrl + "/parser-enforce?jwt=\n\tParse passed in JWT enforcing the 'iss' registered claim and the 'hasMotorcycle' custom claim\n\n" + + " http " + requestUrl + "/get-secrets\n\tShow the signing keys currently in use.\n\n" + + " http " + requestUrl + "/refresh-secrets\n\tGenerate new signing keys and show them.\n\n" + + " http POST " + requestUrl + "/set-secrets HS256=base64-encoded-value HS384=base64-encoded-value HS512=base64-encoded-value\n\tExplicitly set secrets to use in the application."; + } + + private String getUrl(HttpServletRequest req) { + return req.getScheme() + "://" + + req.getServerName() + + ((req.getServerPort() == 80 || req.getServerPort() == 443) ? "" : ":" + req.getServerPort()); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java new file mode 100644 index 0000000000..1ca0973c33 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/SecretsController.java @@ -0,0 +1,35 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import io.jsonwebtoken.jjwtfun.service.SecretService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +@RestController +public class SecretsController extends BaseController { + + @Autowired + SecretService secretService; + + @RequestMapping(value = "/get-secrets", method = GET) + public Map getSecrets() { + return secretService.getSecrets(); + } + + @RequestMapping(value = "/refresh-secrets", method = GET) + public Map refreshSecrets() { + return secretService.refreshSecrets(); + } + + @RequestMapping(value = "/set-secrets", method = POST) + public Map setSecrets(@RequestBody Map secrets) { + secretService.setSecrets(secrets); + return secretService.getSecrets(); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java new file mode 100644 index 0000000000..83f5336978 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/controller/StaticJWTController.java @@ -0,0 +1,64 @@ +package io.jsonwebtoken.jjwtfun.controller; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.jjwtfun.model.JwtResponse; +import io.jsonwebtoken.jjwtfun.service.SecretService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.UnsupportedEncodingException; +import java.time.Instant; +import java.util.Date; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; + +@RestController +public class StaticJWTController extends BaseController { + + @Autowired + SecretService secretService; + + @RequestMapping(value = "/static-builder", method = GET) + public JwtResponse fixedBuilder() throws UnsupportedEncodingException { + String jws = Jwts.builder() + .setIssuer("Stormpath") + .setSubject("msilverman") + .claim("name", "Micah Silverman") + .claim("scope", "admins") + .setIssuedAt(Date.from(Instant.ofEpochSecond(1466796822L))) // Fri Jun 24 2016 15:33:42 GMT-0400 (EDT) + .setExpiration(Date.from(Instant.ofEpochSecond(4622470422L))) // Sat Jun 24 2116 15:33:42 GMT-0400 (EDT) + .signWith( + SignatureAlgorithm.HS256, + secretService.getHS256SecretBytes() + ) + .compact(); + + return new JwtResponse(jws); + } + + @RequestMapping(value = "/parser", method = GET) + public JwtResponse parser(@RequestParam String jwt) throws UnsupportedEncodingException { + + Jws jws = Jwts.parser() + .setSigningKeyResolver(secretService.getSigningKeyResolver()) + .parseClaimsJws(jwt); + + return new JwtResponse(jws); + } + + @RequestMapping(value = "/parser-enforce", method = GET) + public JwtResponse parserEnforce(@RequestParam String jwt) throws UnsupportedEncodingException { + Jws jws = Jwts.parser() + .requireIssuer("Stormpath") + .require("hasMotorcycle", true) + .setSigningKeyResolver(secretService.getSigningKeyResolver()) + .parseClaimsJws(jwt); + + return new JwtResponse(jws); + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java new file mode 100644 index 0000000000..491f003289 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/model/JwtResponse.java @@ -0,0 +1,70 @@ +package io.jsonwebtoken.jjwtfun.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class JwtResponse { + private String message; + private Status status; + private String exceptionType; + private String jwt; + private Jws jws; + + public enum Status { + SUCCESS, ERROR + } + + public JwtResponse() {} + + public JwtResponse(String jwt) { + this.jwt = jwt; + this.status = Status.SUCCESS; + } + + public JwtResponse(Jws jws) { + this.jws = jws; + this.status = Status.SUCCESS; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public String getExceptionType() { + return exceptionType; + } + + public void setExceptionType(String exceptionType) { + this.exceptionType = exceptionType; + } + + public String getJwt() { + return jwt; + } + + public void setJwt(String jwt) { + this.jwt = jwt; + } + + public Jws getJws() { + return jws; + } + + public void setJws(Jws jws) { + this.jws = jws; + } +} diff --git a/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java new file mode 100644 index 0000000000..4311afa592 --- /dev/null +++ b/jjwt/src/main/java/io/jsonwebtoken/jjwtfun/service/SecretService.java @@ -0,0 +1,74 @@ +package io.jsonwebtoken.jjwtfun.service; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwsHeader; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.SigningKeyResolver; +import io.jsonwebtoken.SigningKeyResolverAdapter; +import io.jsonwebtoken.impl.TextCodec; +import io.jsonwebtoken.impl.crypto.MacProvider; +import io.jsonwebtoken.lang.Assert; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.crypto.SecretKey; +import java.util.HashMap; +import java.util.Map; + +@Service +public class SecretService { + + private Map secrets = new HashMap<>(); + + private SigningKeyResolver signingKeyResolver = new SigningKeyResolverAdapter() { + @Override + public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) { + return TextCodec.BASE64.decode(secrets.get(header.getAlgorithm())); + } + }; + + @PostConstruct + public void setup() { + refreshSecrets(); + } + + public SigningKeyResolver getSigningKeyResolver() { + return signingKeyResolver; + } + + public Map getSecrets() { + return secrets; + } + + public void setSecrets(Map secrets) { + Assert.notNull(secrets); + Assert.hasText(secrets.get(SignatureAlgorithm.HS256.getValue())); + Assert.hasText(secrets.get(SignatureAlgorithm.HS384.getValue())); + Assert.hasText(secrets.get(SignatureAlgorithm.HS512.getValue())); + + this.secrets = secrets; + } + + public byte[] getHS256SecretBytes() { + return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS256.getValue())); + } + + public byte[] getHS384SecretBytes() { + return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS384.getValue())); + } + + public byte[] getHS512SecretBytes() { + return TextCodec.BASE64.decode(secrets.get(SignatureAlgorithm.HS384.getValue())); + } + + + public Map refreshSecrets() { + SecretKey key = MacProvider.generateKey(SignatureAlgorithm.HS256); + secrets.put(SignatureAlgorithm.HS256.getValue(), TextCodec.BASE64.encode(key.getEncoded())); + key = MacProvider.generateKey(SignatureAlgorithm.HS384); + secrets.put(SignatureAlgorithm.HS384.getValue(), TextCodec.BASE64.encode(key.getEncoded())); + key = MacProvider.generateKey(SignatureAlgorithm.HS512); + secrets.put(SignatureAlgorithm.HS512.getValue(), TextCodec.BASE64.encode(key.getEncoded())); + return secrets; + } +} diff --git a/spring-cloud-data-flow/batch-job/src/main/resources/application.properties b/jjwt/src/main/resources/application.properties similarity index 100% rename from spring-cloud-data-flow/batch-job/src/main/resources/application.properties rename to jjwt/src/main/resources/application.properties diff --git a/jjwt/src/main/resources/templates/expired-jwt.html b/jjwt/src/main/resources/templates/expired-jwt.html new file mode 100644 index 0000000000..7bf9ff258e --- /dev/null +++ b/jjwt/src/main/resources/templates/expired-jwt.html @@ -0,0 +1,17 @@ + + + + + +
    +
    +
    +

    JWT CSRF Token expired

    +

    + + Back +
    +
    +
    + + \ No newline at end of file diff --git a/jjwt/src/main/resources/templates/fragments/head.html b/jjwt/src/main/resources/templates/fragments/head.html new file mode 100644 index 0000000000..2d5f54e5a0 --- /dev/null +++ b/jjwt/src/main/resources/templates/fragments/head.html @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + +

    Nothing to see here, move along.

    + + \ No newline at end of file diff --git a/jjwt/src/main/resources/templates/jwt-csrf-form-result.html b/jjwt/src/main/resources/templates/jwt-csrf-form-result.html new file mode 100644 index 0000000000..cfb832bf7c --- /dev/null +++ b/jjwt/src/main/resources/templates/jwt-csrf-form-result.html @@ -0,0 +1,18 @@ + + + + + + +
    +
    +
    +

    You made it!

    +
    +

    BLARG

    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/jjwt/src/main/resources/templates/jwt-csrf-form.html b/jjwt/src/main/resources/templates/jwt-csrf-form.html new file mode 100644 index 0000000000..235f6063c9 --- /dev/null +++ b/jjwt/src/main/resources/templates/jwt-csrf-form.html @@ -0,0 +1,18 @@ + + + + + + +
    +
    +
    +

    +

    + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java b/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java new file mode 100644 index 0000000000..82138ea23e --- /dev/null +++ b/jjwt/src/test/java/io/jsonwebtoken/jjwtfun/DemoApplicationTests.java @@ -0,0 +1,18 @@ +package io.jsonwebtoken.jjwtfun; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = JJWTFunApplication.class) +@WebAppConfiguration +public class DemoApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/jooq-spring/.gitignore b/jooq-spring/.gitignore new file mode 100644 index 0000000000..aba850c8e6 --- /dev/null +++ b/jooq-spring/.gitignore @@ -0,0 +1 @@ +/src/main/java/com/baeldung/jooq/introduction/db \ No newline at end of file diff --git a/jooq-spring/pom.xml b/jooq-spring/pom.xml new file mode 100644 index 0000000000..e77ff0cbfd --- /dev/null +++ b/jooq-spring/pom.xml @@ -0,0 +1,178 @@ + + 4.0.0 + com.baeldung + jooq-spring + 0.0.1-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-dependencies + 1.3.5.RELEASE + pom + import + + + + + + + + org.jooq + jooq + ${org.jooq.version} + + + + + com.h2database + h2 + ${com.h2database.version} + + + + + org.springframework + spring-context + + + org.springframework + spring-jdbc + + + org.springframework.boot + spring-boot-starter-jooq + + + + + org.slf4j + slf4j-api + runtime + + + ch.qos.logback + logback-classic + runtime + + + + + junit + junit + test + + + org.springframework + spring-test + test + + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.0.0 + + + initialize + + read-project-properties + + + + src/main/resources/intro_config.properties + + + + + + + + org.codehaus.mojo + sql-maven-plugin + 1.5 + + + initialize + + execute + + + ${db.driver} + ${db.url} + ${db.username} + ${db.password} + + src/main/resources/intro_schema.sql + + + + + + + com.h2database + h2 + ${com.h2database.version} + + + + + + org.jooq + jooq-codegen-maven + ${org.jooq.version} + + + generate-sources + + generate + + + + ${db.driver} + ${db.url} + ${db.username} + ${db.password} + + + + com.baeldung.jooq.introduction.db + src/main/java + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + + + + 3.7.3 + 1.4.191 + 4.2.5.RELEASE + 1.7.18 + 1.1.3 + 4.12 + + 3.5.1 + + + \ No newline at end of file diff --git a/jooq-spring/src/main/resources/application.properties b/jooq-spring/src/main/resources/application.properties new file mode 100644 index 0000000000..2b32da2356 --- /dev/null +++ b/jooq-spring/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.datasource.url=jdbc:h2:~/jooq +spring.datasource.username=sa +spring.datasource.password= \ No newline at end of file diff --git a/jooq-spring/src/main/resources/intro_config.properties b/jooq-spring/src/main/resources/intro_config.properties new file mode 100644 index 0000000000..3275089585 --- /dev/null +++ b/jooq-spring/src/main/resources/intro_config.properties @@ -0,0 +1,8 @@ +#Database Configuration +db.driver=org.h2.Driver +db.url=jdbc:h2:~/jooq +db.username=sa +db.password= + +#SQL Dialect +jooq.sql.dialect=H2 \ No newline at end of file diff --git a/jooq-spring/src/main/resources/intro_schema.sql b/jooq-spring/src/main/resources/intro_schema.sql new file mode 100644 index 0000000000..0d4bd26235 --- /dev/null +++ b/jooq-spring/src/main/resources/intro_schema.sql @@ -0,0 +1,34 @@ +DROP TABLE IF EXISTS author_book, author, book; + +CREATE TABLE author ( + id INT NOT NULL PRIMARY KEY, + first_name VARCHAR(50), + last_name VARCHAR(50) NOT NULL +); + +CREATE TABLE book ( + id INT NOT NULL PRIMARY KEY, + title VARCHAR(100) NOT NULL +); + +CREATE TABLE author_book ( + author_id INT NOT NULL, + book_id INT NOT NULL, + + PRIMARY KEY (author_id, book_id), + CONSTRAINT fk_ab_author FOREIGN KEY (author_id) REFERENCES author (id) + ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT fk_ab_book FOREIGN KEY (book_id) REFERENCES book (id) +); + +INSERT INTO author VALUES + (1, 'Kathy', 'Sierra'), + (2, 'Bert', 'Bates'), + (3, 'Bryan', 'Basham'); + +INSERT INTO book VALUES + (1, 'Head First Java'), + (2, 'Head First Servlets and JSP'), + (3, 'OCA/OCP Java SE 7 Programmer'); + +INSERT INTO author_book VALUES (1, 1), (1, 3), (2, 1); \ No newline at end of file diff --git a/jooq-spring/src/test/java/com/baeldung/jooq/introduction/ExceptionTranslator.java b/jooq-spring/src/test/java/com/baeldung/jooq/introduction/ExceptionTranslator.java new file mode 100644 index 0000000000..8312f20c05 --- /dev/null +++ b/jooq-spring/src/test/java/com/baeldung/jooq/introduction/ExceptionTranslator.java @@ -0,0 +1,19 @@ +package com.baeldung.jooq.introduction; + +import org.jooq.ExecuteContext; +import org.jooq.SQLDialect; +import org.jooq.impl.DefaultExecuteListener; + +import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator; +import org.springframework.jdbc.support.SQLExceptionTranslator; + +public class ExceptionTranslator extends DefaultExecuteListener { + + @Override + public void exception(ExecuteContext context) { + SQLDialect dialect = context.configuration().dialect(); + SQLExceptionTranslator translator = new SQLErrorCodeSQLExceptionTranslator(dialect.name()); + + context.exception(translator.translate("Access database using jOOQ", context.sql(), context.sqlException())); + } +} \ No newline at end of file diff --git a/jooq-spring/src/test/java/com/baeldung/jooq/introduction/PersistenceContext.java b/jooq-spring/src/test/java/com/baeldung/jooq/introduction/PersistenceContext.java new file mode 100644 index 0000000000..df628f9f78 --- /dev/null +++ b/jooq-spring/src/test/java/com/baeldung/jooq/introduction/PersistenceContext.java @@ -0,0 +1,78 @@ +package com.baeldung.jooq.introduction; + +import org.h2.jdbcx.JdbcDataSource; +import org.jooq.SQLDialect; +import org.jooq.impl.DataSourceConnectionProvider; +import org.jooq.impl.DefaultConfiguration; +import org.jooq.impl.DefaultDSLContext; +import org.jooq.impl.DefaultExecuteListenerProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; + +@Configuration +@ComponentScan({ "com.baeldung.jooq.introduction.db.public_.tables" }) +@EnableTransactionManagement +@PropertySource("classpath:intro_config.properties") +public class PersistenceContext { + + @Autowired + private Environment environment; + + @Bean + public DataSource dataSource() { + JdbcDataSource dataSource = new JdbcDataSource(); + + dataSource.setUrl(environment.getRequiredProperty("db.url")); + dataSource.setUser(environment.getRequiredProperty("db.username")); + dataSource.setPassword(environment.getRequiredProperty("db.password")); + + return dataSource; + } + + @Bean + public TransactionAwareDataSourceProxy transactionAwareDataSource() { + return new TransactionAwareDataSourceProxy(dataSource()); + } + + @Bean + public DataSourceTransactionManager transactionManager() { + return new DataSourceTransactionManager(dataSource()); + } + + @Bean + public DataSourceConnectionProvider connectionProvider() { + return new DataSourceConnectionProvider(transactionAwareDataSource()); + } + + @Bean + public ExceptionTranslator exceptionTransformer() { + return new ExceptionTranslator(); + } + + @Bean + public DefaultDSLContext dsl() { + return new DefaultDSLContext(configuration()); + } + + @Bean + public DefaultConfiguration configuration() { + DefaultConfiguration jooqConfiguration = new DefaultConfiguration(); + jooqConfiguration.set(connectionProvider()); + jooqConfiguration.set(new DefaultExecuteListenerProvider(exceptionTransformer())); + + String sqlDialectName = environment.getRequiredProperty("jooq.sql.dialect"); + SQLDialect dialect = SQLDialect.valueOf(sqlDialectName); + jooqConfiguration.set(dialect); + + return jooqConfiguration; + } +} \ No newline at end of file diff --git a/jooq-spring/src/test/java/com/baeldung/jooq/introduction/QueryTest.java b/jooq-spring/src/test/java/com/baeldung/jooq/introduction/QueryTest.java new file mode 100644 index 0000000000..68f975dd6d --- /dev/null +++ b/jooq-spring/src/test/java/com/baeldung/jooq/introduction/QueryTest.java @@ -0,0 +1,122 @@ +package com.baeldung.jooq.introduction; + +import org.jooq.DSLContext; +import org.jooq.Record3; +import org.jooq.Result; +import org.jooq.impl.DSL; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +import static com.baeldung.jooq.introduction.db.public_.tables.Author.AUTHOR; +import static com.baeldung.jooq.introduction.db.public_.tables.AuthorBook.AUTHOR_BOOK; +import static com.baeldung.jooq.introduction.db.public_.tables.Book.BOOK; +import static org.junit.Assert.assertEquals; + +@ContextConfiguration(classes = PersistenceContext.class) +@Transactional(transactionManager = "transactionManager") +@RunWith(SpringJUnit4ClassRunner.class) +public class QueryTest { + + @Autowired + private DSLContext dsl; + + @Test + public void givenValidData_whenInserting_thenSucceed() { + dsl.insertInto(AUTHOR) + .set(AUTHOR.ID, 4) + .set(AUTHOR.FIRST_NAME, "Herbert") + .set(AUTHOR.LAST_NAME, "Schildt") + .execute(); + + dsl.insertInto(BOOK) + .set(BOOK.ID, 4) + .set(BOOK.TITLE, "A Beginner's Guide") + .execute(); + + dsl.insertInto(AUTHOR_BOOK) + .set(AUTHOR_BOOK.AUTHOR_ID, 4) + .set(AUTHOR_BOOK.BOOK_ID, 4) + .execute(); + + final Result> result = dsl.select(AUTHOR.ID, AUTHOR.LAST_NAME, DSL.count()) + .from(AUTHOR) + .join(AUTHOR_BOOK).on(AUTHOR.ID.equal(AUTHOR_BOOK.AUTHOR_ID)) + .join(BOOK).on(AUTHOR_BOOK.BOOK_ID.equal(BOOK.ID)) + .groupBy(AUTHOR.LAST_NAME).fetch(); + + assertEquals(3, result.size()); + assertEquals("Sierra", result.getValue(0, AUTHOR.LAST_NAME)); + assertEquals(Integer.valueOf(2), result.getValue(0, DSL.count())); + assertEquals("Schildt", result.getValue(2, AUTHOR.LAST_NAME)); + assertEquals(Integer.valueOf(1), result.getValue(2, DSL.count())); + } + + @Test(expected = DataAccessException.class) + public void givenInvalidData_whenInserting_thenFail() { + dsl.insertInto(AUTHOR_BOOK).set(AUTHOR_BOOK.AUTHOR_ID, 4).set(AUTHOR_BOOK.BOOK_ID, 5).execute(); + } + + @Test + public void givenValidData_whenUpdating_thenSucceed() { + dsl.update(AUTHOR) + .set(AUTHOR.LAST_NAME, "Baeldung") + .where(AUTHOR.ID.equal(3)) + .execute(); + + dsl.update(BOOK) + .set(BOOK.TITLE, "Building your REST API with Spring") + .where(BOOK.ID.equal(3)).execute(); + + dsl.insertInto(AUTHOR_BOOK) + .set(AUTHOR_BOOK.AUTHOR_ID, 3) + .set(AUTHOR_BOOK.BOOK_ID, 3) + .execute(); + + final Result> result = dsl.select(AUTHOR.ID, AUTHOR.LAST_NAME, BOOK.TITLE) + .from(AUTHOR) + .join(AUTHOR_BOOK).on(AUTHOR.ID.equal(AUTHOR_BOOK.AUTHOR_ID)) + .join(BOOK).on(AUTHOR_BOOK.BOOK_ID.equal(BOOK.ID)) + .where(AUTHOR.ID.equal(3)) + .fetch(); + + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(3), result.getValue(0, AUTHOR.ID)); + assertEquals("Baeldung", result.getValue(0, AUTHOR.LAST_NAME)); + assertEquals("Building your REST API with Spring", result.getValue(0, BOOK.TITLE)); + } + + @Test(expected = DataAccessException.class) + public void givenInvalidData_whenUpdating_thenFail() { + dsl.update(AUTHOR_BOOK) + .set(AUTHOR_BOOK.AUTHOR_ID, 4) + .set(AUTHOR_BOOK.BOOK_ID, 5) + .execute(); + } + + @Test + public void givenValidData_whenDeleting_thenSucceed() { + dsl.delete(AUTHOR) + .where(AUTHOR.ID.lt(3)) + .execute(); + + final Result> result = dsl.select(AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) + .from(AUTHOR) + .fetch(); + + assertEquals(1, result.size()); + assertEquals("Bryan", result.getValue(0, AUTHOR.FIRST_NAME)); + assertEquals("Basham", result.getValue(0, AUTHOR.LAST_NAME)); + } + + @Test(expected = DataAccessException.class) + public void givenInvalidData_whenDeleting_thenFail() { + dsl.delete(BOOK) + .where(BOOK.ID.equal(1)) + .execute(); + } +} \ No newline at end of file diff --git a/jooq-spring/src/test/java/com/baeldung/jooq/springboot/Application.java b/jooq-spring/src/test/java/com/baeldung/jooq/springboot/Application.java new file mode 100644 index 0000000000..ff74851d2a --- /dev/null +++ b/jooq-spring/src/test/java/com/baeldung/jooq/springboot/Application.java @@ -0,0 +1,9 @@ +package com.baeldung.jooq.springboot; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@SpringBootApplication +@EnableTransactionManagement +public class Application { +} \ No newline at end of file diff --git a/jooq-spring/src/test/java/com/baeldung/jooq/springboot/InitialConfiguration.java b/jooq-spring/src/test/java/com/baeldung/jooq/springboot/InitialConfiguration.java new file mode 100644 index 0000000000..c0d9dac797 --- /dev/null +++ b/jooq-spring/src/test/java/com/baeldung/jooq/springboot/InitialConfiguration.java @@ -0,0 +1,39 @@ +package com.baeldung.jooq.springboot; + +import com.baeldung.jooq.introduction.ExceptionTranslator; +import org.jooq.impl.DataSourceConnectionProvider; +import org.jooq.impl.DefaultConfiguration; +import org.jooq.impl.DefaultDSLContext; +import org.jooq.impl.DefaultExecuteListenerProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; + +import javax.sql.DataSource; + +@Configuration +public class InitialConfiguration { + + @Autowired + private DataSource dataSource; + + @Bean + public DataSourceConnectionProvider connectionProvider() { + return new DataSourceConnectionProvider(new TransactionAwareDataSourceProxy(dataSource)); + } + + @Bean + public DefaultDSLContext dsl() { + return new DefaultDSLContext(configuration()); + } + + public DefaultConfiguration configuration() { + DefaultConfiguration jooqConfiguration = new DefaultConfiguration(); + + jooqConfiguration.set(connectionProvider()); + jooqConfiguration.set(new DefaultExecuteListenerProvider(new ExceptionTranslator())); + + return jooqConfiguration; + } +} diff --git a/jooq-spring/src/test/java/com/baeldung/jooq/springboot/SpringBootTest.java b/jooq-spring/src/test/java/com/baeldung/jooq/springboot/SpringBootTest.java new file mode 100644 index 0000000000..f9427f30fb --- /dev/null +++ b/jooq-spring/src/test/java/com/baeldung/jooq/springboot/SpringBootTest.java @@ -0,0 +1,124 @@ +package com.baeldung.jooq.springboot; + +import org.jooq.DSLContext; +import org.jooq.Record3; +import org.jooq.Result; +import org.jooq.impl.DSL; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.dao.DataAccessException; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +import static com.baeldung.jooq.introduction.db.public_.tables.Author.AUTHOR; +import static com.baeldung.jooq.introduction.db.public_.tables.AuthorBook.AUTHOR_BOOK; +import static com.baeldung.jooq.introduction.db.public_.tables.Book.BOOK; +import static org.junit.Assert.assertEquals; + +@SpringApplicationConfiguration(Application.class) +@Transactional("transactionManager") +@RunWith(SpringJUnit4ClassRunner.class) +public class SpringBootTest { + + @Autowired + private DSLContext dsl; + + @Test + public void givenValidData_whenInserting_thenSucceed() { + dsl.insertInto(AUTHOR) + .set(AUTHOR.ID, 4) + .set(AUTHOR.FIRST_NAME, "Herbert") + .set(AUTHOR.LAST_NAME, "Schildt") + .execute(); + + dsl.insertInto(BOOK) + .set(BOOK.ID, 4) + .set(BOOK.TITLE, "A Beginner's Guide") + .execute(); + + dsl.insertInto(AUTHOR_BOOK) + .set(AUTHOR_BOOK.AUTHOR_ID, 4) + .set(AUTHOR_BOOK.BOOK_ID, 4) + .execute(); + + final Result> result = dsl.select(AUTHOR.ID, AUTHOR.LAST_NAME, DSL.count()) + .from(AUTHOR).join(AUTHOR_BOOK).on(AUTHOR.ID.equal(AUTHOR_BOOK.AUTHOR_ID)) + .join(BOOK).on(AUTHOR_BOOK.BOOK_ID.equal(BOOK.ID)) + .groupBy(AUTHOR.LAST_NAME) + .fetch(); + + assertEquals(3, result.size()); + assertEquals("Sierra", result.getValue(0, AUTHOR.LAST_NAME)); + assertEquals(Integer.valueOf(2), result.getValue(0, DSL.count())); + assertEquals("Schildt", result.getValue(2, AUTHOR.LAST_NAME)); + assertEquals(Integer.valueOf(1), result.getValue(2, DSL.count())); + } + + @Test(expected = DataAccessException.class) + public void givenInvalidData_whenInserting_thenFail() { + dsl.insertInto(AUTHOR_BOOK) + .set(AUTHOR_BOOK.AUTHOR_ID, 4) + .set(AUTHOR_BOOK.BOOK_ID, 5) + .execute(); + } + + @Test + public void givenValidData_whenUpdating_thenSucceed() { + dsl.update(AUTHOR) + .set(AUTHOR.LAST_NAME, "Baeldung") + .where(AUTHOR.ID.equal(3)) + .execute(); + + dsl.update(BOOK) + .set(BOOK.TITLE, "Building your REST API with Spring") + .where(BOOK.ID.equal(3)) + .execute(); + + dsl.insertInto(AUTHOR_BOOK) + .set(AUTHOR_BOOK.AUTHOR_ID, 3) + .set(AUTHOR_BOOK.BOOK_ID, 3) + .execute(); + + final Result> result = dsl.select(AUTHOR.ID, AUTHOR.LAST_NAME, BOOK.TITLE) + .from(AUTHOR).join(AUTHOR_BOOK).on(AUTHOR.ID.equal(AUTHOR_BOOK.AUTHOR_ID)) + .join(BOOK).on(AUTHOR_BOOK.BOOK_ID.equal(BOOK.ID)) + .where(AUTHOR.ID.equal(3)) + .fetch(); + + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(3), result.getValue(0, AUTHOR.ID)); + assertEquals("Baeldung", result.getValue(0, AUTHOR.LAST_NAME)); + assertEquals("Building your REST API with Spring", result.getValue(0, BOOK.TITLE)); + } + + @Test(expected = DataAccessException.class) + public void givenInvalidData_whenUpdating_thenFail() { + dsl.update(AUTHOR_BOOK) + .set(AUTHOR_BOOK.AUTHOR_ID, 4) + .set(AUTHOR_BOOK.BOOK_ID, 5) + .execute(); + } + + @Test + public void givenValidData_whenDeleting_thenSucceed() { + dsl.delete(AUTHOR) + .where(AUTHOR.ID.lt(3)) + .execute(); + + final Result> result = dsl.select(AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) + .from(AUTHOR).fetch(); + + assertEquals(1, result.size()); + assertEquals("Bryan", result.getValue(0, AUTHOR.FIRST_NAME)); + assertEquals("Basham", result.getValue(0, AUTHOR.LAST_NAME)); + } + + @Test(expected = DataAccessException.class) + public void givenInvalidData_whenDeleting_thenFail() { + dsl.delete(BOOK) + .where(BOOK.ID.equal(1)) + .execute(); + } +} \ No newline at end of file diff --git a/jpa-storedprocedure/pom.xml b/jpa-storedprocedure/pom.xml new file mode 100644 index 0000000000..b2ebaa32e2 --- /dev/null +++ b/jpa-storedprocedure/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + com.baeldung + jpa-storedprocedure + 1.0 + jar + + + 7.0 + 5.1.0.Final + 5.1.38 + + + + JpaStoredProcedure + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + maven-assembly-plugin + + + + jar-with-dependencies + + + + + + + + + + + + javax + javaee-api + ${jee.version} + provided + + + + org.hibernate + hibernate-entitymanager + ${hibernate.version} + + + + + + mysql + mysql-connector-java + 5.1.38 + + + + + + junit + junit + 4.4 + + + + commons-io + commons-io + 2.4 + + + + + \ No newline at end of file diff --git a/jpa-storedprocedure/src/main/java/com/baeldung/jpa/model/Car.java b/jpa-storedprocedure/src/main/java/com/baeldung/jpa/model/Car.java new file mode 100644 index 0000000000..676d76307e --- /dev/null +++ b/jpa-storedprocedure/src/main/java/com/baeldung/jpa/model/Car.java @@ -0,0 +1,60 @@ +package com.baeldung.jpa.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.NamedStoredProcedureQueries; +import javax.persistence.NamedStoredProcedureQuery; +import javax.persistence.ParameterMode; +import javax.persistence.StoredProcedureParameter; +import javax.persistence.Table; + +@Entity +@Table(name = "CAR") +@NamedStoredProcedureQueries({ + @NamedStoredProcedureQuery(name = "findByYearProcedure", procedureName = "FIND_CAR_BY_YEAR", resultClasses = { Car.class }, parameters = { @StoredProcedureParameter(name = "p_year", type = Integer.class, mode = ParameterMode.IN) }) }) +public class Car { + + private long id; + private String model; + private Integer year; + + public Car(final String model, final Integer year) { + this.model = model; + this.year = year; + } + + public Car() { + } + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ID", unique = true, nullable = false, scale = 0) + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + @Column(name = "MODEL") + public String getModel() { + return model; + } + + public void setModel(final String model) { + this.model = model; + } + + @Column(name = "YEAR") + public Integer getYear() { + return year; + } + + public void setYear(final Integer year) { + this.year = year; + } +} diff --git a/jpa-storedprocedure/src/main/java/com/baeldung/jpa/model/QueryParameter.java b/jpa-storedprocedure/src/main/java/com/baeldung/jpa/model/QueryParameter.java new file mode 100644 index 0000000000..0a15213f62 --- /dev/null +++ b/jpa-storedprocedure/src/main/java/com/baeldung/jpa/model/QueryParameter.java @@ -0,0 +1,28 @@ +package com.baeldung.jpa.model; + +import java.util.HashMap; +import java.util.Map; + +public class QueryParameter { + + private Map parameters = null; + + private QueryParameter(final String name, final Object value) { + this.parameters = new HashMap<>(); + this.parameters.put(name, value); + } + + public static QueryParameter with(final String name, final Object value) { + return new QueryParameter(name, value); + } + + public QueryParameter and(final String name, final Object value) { + this.parameters.put(name, value); + return this; + } + + public Map parameters() { + return this.parameters; + } + +} \ No newline at end of file diff --git a/jpa-storedprocedure/src/main/resources/META-INF/persistence.xml b/jpa-storedprocedure/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000000..4c443cb7cf --- /dev/null +++ b/jpa-storedprocedure/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,20 @@ + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.model.Car + + + + + + + + + + \ No newline at end of file diff --git a/jpa-storedprocedure/src/main/resources/config/database/FindCarByYearProcedureMySQL.sql b/jpa-storedprocedure/src/main/resources/config/database/FindCarByYearProcedureMySQL.sql new file mode 100644 index 0000000000..0ef84fb7eb --- /dev/null +++ b/jpa-storedprocedure/src/main/resources/config/database/FindCarByYearProcedureMySQL.sql @@ -0,0 +1,8 @@ +DELIMITER $$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `FIND_CAR_BY_YEAR`(in p_year int) +begin +SELECT ID, MODEL, YEAR + FROM CAR + WHERE YEAR = p_year; +end$$ +DELIMITER ; diff --git a/jpa-storedprocedure/src/main/resources/config/database/create_table_mysql.sql b/jpa-storedprocedure/src/main/resources/config/database/create_table_mysql.sql new file mode 100644 index 0000000000..4a4feebdea --- /dev/null +++ b/jpa-storedprocedure/src/main/resources/config/database/create_table_mysql.sql @@ -0,0 +1,6 @@ +CREATE TABLE `car` ( + `ID` int(10) NOT NULL AUTO_INCREMENT, + `MODEL` varchar(50) NOT NULL, + `YEAR` int(4) NOT NULL, + PRIMARY KEY (`ID`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/jpa-storedprocedure/src/main/resources/config/database/insert_cars.sql b/jpa-storedprocedure/src/main/resources/config/database/insert_cars.sql new file mode 100644 index 0000000000..89f69ac1ee --- /dev/null +++ b/jpa-storedprocedure/src/main/resources/config/database/insert_cars.sql @@ -0,0 +1,5 @@ +INSERT INTO CAR (ID, MODEL, YEAR) VALUES ('123456', 'Camaro', '2012'); +INSERT INTO CAR (ID, MODEL, YEAR) VALUES ('12112', 'Fiat Panda', '2000'); +INSERT INTO CAR (ID, MODEL, YEAR) VALUES ('111000', 'Fiat Punto', '2007'); +INSERT INTO CAR (ID, MODEL, YEAR) VALUES ('3382', 'Citroen C3', '2009'); +commit; \ No newline at end of file diff --git a/jpa-storedprocedure/src/test/java/com/baeldung/jpa/storedprocedure/StoredProcedureTest.java b/jpa-storedprocedure/src/test/java/com/baeldung/jpa/storedprocedure/StoredProcedureTest.java new file mode 100644 index 0000000000..69351d9683 --- /dev/null +++ b/jpa-storedprocedure/src/test/java/com/baeldung/jpa/storedprocedure/StoredProcedureTest.java @@ -0,0 +1,72 @@ +package com.baeldung.jpa.storedprocedure; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.ParameterMode; +import javax.persistence.Persistence; +import javax.persistence.StoredProcedureQuery; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.jpa.model.Car; + +public class StoredProcedureTest { + + private static EntityManagerFactory factory = null; + private static EntityManager entityManager = null; + + @BeforeClass + public static void init() { + factory = Persistence.createEntityManagerFactory("jpa-db"); + entityManager = factory.createEntityManager(); + } + + @Before + public void setup() { + } + + @Test + public void createCarTest() { + final EntityTransaction transaction = entityManager.getTransaction(); + try { + transaction.begin(); + final Car car = new Car("Fiat Marea", 2015); + entityManager.persist(car); + transaction.commit(); + } catch (final Exception e) { + System.out.println(e.getCause()); + if (transaction.isActive()) { + transaction.rollback(); + } + } + } + + @Test + public void findCarsByYearNamedProcedure() { + final StoredProcedureQuery findByYearProcedure = entityManager.createNamedStoredProcedureQuery("findByYearProcedure"); + final StoredProcedureQuery storedProcedure = findByYearProcedure.setParameter("p_year", 2015); + storedProcedure.getResultList().forEach(c -> Assert.assertEquals(new Integer(2015), ((Car) c).getYear())); + } + + @Test + public void findCarsByYearNoNamed() { + final StoredProcedureQuery storedProcedure = entityManager.createStoredProcedureQuery("FIND_CAR_BY_YEAR", Car.class).registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN).setParameter(1, 2015); + storedProcedure.getResultList().forEach(c -> Assert.assertEquals(new Integer(2015), ((Car) c).getYear())); + } + + @AfterClass + public static void destroy() { + + if (entityManager != null) { + entityManager.close(); + } + if (factory != null) { + factory.close(); + } + } +} diff --git a/jpa-storedprocedure/src/test/resources/persistence.xml b/jpa-storedprocedure/src/test/resources/persistence.xml new file mode 100644 index 0000000000..d94221b54f --- /dev/null +++ b/jpa-storedprocedure/src/test/resources/persistence.xml @@ -0,0 +1,21 @@ + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.model.Car + + + + + + + + + + + diff --git a/jsf/.gitignore b/jsf/.gitignore new file mode 100644 index 0000000000..d1c20ca0f1 --- /dev/null +++ b/jsf/.gitignore @@ -0,0 +1,2 @@ +/target +*.iml diff --git a/jsf/pom.xml b/jsf/pom.xml new file mode 100644 index 0000000000..6a4b358252 --- /dev/null +++ b/jsf/pom.xml @@ -0,0 +1,144 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + jsf + 0.1-SNAPSHOT + war + + + + + com.sun.faces + jsf-api + ${com.sun.faces.version} + + + com.sun.faces + jsf-impl + ${com.sun.faces.version} + + + javax.el + javax.el-api + ${javax.el.version} + + + + + + javax.servlet + jstl + 1.2 + + + + + + org.springframework + spring-web + ${org.springframework.version} + + + org.springframework + spring-webmvc + ${org.springframework.version} + + + org.springframework + spring-websocket + ${org.springframework.version} + + + org.springframework + spring-messaging + ${org.springframework.version} + + + org.springframework + spring-web + ${org.springframework.version} + + + javax.servlet + javax.servlet-api + provided + ${javax.servlet.version} + + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + false + + + + + + + + 4.2.5.RELEASE + + + 2.2.13 + 3.0.0 + + + 1.7.13 + 1.1.3 + + + 3.1.0 + + + 3.5.1 + 2.6 + + + \ No newline at end of file diff --git a/jsf/src/main/java/com/baeldung/springintegration/config/MainWebAppInitializer.java b/jsf/src/main/java/com/baeldung/springintegration/config/MainWebAppInitializer.java new file mode 100644 index 0000000000..2de647915c --- /dev/null +++ b/jsf/src/main/java/com/baeldung/springintegration/config/MainWebAppInitializer.java @@ -0,0 +1,36 @@ +package com.baeldung.springintegration.config; + +import com.sun.faces.config.FacesInitializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import java.util.Set; + +public class MainWebAppInitializer extends FacesInitializer implements WebApplicationInitializer { + private static final Logger LOGGER = LoggerFactory.getLogger(MainWebAppInitializer.class); + + @Override + public void onStartup(Set> classes, ServletContext servletContext) throws ServletException { + super.onStartup(classes, servletContext); + } + + /** + * Register and configure all Servlet container components necessary to power the web application. + */ + @Override + public void onStartup(final ServletContext sc) throws ServletException { + LOGGER.info("MainWebAppInitializer.onStartup()"); + sc.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", "true"); + + // Create the 'root' Spring application context + final AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); + root.register(SpringCoreConfig.class); + sc.addListener(new ContextLoaderListener(root)); + } + +} diff --git a/jsf/src/main/java/com/baeldung/springintegration/config/SpringCoreConfig.java b/jsf/src/main/java/com/baeldung/springintegration/config/SpringCoreConfig.java new file mode 100644 index 0000000000..a39da3fe25 --- /dev/null +++ b/jsf/src/main/java/com/baeldung/springintegration/config/SpringCoreConfig.java @@ -0,0 +1,15 @@ +package com.baeldung.springintegration.config; + +import com.baeldung.springintegration.dao.UserManagementDAO; +import com.baeldung.springintegration.dao.UserManagementDAOImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SpringCoreConfig { + + @Bean + public UserManagementDAO userManagementDAO() { + return new UserManagementDAOImpl(); + } +} diff --git a/jsf/src/main/java/com/baeldung/springintegration/controllers/ELSampleBean.java b/jsf/src/main/java/com/baeldung/springintegration/controllers/ELSampleBean.java new file mode 100644 index 0000000000..16d9f80d89 --- /dev/null +++ b/jsf/src/main/java/com/baeldung/springintegration/controllers/ELSampleBean.java @@ -0,0 +1,129 @@ +package com.baeldung.springintegration.controllers; + +import javax.annotation.PostConstruct; +import javax.el.ELContextEvent; +import javax.el.ELContextListener; +import javax.el.LambdaExpression; +import javax.faces.application.Application; +import javax.faces.application.FacesMessage; +import javax.el.LambdaExpression; +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ViewScoped; +import javax.faces.context.FacesContext; +import java.util.Collection; +import java.util.Random; + +@ManagedBean(name = "ELBean") +@ViewScoped +public class ELSampleBean { + + private String firstName; + private String lastName; + private String pageDescription = "This page demos JSF EL Basics"; + public static final String constantField = "THIS_IS_NOT_CHANGING_ANYTIME_SOON"; + private int pageCounter; + private Random randomIntGen = new Random(); + + @PostConstruct + public void init() { + pageCounter = randomIntGen.nextInt(); + FacesContext.getCurrentInstance().getApplication().addELContextListener(new ELContextListener() { + @Override + public void contextCreated(ELContextEvent evt) { + evt.getELContext().getImportHandler().importClass("com.baeldung.springintegration.controllers.ELSampleBean"); + } + }); + } + + public void save() { + + } + + public static String constantField() { + return constantField; + } + + public void saveFirstName(String firstName) { + this.firstName = firstName; + } + + public Long multiplyValue(LambdaExpression expr) { + Long theResult = (Long) expr.invoke(FacesContext.getCurrentInstance().getELContext(), pageCounter); + return theResult; + } + + public void saveByELEvaluation() { + firstName = (String) evaluateEL("#{firstName.value}", String.class); + FacesContext ctx = FacesContext.getCurrentInstance(); + FacesMessage theMessage = new FacesMessage("Name component Evaluated: " + firstName); + theMessage.setSeverity(FacesMessage.SEVERITY_INFO); + ctx.addMessage(null, theMessage); + + } + + private Object evaluateEL(String elExpression, Class clazz) { + Object toReturn = null; + FacesContext ctx = FacesContext.getCurrentInstance(); + Application app = ctx.getApplication(); + toReturn = app.evaluateExpressionGet(ctx, elExpression, clazz); + + return toReturn; + + } + + /** + * @return the firstName + */ + public String getFirstName() { + return firstName; + } + + /** + * @param firstName the firstName to set + */ + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + /** + * @return the lastName + */ + public String getLastName() { + return lastName; + } + + /** + * @param lastName the lastName to set + */ + public void setLastName(String lastName) { + this.lastName = lastName; + } + + /** + * @return the pageDescription + */ + public String getPageDescription() { + return pageDescription; + } + + /** + * @param pageDescription the pageDescription to set + */ + public void setPageDescription(String pageDescription) { + this.pageDescription = pageDescription; + } + + /** + * @return the pageCounter + */ + public int getPageCounter() { + return pageCounter; + } + + /** + * @param pageCounter the pageCounter to set + */ + public void setPageCounter(int pageCounter) { + this.pageCounter = pageCounter; + } +} diff --git a/jsf/src/main/java/com/baeldung/springintegration/controllers/RegistrationBean.java b/jsf/src/main/java/com/baeldung/springintegration/controllers/RegistrationBean.java new file mode 100644 index 0000000000..cf8dab5289 --- /dev/null +++ b/jsf/src/main/java/com/baeldung/springintegration/controllers/RegistrationBean.java @@ -0,0 +1,62 @@ +package com.baeldung.springintegration.controllers; + +import com.baeldung.springintegration.dao.UserManagementDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.faces.bean.ManagedBean; +import javax.faces.bean.ManagedProperty; +import javax.faces.bean.ViewScoped; +import javax.faces.context.FacesContext; +import java.io.Serializable; + +@ManagedBean(name = "registration") +@ViewScoped +public class RegistrationBean implements Serializable { + private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationBean.class); + + @ManagedProperty(value = "#{userManagementDAO}") + transient private UserManagementDAO userDao; + private String userName; + private String operationMessage; + + public void createNewUser() { + try { + LOGGER.info("Creating new user"); + FacesContext context = FacesContext.getCurrentInstance(); + boolean operationStatus = userDao.createUser(userName); + context.isValidationFailed(); + if (operationStatus) { + operationMessage = "User " + userName + " created"; + } + } catch (Exception ex) { + LOGGER.error("Error registering new user "); + ex.printStackTrace(); + operationMessage = "Error " + userName + " not created"; + } + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public void setUserDao(UserManagementDAO userDao) { + this.userDao = userDao; + } + + public UserManagementDAO getUserDao() { + return this.userDao; + } + + public String getOperationMessage() { + return operationMessage; + } + + public void setOperationMessage(String operationMessage) { + this.operationMessage = operationMessage; + } +} diff --git a/jsf/src/main/java/com/baeldung/springintegration/dao/UserManagementDAO.java b/jsf/src/main/java/com/baeldung/springintegration/dao/UserManagementDAO.java new file mode 100644 index 0000000000..2acb4e636d --- /dev/null +++ b/jsf/src/main/java/com/baeldung/springintegration/dao/UserManagementDAO.java @@ -0,0 +1,7 @@ +package com.baeldung.springintegration.dao; + +public interface UserManagementDAO { + + boolean createUser(String newUserData); + +} diff --git a/jsf/src/main/java/com/baeldung/springintegration/dao/UserManagementDAOImpl.java b/jsf/src/main/java/com/baeldung/springintegration/dao/UserManagementDAOImpl.java new file mode 100644 index 0000000000..56cbdd7b88 --- /dev/null +++ b/jsf/src/main/java/com/baeldung/springintegration/dao/UserManagementDAOImpl.java @@ -0,0 +1,38 @@ +package com.baeldung.springintegration.dao; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.List; +import javax.annotation.PostConstruct; + +@Repository +public class UserManagementDAOImpl implements UserManagementDAO { + private static final Logger LOGGER = LoggerFactory.getLogger(UserManagementDAOImpl.class); + + private List users; + + @PostConstruct + public void initUserList() { + users = new ArrayList<>(); + } + + @Override + public boolean createUser(String newUserData) { + if (newUserData != null) { + users.add(newUserData); + LOGGER.info("User {} successfully created", newUserData); + return true; + } else { + return false; + } + } + + public UserManagementDAOImpl() { + } + + +} diff --git a/jsf/src/main/resources/logback.xml b/jsf/src/main/resources/logback.xml new file mode 100644 index 0000000000..e9ae1894a6 --- /dev/null +++ b/jsf/src/main/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + \ No newline at end of file diff --git a/jsf/src/main/resources/messages.properties b/jsf/src/main/resources/messages.properties new file mode 100644 index 0000000000..41e9622630 --- /dev/null +++ b/jsf/src/main/resources/messages.properties @@ -0,0 +1,3 @@ +message.valueRequired = This value is required +message.welcome = Baeldung | Register +label.saveButton = Save diff --git a/jsf/src/main/webapp/META-INF/context.xml b/jsf/src/main/webapp/META-INF/context.xml new file mode 100644 index 0000000000..cf746bfae4 --- /dev/null +++ b/jsf/src/main/webapp/META-INF/context.xml @@ -0,0 +1,2 @@ + + diff --git a/jsf/src/main/webapp/WEB-INF/faces-config.xml b/jsf/src/main/webapp/WEB-INF/faces-config.xml new file mode 100644 index 0000000000..e9e6404b95 --- /dev/null +++ b/jsf/src/main/webapp/WEB-INF/faces-config.xml @@ -0,0 +1,39 @@ + + + + + + + + + + messages + + + msg + + + + + constraints + + + constraints + + + org.springframework.web.jsf.el.SpringBeanFacesELResolver + + + + /* + + home + /index.xhtml + + + + + diff --git a/jsf/src/main/webapp/el3_intro.xhtml b/jsf/src/main/webapp/el3_intro.xhtml new file mode 100644 index 0000000000..3f1f407a08 --- /dev/null +++ b/jsf/src/main/webapp/el3_intro.xhtml @@ -0,0 +1,35 @@ + + + + + Baeldung | Expression Language 3.0 + + + + +
    + + +
    + + +
    + + +
    + + + +
    + + + + + + + +
    + + diff --git a/jsf/src/main/webapp/el_intro.xhtml b/jsf/src/main/webapp/el_intro.xhtml new file mode 100644 index 0000000000..446647497f --- /dev/null +++ b/jsf/src/main/webapp/el_intro.xhtml @@ -0,0 +1,52 @@ + + + + + Baeldung | The EL Intro + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    KeyValue
    #{header.key}#{header.value}
    + +
    +
    + + diff --git a/jsf/src/main/webapp/index.xhtml b/jsf/src/main/webapp/index.xhtml new file mode 100644 index 0000000000..b37c864f2c --- /dev/null +++ b/jsf/src/main/webapp/index.xhtml @@ -0,0 +1,28 @@ + + + + + <h:outputText value="#{msg['message.welcome']}"/> + + + + + + + + + + + + + + + diff --git a/rest-testing/src/test/resources/.gitignore b/json-path/.gitignore similarity index 100% rename from rest-testing/src/test/resources/.gitignore rename to json-path/.gitignore diff --git a/json-path/pom.xml b/json-path/pom.xml new file mode 100644 index 0000000000..c03385cf1d --- /dev/null +++ b/json-path/pom.xml @@ -0,0 +1,65 @@ + + 4.0.0 + com.baeldung + json-path + 0.0.1-SNAPSHOT + json-path + + + + + com.jayway.jsonpath + json-path + ${json-path.version} + + + + + junit + junit + ${junit.version} + test + + + + + org.slf4j + slf4j-api + ${slf4j.version} + runtime + + + ch.qos.logback + logback-classic + ${logback.version} + runtime + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + + + + 2.1.0 + + + 4.12 + + + 1.7.14 + 1.1.3 + + \ No newline at end of file diff --git a/json-path/src/main/resources/intro_api.json b/json-path/src/main/resources/intro_api.json new file mode 100644 index 0000000000..8a252f2971 --- /dev/null +++ b/json-path/src/main/resources/intro_api.json @@ -0,0 +1,57 @@ +{ + "tool": + { + "jsonpath": + { + "creator": + { + "name": "Jayway Inc.", + "location": + [ + "Malmo", + "Stockholm", + "Copenhagen", + "San Francisco", + "Karlskrona", + "Halmstad", + "Helsingborg" + ] + }, + + "current release": "2.1" + } + }, + + "book": + [ + { + "title": "Beginning JSON", + "author": "Ben Smith", + "price": 49.99 + }, + + { + "title": "JSON at Work", + "author": "Tom Marrs", + "price": 29.99 + }, + + { + "title": "Learn JSON in a DAY", + "author": "Acodemy", + "price": 8.99 + }, + + { + "title": "JSON: Questions and Answers", + "author": "George Duckett", + "price": 6.00 + } + ], + + "price range": + { + "cheap": 10.00, + "medium": 20.00 + } +} \ No newline at end of file diff --git a/json-path/src/main/resources/intro_service.json b/json-path/src/main/resources/intro_service.json new file mode 100644 index 0000000000..448492463a --- /dev/null +++ b/json-path/src/main/resources/intro_service.json @@ -0,0 +1,61 @@ +[ + { + "id": 1, + "title": "Casino Royale", + "director": "Martin Campbell", + "starring": + [ + "Daniel Craig", + "Eva Green" + ], + + "desc": "Twenty-first James Bond movie", + "release date": 1163466000000, + "box office": 594275385 + }, + + { + "id": 2, + "title": "Quantum of Solace", + "director": "Marc Forster", + "starring": + [ + "Daniel Craig", + "Olga Kurylenko" + ], + + "desc": "Twenty-second James Bond movie", + "release date": 1225242000000, + "box office": 591692078 + }, + + { + "id": 3, + "title": "Skyfall", + "director": "Sam Mendes", + "starring": + [ + "Daniel Craig", + "Naomie Harris" + ], + + "desc": "Twenty-third James Bond movie", + "release date": 1350954000000, + "box office": 1110526981 + }, + + { + "id": 4, + "title": "Spectre", + "director": "Sam Mendes", + "starring": + [ + "Daniel Craig", + "Lea Seydoux" + ], + + "desc": "Twenty-fourth James Bond movie", + "release date": 1445821200000, + "box office": 879376275 + } +] \ No newline at end of file diff --git a/json-path/src/main/resources/intro_user.json b/json-path/src/main/resources/intro_user.json new file mode 100644 index 0000000000..c35914c6c4 --- /dev/null +++ b/json-path/src/main/resources/intro_user.json @@ -0,0 +1,46 @@ +[ + { + "username": "oracle", + "password": + { + "current": + { + "value": "Java_SE_8", + "created": 1397754000000 + }, + + "old": + [ + { + "value": "Java_SE_7", + "created": 1312650000000 + } + ] + } + }, + + { + "username": "sun", + "password": + { + "current": + { + "value": "Java_SE_6", + "created": 1168448400000 + }, + + "old": + [ + { + "value": "J2SE_5.0", + "created": 1099069200000 + }, + + { + "value": "J2SE_1.4", + "created": 1025542800000 + } + ] + } + } +] \ No newline at end of file diff --git a/json-path/src/test/java/com/baeldung/jsonpath/introduction/OperationTest.java b/json-path/src/test/java/com/baeldung/jsonpath/introduction/OperationTest.java new file mode 100644 index 0000000000..d90fafb7cb --- /dev/null +++ b/json-path/src/test/java/com/baeldung/jsonpath/introduction/OperationTest.java @@ -0,0 +1,71 @@ +package com.baeldung.jsonpath.introduction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.not; + +import org.junit.Test; + +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import java.util.Scanner; + +import com.jayway.jsonpath.Criteria; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.Filter; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.Predicate; + +public class OperationTest { + InputStream jsonInputStream = this.getClass().getClassLoader().getResourceAsStream("intro_api.json"); + String jsonDataSourceString = new Scanner(jsonInputStream, "UTF-8").useDelimiter("\\Z").next(); + + @Test + public void givenJsonPathWithoutPredicates_whenReading_thenCorrect() { + String jsonpathCreatorNamePath = "$['tool']['jsonpath']['creator']['name']"; + String jsonpathCreatorLocationPath = "$['tool']['jsonpath']['creator']['location'][*]"; + + DocumentContext jsonContext = JsonPath.parse(jsonDataSourceString); + String jsonpathCreatorName = jsonContext.read(jsonpathCreatorNamePath); + List jsonpathCreatorLocation = jsonContext.read(jsonpathCreatorLocationPath); + + assertEquals("Jayway Inc.", jsonpathCreatorName); + assertThat(jsonpathCreatorLocation.toString(), containsString("Malmo")); + assertThat(jsonpathCreatorLocation.toString(), containsString("San Francisco")); + assertThat(jsonpathCreatorLocation.toString(), containsString("Helsingborg")); + } + + @Test + public void givenJsonPathWithFilterPredicate_whenReading_thenCorrect() { + Filter expensiveFilter = Filter.filter(Criteria.where("price").gt(20.00)); + List> expensive = JsonPath.parse(jsonDataSourceString).read("$['book'][?]", expensiveFilter); + predicateUsageAssertionHelper(expensive); + } + + @Test + public void givenJsonPathWithCustomizedPredicate_whenReading_thenCorrect() { + Predicate expensivePredicate = new Predicate() { + public boolean apply(PredicateContext context) { + String value = context.item(Map.class).get("price").toString(); + return Float.valueOf(value) > 20.00; + } + }; + List> expensive = JsonPath.parse(jsonDataSourceString).read("$['book'][?]", expensivePredicate); + predicateUsageAssertionHelper(expensive); + } + + @Test + public void givenJsonPathWithInlinePredicate_whenReading_thenCorrect() { + List> expensive = JsonPath.parse(jsonDataSourceString).read("$['book'][?(@['price'] > $['price range']['medium'])]"); + predicateUsageAssertionHelper(expensive); + } + + private void predicateUsageAssertionHelper(List predicate) { + assertThat(predicate.toString(), containsString("Beginning JSON")); + assertThat(predicate.toString(), containsString("JSON at Work")); + assertThat(predicate.toString(), not(containsString("Learn JSON in a DAY"))); + assertThat(predicate.toString(), not(containsString("JSON: Questions and Answers"))); + } +} diff --git a/json-path/src/test/java/com/baeldung/jsonpath/introduction/ServiceTest.java b/json-path/src/test/java/com/baeldung/jsonpath/introduction/ServiceTest.java new file mode 100644 index 0000000000..868acac8d0 --- /dev/null +++ b/json-path/src/test/java/com/baeldung/jsonpath/introduction/ServiceTest.java @@ -0,0 +1,91 @@ +package com.baeldung.jsonpath.introduction; + +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertEquals; +import static org.hamcrest.CoreMatchers.containsString; + +import org.junit.Test; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Scanner; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.Option; + +public class ServiceTest { + InputStream jsonInputStream = this.getClass().getClassLoader().getResourceAsStream("intro_service.json"); + String jsonString = new Scanner(jsonInputStream, "UTF-8").useDelimiter("\\Z").next(); + + @Test + public void givenId_whenRequestingRecordData_thenSucceed() { + Object dataObject = JsonPath.parse(jsonString).read("$[?(@.id == 2)]"); + String dataString = dataObject.toString(); + + assertThat(dataString, containsString("2")); + assertThat(dataString, containsString("Quantum of Solace")); + assertThat(dataString, containsString("Twenty-second James Bond movie")); + } + + @Test + public void givenStarring_whenRequestingMovieTitle_thenSucceed() { + List> dataList = JsonPath.parse(jsonString).read("$[?('Eva Green' in @['starring'])]"); + String title = (String) dataList.get(0).get("title"); + + assertEquals("Casino Royale", title); + } + + @Test + public void givenCompleteStructure_whenCalculatingTotalRevenue_thenSucceed() { + DocumentContext context = JsonPath.parse(jsonString); + int length = context.read("$.length()"); + long revenue = 0; + for (int i = 0; i < length; i++) { + revenue += context.read("$[" + i + "]['box office']", Long.class); + } + + assertEquals(594275385L + 591692078L + 1110526981L + 879376275L, revenue); + } + + @Test + public void givenStructure_whenRequestingHighestRevenueMovieTitle_thenSucceed() { + DocumentContext context = JsonPath.parse(jsonString); + List revenueList = context.read("$[*]['box office']"); + Integer[] revenueArray = revenueList.toArray(new Integer[0]); + Arrays.sort(revenueArray); + + int highestRevenue = revenueArray[revenueArray.length - 1]; + Configuration pathConfiguration = Configuration.builder().options(Option.AS_PATH_LIST).build(); + List pathList = JsonPath.using(pathConfiguration).parse(jsonString).read("$[?(@['box office'] == " + highestRevenue + ")]"); + + Map dataRecord = context.read(pathList.get(0)); + String title = dataRecord.get("title"); + + assertEquals("Skyfall", title); + } + + @Test + public void givenDirector_whenRequestingLatestMovieTitle_thenSucceed() { + DocumentContext context = JsonPath.parse(jsonString); + List> dataList = context.read("$[?(@.director == 'Sam Mendes')]"); + + List dateList = new ArrayList<>(); + for (Map item : dataList) { + Object date = item.get("release date"); + dateList.add(date); + } + Long[] dateArray = dateList.toArray(new Long[0]); + Arrays.sort(dateArray); + + long latestTime = dateArray[dateArray.length - 1]; + List> finalDataList = context.read("$[?(@['director'] == 'Sam Mendes' && @['release date'] == " + latestTime + ")]"); + String title = (String) finalDataList.get(0).get("title"); + + assertEquals("Spectre", title); + } +} \ No newline at end of file diff --git a/json/README.md b/json/README.md new file mode 100644 index 0000000000..c47eca3e84 --- /dev/null +++ b/json/README.md @@ -0,0 +1,7 @@ +========= + +## Fast-Json + +### Relevant Articles: +- [Introduction to JSON Schema in Java](http://www.baeldung.com/introduction-to-json-schema-in-java) +- [A Guide to FastJson](http://www.baeldung.com/????????) diff --git a/json/pom.xml b/json/pom.xml index 47f1f25aa2..4d9efe56e4 100644 --- a/json/pom.xml +++ b/json/pom.xml @@ -13,6 +13,12 @@ 1.3.0 + + com.alibaba + fastjson + 1.2.13 + + junit junit diff --git a/json/src/test/java/org/baeldung/json/schema/JSONSchemaTest.java b/json/src/test/java/com/baeldung/json/schema/JSONSchemaTest.java similarity index 88% rename from json/src/test/java/org/baeldung/json/schema/JSONSchemaTest.java rename to json/src/test/java/com/baeldung/json/schema/JSONSchemaTest.java index 273fd48bac..bd4aaee682 100644 --- a/json/src/test/java/org/baeldung/json/schema/JSONSchemaTest.java +++ b/json/src/test/java/com/baeldung/json/schema/JSONSchemaTest.java @@ -1,31 +1,32 @@ -package org.baeldung.json.schema; - -import org.everit.json.schema.Schema; -import org.everit.json.schema.loader.SchemaLoader; - -import org.json.JSONObject; -import org.json.JSONTokener; -import org.junit.Test; - -public class JSONSchemaTest { - - @Test - public void givenInvalidInput_whenValidating_thenInvalid() { - - JSONObject jsonSchema = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/schema.json"))); - JSONObject jsonSubject = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/product_invalid.json"))); - - Schema schema = SchemaLoader.load(jsonSchema); - schema.validate(jsonSubject); - } - - @Test - public void givenValidInput_whenValidating_thenValid() { - - JSONObject jsonSchema = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/schema.json"))); - JSONObject jsonSubject = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/product_valid.json"))); - - Schema schema = SchemaLoader.load(jsonSchema); - schema.validate(jsonSubject); - } -} +package com.baeldung.json.schema; + +import org.everit.json.schema.Schema; +import org.everit.json.schema.ValidationException; +import org.everit.json.schema.loader.SchemaLoader; + +import org.json.JSONObject; +import org.json.JSONTokener; +import org.junit.Test; + +public class JSONSchemaTest { + + @Test(expected = ValidationException.class) + public void givenInvalidInput_whenValidating_thenInvalid() { + + JSONObject jsonSchema = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/schema.json"))); + JSONObject jsonSubject = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/product_invalid.json"))); + + Schema schema = SchemaLoader.load(jsonSchema); + schema.validate(jsonSubject); + } + + @Test + public void givenValidInput_whenValidating_thenValid() { + + JSONObject jsonSchema = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/schema.json"))); + JSONObject jsonSubject = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/product_valid.json"))); + + Schema schema = SchemaLoader.load(jsonSchema); + schema.validate(jsonSubject); + } +} diff --git a/json/src/test/java/fast_json/FastJsonTests.java b/json/src/test/java/fast_json/FastJsonTests.java new file mode 100644 index 0000000000..7b7e3c0434 --- /dev/null +++ b/json/src/test/java/fast_json/FastJsonTests.java @@ -0,0 +1,104 @@ +package fast_json; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.serializer.BeanContext; +import com.alibaba.fastjson.serializer.ContextValueFilter; +import com.alibaba.fastjson.serializer.NameFilter; +import com.alibaba.fastjson.serializer.SerializeConfig; +import org.junit.Before; +import org.junit.Test; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class FastJsonTests { + private List listOfPersons; + + @Before + public void setUp() { + listOfPersons = new ArrayList(); + Calendar calendar = Calendar.getInstance(); + calendar.set(2016, 6, 24); + listOfPersons.add(new Person(15, "John", "Doe", calendar.getTime())); + listOfPersons.add(new Person(20, "Janette", "Doe", calendar.getTime())); + } + + @Test + public void whenJavaList_thanConvertToJsonCorrect() { + String personJsonFormat = JSON.toJSONString(listOfPersons); + assertEquals( + personJsonFormat, + "[{\"FIRST NAME\":\"Doe\",\"LAST NAME\":\"John\",\"DATE OF BIRTH\":" + + "\"24/07/2016\"},{\"FIRST NAME\":\"Doe\",\"LAST NAME\":\"Janette\",\"DATE OF BIRTH\":" + + "\"24/07/2016\"}]"); + } + + @Test + public void whenJson_thanConvertToObjectCorrect() { + String personJsonFormat = JSON.toJSONString(listOfPersons.get(0)); + Person newPerson = JSON.parseObject(personJsonFormat, Person.class); + assertEquals(newPerson.getAge(), 0); // serialize is set to false for age attribute + assertEquals(newPerson.getFirstName(), listOfPersons.get(0).getFirstName()); + assertEquals(newPerson.getLastName(), listOfPersons.get(0).getLastName()); + } + + @Test + public void whenGenerateJson_thanGenerationCorrect() throws ParseException { + JSONArray jsonArray = new JSONArray(); + for (int i = 0; i < 2; i++) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("FIRST NAME", "John" + i); + jsonObject.put("LAST NAME", "Doe" + i); + jsonObject.put("DATE OF BIRTH", "2016/12/12 12:12:12"); + jsonArray.add(jsonObject); + } + assertEquals( + jsonArray.toString(), + "[{\"LAST NAME\":\"Doe0\",\"DATE OF BIRTH\":" + + "\"2016/12/12 12:12:12\",\"FIRST NAME\":\"John0\"},{\"LAST NAME\":\"Doe1\"," + + "\"DATE OF BIRTH\":\"2016/12/12 12:12:12\",\"FIRST NAME\":\"John1\"}]"); + } + + @Test + public void givenContextFilter_whenJavaObject_thanJsonCorrect() { + ContextValueFilter valueFilter = new ContextValueFilter() { + public Object process(BeanContext context, Object object, + String name, Object value) { + if (name.equals("DATE OF BIRTH")) { + return "NOT TO DISCLOSE"; + } + if (value.equals("John") || value.equals("Doe")) { + return ((String) value).toUpperCase(); + } else { + return null; + } + } + }; + JSON.toJSONString(listOfPersons, valueFilter); + } + + @Test + public void givenSerializeConfig_whenJavaObject_thanJsonCorrect() { + NameFilter formatName = new NameFilter() { + public String process(Object object, String name, Object value) { + return name.toLowerCase().replace(" ", "_"); + } + }; + SerializeConfig.getGlobalInstance().addFilter(Person.class, formatName); + String jsonOutput = JSON.toJSONStringWithDateFormat(listOfPersons, + "yyyy-MM-dd"); + assertEquals( + jsonOutput, + "[{\"first_name\":\"Doe\",\"last_name\":\"John\"," + + "\"date_of_birth\":\"2016-07-24\"},{\"first_name\":\"Doe\",\"last_name\":" + + "\"Janette\",\"date_of_birth\":\"2016-07-24\"}]"); + // resetting custom serializer + SerializeConfig.getGlobalInstance().put(Person.class, null); + } +} diff --git a/json/src/test/java/fast_json/Person.java b/json/src/test/java/fast_json/Person.java new file mode 100644 index 0000000000..0eac58cdfd --- /dev/null +++ b/json/src/test/java/fast_json/Person.java @@ -0,0 +1,70 @@ +package fast_json; + +import com.alibaba.fastjson.annotation.JSONField; + +import java.util.Date; + +public class Person { + + @JSONField(name = "AGE", serialize = false, deserialize = false) + private int age; + + @JSONField(name = "LAST NAME", ordinal = 2) + private String lastName; + + @JSONField(name = "FIRST NAME", ordinal = 1) + private String firstName; + + @JSONField(name = "DATE OF BIRTH", format = "dd/MM/yyyy", ordinal = 3) + private Date dateOfBirth; + + public Person() { + + } + + public Person(int age, String lastName, String firstName, Date dateOfBirth) { + super(); + this.age = age; + this.lastName = lastName; + this.firstName = firstName; + this.dateOfBirth = dateOfBirth; + } + + @Override + public String toString() { + return "Person [age=" + age + ", lastName=" + lastName + ", firstName=" + + firstName + ", dateOfBirth=" + dateOfBirth + "]"; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public Date getDateOfBirth() { + return dateOfBirth; + } + + public void setDateOfBirth(Date dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } +} diff --git a/junit5/pom.xml b/junit5/pom.xml new file mode 100644 index 0000000000..5a2ea61668 --- /dev/null +++ b/junit5/pom.xml @@ -0,0 +1,83 @@ + + + 4.0.0 + + com.baeldung + junit5 + 1.0-SNAPSHOT + + junit5 + Intro to JUnit 5 + + + UTF-8 + 1.8 + + 5.0.0-SNAPSHOT + + + + + snapshots-repo + https://oss.sonatype.org/content/repositories/snapshots + + false + + + + always + true + + + + + + + snapshots-repo + https://oss.sonatype.org/content/repositories/snapshots + + false + + + + always + true + + + + + + + + maven-compiler-plugin + 3.1 + + ${java.version} + ${java.version} + + + + maven-surefire-plugin + 2.19 + + + org.junit + surefire-junit5 + ${junit.gen5.version} + + + + + + + + + org.junit + junit5-api + ${junit.gen5.version} + test + + + \ No newline at end of file diff --git a/junit5/src/test/java/com/baeldung/AssumptionTest.java b/junit5/src/test/java/com/baeldung/AssumptionTest.java new file mode 100644 index 0000000000..e4c2b56124 --- /dev/null +++ b/junit5/src/test/java/com/baeldung/AssumptionTest.java @@ -0,0 +1,30 @@ +package com.baeldung; + +import org.junit.gen5.api.Test; + +import static org.junit.gen5.api.Assertions.assertEquals; +import static org.junit.gen5.api.Assumptions.*; + +public class AssumptionTest { + + @Test + void trueAssumption() { + assumeTrue(5 > 1); + assertEquals(5 + 2, 7); + } + + @Test + void falseAssumption() { + assumeFalse(5 < 1); + assertEquals(5 + 2, 7); + } + + @Test + void assumptionThat() { + String someString = "Just a string"; + assumingThat( + someString.equals("Just a string"), + () -> assertEquals(2 + 2, 4) + ); + } +} diff --git a/junit5/src/test/java/com/baeldung/ExceptionTest.java b/junit5/src/test/java/com/baeldung/ExceptionTest.java new file mode 100644 index 0000000000..5c30ad5b44 --- /dev/null +++ b/junit5/src/test/java/com/baeldung/ExceptionTest.java @@ -0,0 +1,18 @@ +package com.baeldung; + +import org.junit.gen5.api.Test; + +import static org.junit.gen5.api.Assertions.assertEquals; +import static org.junit.gen5.api.Assertions.expectThrows; + +public class ExceptionTest { + + @Test + void shouldThrowException() { + Throwable exception = expectThrows(UnsupportedOperationException.class, + () -> { + throw new UnsupportedOperationException("Not supported"); + }); + assertEquals(exception.getMessage(), "Not supported"); + } +} diff --git a/junit5/src/test/java/com/baeldung/FirstTest.java b/junit5/src/test/java/com/baeldung/FirstTest.java new file mode 100644 index 0000000000..4fc6037174 --- /dev/null +++ b/junit5/src/test/java/com/baeldung/FirstTest.java @@ -0,0 +1,37 @@ +package com.baeldung; + +import org.junit.gen5.api.Disabled; +import org.junit.gen5.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.gen5.api.Assertions.*; + +class FirstTest { + + @Test + void lambdaExpressions() { + List numbers = Arrays.asList(1, 2, 3); + assertTrue(numbers + .stream() + .mapToInt(i -> i) + .sum() > 5, "Sum should be greater than 5"); + } + + @Test + void groupAssertions() { + int[] numbers = {0, 1, 2, 3, 4}; + assertAll("numbers", + () -> assertEquals(numbers[0], 1), + () -> assertEquals(numbers[3], 3), + () -> assertEquals(numbers[4], 1) + ); + } + + @Test + @Disabled + void disabledTest() { + assertTrue(false); + } +} diff --git a/junit5/src/test/java/com/baeldung/NestedTest.java b/junit5/src/test/java/com/baeldung/NestedTest.java new file mode 100644 index 0000000000..3fbe4f8644 --- /dev/null +++ b/junit5/src/test/java/com/baeldung/NestedTest.java @@ -0,0 +1,77 @@ +package com.baeldung; + +import org.junit.gen5.api.*; + +import java.util.EmptyStackException; +import java.util.Stack; + +public class NestedTest { + Stack stack; + boolean isRun = false; + + @Test + @DisplayName("is instantiated with new Stack()") + void isInstantiatedWithNew() { + new Stack(); + } + + @Nested + @DisplayName("when new") + class WhenNew { + + @BeforeEach + void init() { + stack = new Stack(); + } + + @Test + @DisplayName("is empty") + void isEmpty() { + Assertions.assertTrue(stack.isEmpty()); + } + + @Test + @DisplayName("throws EmptyStackException when popped") + void throwsExceptionWhenPopped() { + Assertions.expectThrows(EmptyStackException.class, () -> stack.pop()); + } + + @Test + @DisplayName("throws EmptyStackException when peeked") + void throwsExceptionWhenPeeked() { + Assertions.expectThrows(EmptyStackException.class, () -> stack.peek()); + } + + @Nested + @DisplayName("after pushing an element") + class AfterPushing { + + String anElement = "an element"; + + @BeforeEach + void init() { + stack.push(anElement); + } + + @Test + @DisplayName("it is no longer empty") + void isEmpty() { + Assertions.assertFalse(stack.isEmpty()); + } + + @Test + @DisplayName("returns the element when popped and is empty") + void returnElementWhenPopped() { + Assertions.assertEquals(anElement, stack.pop()); + Assertions.assertTrue(stack.isEmpty()); + } + + @Test + @DisplayName("returns the element when peeked but remains not empty") + void returnElementWhenPeeked() { + Assertions.assertEquals(anElement, stack.peek()); + Assertions.assertFalse(stack.isEmpty()); + } + } + } +} diff --git a/junit5/src/test/java/com/baeldung/TaggedTest.java b/junit5/src/test/java/com/baeldung/TaggedTest.java new file mode 100644 index 0000000000..dbc82f4022 --- /dev/null +++ b/junit5/src/test/java/com/baeldung/TaggedTest.java @@ -0,0 +1,16 @@ +package com.baeldung; + +import org.junit.gen5.api.Tag; +import org.junit.gen5.api.Test; + +import static org.junit.gen5.api.Assertions.assertEquals; + +@Tag("Test case") +public class TaggedTest { + + @Test + @Tag("Method") + void testMethod() { + assertEquals(2 + 2, 4); + } +} diff --git a/log4j/pom.xml b/log4j/pom.xml new file mode 100644 index 0000000000..1081513dcf --- /dev/null +++ b/log4j/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + com.baeldung + log4j + 1.0-SNAPSHOT + + + + + log4j + log4j + 1.2.17 + + + + + org.apache.logging.log4j + log4j-api + 2.6 + + + org.apache.logging.log4j + log4j-core + 2.6 + + + + com.lmax + disruptor + 3.3.4 + + + + + ch.qos.logback + logback-classic + 1.1.7 + + + + + + maven-compiler-plugin + 3.3 + + true + true + 1.8 + 1.8 + UTF-8 + true + true + + + + + + \ No newline at end of file diff --git a/log4j/src/main/java/com/baeldung/log4j/Log4jExample.java b/log4j/src/main/java/com/baeldung/log4j/Log4jExample.java new file mode 100644 index 0000000000..e53fdd4881 --- /dev/null +++ b/log4j/src/main/java/com/baeldung/log4j/Log4jExample.java @@ -0,0 +1,17 @@ +package com.baeldung.log4j; + + +import org.apache.log4j.Logger; + +public class Log4jExample { + + private final static Logger logger = Logger.getLogger(Log4jExample.class); + + public static void main(String[] args) { + logger.trace("Trace log message"); + logger.debug("Debug log message"); + logger.info("Info log message"); + logger.error("Error log message"); + } + +} diff --git a/log4j/src/main/java/com/baeldung/log4j2/Log4j2Example.java b/log4j/src/main/java/com/baeldung/log4j2/Log4j2Example.java new file mode 100644 index 0000000000..60acc3a774 --- /dev/null +++ b/log4j/src/main/java/com/baeldung/log4j2/Log4j2Example.java @@ -0,0 +1,16 @@ +package com.baeldung.log4j2; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +public class Log4j2Example { + + private static final Logger logger = LogManager.getLogger(Log4j2Example.class); + + public static void main(String[] args) { + logger.debug("Debug log message"); + logger.info("Info log message"); + logger.error("Error log message"); + } + +} diff --git a/log4j/src/main/java/com/baeldung/logback/LogbackExample.java b/log4j/src/main/java/com/baeldung/logback/LogbackExample.java new file mode 100644 index 0000000000..536aa78ec9 --- /dev/null +++ b/log4j/src/main/java/com/baeldung/logback/LogbackExample.java @@ -0,0 +1,16 @@ +package com.baeldung.logback; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LogbackExample { + + private static final Logger logger = LoggerFactory.getLogger(LogbackExample.class); + + public static void main(String[] args) { + logger.debug("Debug log message"); + logger.info("Info log message"); + logger.error("Error log message"); + } + +} diff --git a/log4j/src/main/java/com/baeldung/slf4j/Slf4jExample.java b/log4j/src/main/java/com/baeldung/slf4j/Slf4jExample.java new file mode 100644 index 0000000000..6ecc7b887a --- /dev/null +++ b/log4j/src/main/java/com/baeldung/slf4j/Slf4jExample.java @@ -0,0 +1,20 @@ +package com.baeldung.slf4j; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * To switch between logging frameworks you need only to uncomment needed framework dependencies in pom.xml + */ +public class Slf4jExample { + private static Logger logger = LoggerFactory.getLogger(Slf4jExample.class); + + public static void main(String[] args) { + logger.debug("Debug log message"); + logger.info("Info log message"); + logger.error("Error log message"); + + String variable = "Hello John"; + logger.debug("Printing variable value {} ", variable); + } +} diff --git a/log4j/src/main/resources/log4j.xml b/log4j/src/main/resources/log4j.xml new file mode 100644 index 0000000000..58a924f970 --- /dev/null +++ b/log4j/src/main/resources/log4j.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/log4j/src/main/resources/log4j2.xml b/log4j/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..76a20bcd61 --- /dev/null +++ b/log4j/src/main/resources/log4j2.xml @@ -0,0 +1,26 @@ + + + + # Console appender + + # Pattern of log message for console appender + + + + # File appender + + # Pattern of log message for file appender + + + + + + # Override log level for specified package + + + + + + + + \ No newline at end of file diff --git a/log4j/src/main/resources/logback.xml b/log4j/src/main/resources/logback.xml new file mode 100644 index 0000000000..fc66d560aa --- /dev/null +++ b/log4j/src/main/resources/logback.xml @@ -0,0 +1,28 @@ + + # Console appender + + + # Pattern of log message for console appender + %d{yyyy-MM-dd HH:mm:ss} %p %m%n + + + + # File appender + + # Name of a log file + log4j/target/baeldung-logback.log + false + + # Pattern of log message for file appender + %d{yyyy-MM-dd HH:mm:ss} %p %m%n + + + + # Override log level for specified package + + + + + + + \ No newline at end of file diff --git a/lombok/pom.xml b/lombok/pom.xml new file mode 100644 index 0000000000..b816642165 --- /dev/null +++ b/lombok/pom.xml @@ -0,0 +1,151 @@ + + + + 4.0.0 + + lombok + + com.baeldung + lombok + 0.1-SNAPSHOT + + + + + org.projectlombok + lombok + + ${lombok.version} + provided + + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + ${hibernate-jpa-2.1-api.version} + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + + ch.qos.logback + logback-core + ${logback.version} + runtime + + + + + + junit + junit + ${junit.version} + test + + + + + + + lombok + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + org.projectlombok + lombok-maven-plugin + ${delombok-maven-plugin.version} + + + delombok + generate-sources + + delombok + + + ${project.basedir}/src/main/java + false + + skip + + false + + + + + + + + + + + + UTF-8 + + 1.8 + 1.8 + + + 1.16.8 + + + 1.0.0.Final + + + 1.7.13 + 1.1.3 + + + 4.12 + + + 3.5.1 + 2.19.1 + + + ${lombok.version}.0 + + + diff --git a/lombok/src/main/java/com/baeldung/lombok/intro/ApiClientConfiguration.java b/lombok/src/main/java/com/baeldung/lombok/intro/ApiClientConfiguration.java new file mode 100644 index 0000000000..74cc929d32 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/intro/ApiClientConfiguration.java @@ -0,0 +1,22 @@ +package com.baeldung.lombok.intro; + +import lombok.Builder; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Builder +@Slf4j +@Getter +public class ApiClientConfiguration { + + private String host; + private int port; + private boolean useHttps; + + private long connectTimeout; + private long readTimeout; + + private String username; + private String password; + +} diff --git a/lombok/src/main/java/com/baeldung/lombok/intro/ContactInformationSupport.java b/lombok/src/main/java/com/baeldung/lombok/intro/ContactInformationSupport.java new file mode 100644 index 0000000000..ea9c3d23f5 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/intro/ContactInformationSupport.java @@ -0,0 +1,17 @@ +package com.baeldung.lombok.intro; + +import lombok.Data; + +@Data +public class ContactInformationSupport implements HasContactInformation { + + private String firstName; + private String lastName; + private String phoneNr; + + @Override + public String getFullName() { + return getFirstName() + " " + getLastName(); + } + +} diff --git a/lombok/src/main/java/com/baeldung/lombok/intro/HasContactInformation.java b/lombok/src/main/java/com/baeldung/lombok/intro/HasContactInformation.java new file mode 100644 index 0000000000..9128df5fb0 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/intro/HasContactInformation.java @@ -0,0 +1,16 @@ +package com.baeldung.lombok.intro; + +public interface HasContactInformation { + + String getFirstName(); + void setFirstName(String firstName); + + String getFullName(); + + String getLastName(); + void setLastName(String lastName); + + String getPhoneNr(); + void setPhoneNr(String phoneNr); + +} diff --git a/lombok/src/main/java/com/baeldung/lombok/intro/LoginResult.java b/lombok/src/main/java/com/baeldung/lombok/intro/LoginResult.java new file mode 100644 index 0000000000..6e75696612 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/intro/LoginResult.java @@ -0,0 +1,25 @@ +package com.baeldung.lombok.intro; + +import java.net.URL; +import java.time.Duration; +import java.time.Instant; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; + +@RequiredArgsConstructor +@Accessors(fluent = true) @Getter +@EqualsAndHashCode(of = {"authToken"}) +public class LoginResult { + + private final @NonNull Instant loginTs; + + private final @NonNull String authToken; + private final @NonNull Duration tokenValidity; + + private final @NonNull URL tokenRefreshUrl; + +} diff --git a/lombok/src/main/java/com/baeldung/lombok/intro/User.java b/lombok/src/main/java/com/baeldung/lombok/intro/User.java new file mode 100644 index 0000000000..d032d1f9e7 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/intro/User.java @@ -0,0 +1,43 @@ +package com.baeldung.lombok.intro; + +import java.io.Serializable; +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.Delegate; + +@Entity +@Getter @Setter @NoArgsConstructor // <--- THIS is it +@ToString(exclude = {"events"}) +public class User implements Serializable, HasContactInformation { + + private @Id @Setter(AccessLevel.PROTECTED) Long id; // will be set when persisting + + private String nickname; + + // Whichever other User-specific attributes + + @Delegate(types = {HasContactInformation.class}) + private final ContactInformationSupport contactInformation = new ContactInformationSupport(); + + // User itelf will implement all contact information by delegation + + @OneToMany(mappedBy = "user") + private List events; + + public User(String nickname, String firstName, String lastName, String phoneNr) { + this.nickname = nickname; + contactInformation.setFirstName(firstName); + contactInformation.setLastName(lastName); + contactInformation.setPhoneNr(phoneNr); + } + +} diff --git a/lombok/src/main/java/com/baeldung/lombok/intro/UserEvent.java b/lombok/src/main/java/com/baeldung/lombok/intro/UserEvent.java new file mode 100644 index 0000000000..6a13608664 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/intro/UserEvent.java @@ -0,0 +1,29 @@ +package com.baeldung.lombok.intro; + +import java.io.Serializable; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@NoArgsConstructor @Getter @Setter +public class UserEvent implements Serializable { + + // This class is just for sample purposes. + + private @Id @Setter(AccessLevel.PROTECTED) Long id; + + @ManyToOne + private User user; + + public UserEvent(User user) { + this.user = user; + } + +} diff --git a/lombok/src/test/java/com/baeldung/lombok/intro/ApiClientConfigurationTest.java b/lombok/src/test/java/com/baeldung/lombok/intro/ApiClientConfigurationTest.java new file mode 100644 index 0000000000..8283fc655e --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/intro/ApiClientConfigurationTest.java @@ -0,0 +1,43 @@ +package com.baeldung.lombok.intro; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import com.baeldung.lombok.intro.ApiClientConfiguration.ApiClientConfigurationBuilder; +import org.junit.Assert; +import org.junit.Test; + +public class ApiClientConfigurationTest { + + @Test + public void givenAnnotatedConfiguration_thenCanBeBuiltViaBuilder() { + ApiClientConfiguration config = + new ApiClientConfigurationBuilder() + .host("api.server.com") + .port(443) + .useHttps(true) + .connectTimeout(15_000L) + .readTimeout(5_000L) + .username("myusername") + .password("secret") + .build(); + + Assert.assertEquals(config.getHost(), "api.server.com"); + Assert.assertEquals(config.getPort(), 443); + Assert.assertEquals(config.isUseHttps(), true); + Assert.assertEquals(config.getConnectTimeout(), 15_000L); + Assert.assertEquals(config.getReadTimeout(), 5_000L); + Assert.assertEquals(config.getUsername(), "myusername"); + Assert.assertEquals(config.getPassword(), "secret"); + } + + @Test + public void givenAnnotatedConfiguration_thenHasLoggerInstance() throws NoSuchFieldException { + Field loggerInstance = ApiClientConfiguration.class.getDeclaredField("log"); + int modifiers = loggerInstance.getModifiers(); + Assert.assertTrue(Modifier.isPrivate(modifiers)); + Assert.assertTrue(Modifier.isStatic(modifiers)); + Assert.assertTrue(Modifier.isFinal(modifiers)); + } + +} diff --git a/lombok/src/test/java/com/baeldung/lombok/intro/LoginResultTest.java b/lombok/src/test/java/com/baeldung/lombok/intro/LoginResultTest.java new file mode 100644 index 0000000000..56878e4a03 --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/intro/LoginResultTest.java @@ -0,0 +1,59 @@ +package com.baeldung.lombok.intro; + +import java.net.MalformedURLException; +import java.net.URL; +import java.time.Duration; +import java.time.Instant; + +import org.junit.Assert; +import org.junit.Test; + +public class LoginResultTest { + + @Test + public void givenAnnotatedLoginResult_thenHasConstructorForAllFinalFields() + throws MalformedURLException { + /* LoginResult loginResult = */ new LoginResult( + Instant.now(), + "apitoken", + Duration.ofHours(1), + new URL("https://api.product.com/token-refresh")); + } + + @Test + public void givenAnnotatedLoginResult_thenHasFluentGetters() + throws MalformedURLException { + Instant loginTs = Instant.now(); + LoginResult loginResult = new LoginResult( + loginTs, + "apitoken", + Duration.ofHours(1), + new URL("https://api.product.com/token-refresh")); + + Assert.assertEquals(loginResult.loginTs(), loginTs); + Assert.assertEquals(loginResult.authToken(), "apitoken"); + Assert.assertEquals(loginResult.tokenValidity(), Duration.ofHours(1)); + Assert.assertEquals(loginResult.tokenRefreshUrl(), new URL("https://api.product.com/token-refresh")); + } + + @Test + public void givenAnnotatedLoginResult_whenSameApiToken_thenEqualInstances() + throws MalformedURLException { + String theSameApiToken = "testapitoken"; + + LoginResult loginResult1 = new LoginResult( + Instant.now(), + theSameApiToken, + Duration.ofHours(1), + new URL("https://api.product.com/token-refresh")); + + LoginResult loginResult2 = new LoginResult( + Instant.now(), + theSameApiToken, + Duration.ofHours(2), + new URL("https://api.product.com/token-refresh-alt")); + + Assert.assertEquals(loginResult1, loginResult2); + } + +} diff --git a/lombok/src/test/java/com/baeldung/lombok/intro/UserTest.java b/lombok/src/test/java/com/baeldung/lombok/intro/UserTest.java new file mode 100644 index 0000000000..b3bf21478f --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/intro/UserTest.java @@ -0,0 +1,73 @@ +package com.baeldung.lombok.intro; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +public class UserTest { + + @Test + public void givenAnnotatedUser_thenHasEmptyConstructor() { + /* User user = */ new User(); + } + + @Test + public void givenAnnotatedUser_thenHasGettersAndSetters() { + User user = new User("testnickname", "Test", "JUnit", "123456"); + + Assert.assertEquals("testnickname", user.getNickname()); + Assert.assertEquals("Test", user.getFirstName()); + Assert.assertEquals("JUnit", user.getLastName()); + Assert.assertEquals("123456", user.getPhoneNr()); + + user.setNickname("testnickname2"); + user.setFirstName("Test2"); + user.setLastName("JUnit2"); + user.setPhoneNr("654321"); + + Assert.assertEquals("testnickname2", user.getNickname()); + Assert.assertEquals("Test2", user.getFirstName()); + Assert.assertEquals("JUnit2", user.getLastName()); + Assert.assertEquals("654321", user.getPhoneNr()); + } + + @Test + public void givenAnnotatedUser_thenHasProtectedSetId() throws NoSuchMethodException { + Method setIdMethod = User.class.getDeclaredMethod("setId", Long.class); + int modifiers = setIdMethod.getModifiers(); + Assert.assertTrue(Modifier.isProtected(modifiers)); + } + + @Test + public void givenAnnotatedUser_thenImplementsHasContactInformation() { + User user = new User("testnickname3", "Test3", "JUnit3", "987654"); + Assert.assertTrue(user instanceof HasContactInformation); + + Assert.assertEquals("Test3", user.getFirstName()); + Assert.assertEquals("JUnit3", user.getLastName()); + Assert.assertEquals("987654", user.getPhoneNr()); + Assert.assertEquals("Test3 JUnit3", user.getFullName()); + + user.setFirstName("Test4"); + user.setLastName("JUnit4"); + user.setPhoneNr("456789"); + + Assert.assertEquals("Test4", user.getFirstName()); + Assert.assertEquals("JUnit4", user.getLastName()); + Assert.assertEquals("456789", user.getPhoneNr()); + Assert.assertEquals("Test4 JUnit4", user.getFullName()); + } + + @Test + public void givenAnnotatedUser_whenHasEvents_thenToStringDumpsNoEvents() { + User user = new User("testnickname", "Test", "JUnit", "123456"); + List events = Arrays.asList(new UserEvent(user), new UserEvent(user)); + user.setEvents(events); + Assert.assertFalse(user.toString().contains("events")); + } + +} diff --git a/mapstruct/pom.xml b/mapstruct/pom.xml new file mode 100644 index 0000000000..4159ef35c9 --- /dev/null +++ b/mapstruct/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + mapstruct + mapstruct + com.baeldung + 1.0 + jar + + + 1.0.0.Final + + + + org.mapstruct + mapstruct-jdk8 + ${org.mapstruct.version} + + + junit + junit + 4.12 + test + + + org.springframework + spring-context + 4.3.2.RELEASE + + + org.springframework + spring-test + 4.3.2.RELEASE + test + + + + mapstruct + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + org.mapstruct + mapstruct-processor + ${org.mapstruct.version} + + + + + + + diff --git a/mapstruct/src/main/java/com/baeldung/dto/DivisionDTO.java b/mapstruct/src/main/java/com/baeldung/dto/DivisionDTO.java new file mode 100644 index 0000000000..37f8bd111b --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/dto/DivisionDTO.java @@ -0,0 +1,33 @@ +package com.baeldung.dto; + +public class DivisionDTO { + + public DivisionDTO() { + } + + public DivisionDTO(int id, String name) { + super(); + this.id = id; + this.name = name; + } + + private int id; + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/mapstruct/src/main/java/com/baeldung/dto/EmployeeDTO.java b/mapstruct/src/main/java/com/baeldung/dto/EmployeeDTO.java new file mode 100644 index 0000000000..5da3165683 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/dto/EmployeeDTO.java @@ -0,0 +1,42 @@ +package com.baeldung.dto; + +public class EmployeeDTO { + + private int employeeId; + private String employeeName; + private DivisionDTO division; + private String employeeStartDt; + + public int getEmployeeId() { + return employeeId; + } + + public void setEmployeeId(int employeeId) { + this.employeeId = employeeId; + } + + public String getEmployeeName() { + return employeeName; + } + + public void setEmployeeName(String employeeName) { + this.employeeName = employeeName; + } + + public DivisionDTO getDivision() { + return division; + } + + public void setDivision(DivisionDTO division) { + this.division = division; + } + + public String getEmployeeStartDt() { + return employeeStartDt; + } + + public void setEmployeeStartDt(String employeeStartDt) { + this.employeeStartDt = employeeStartDt; + } + +} diff --git a/mapstruct/src/main/java/com/baeldung/dto/SimpleSource.java b/mapstruct/src/main/java/com/baeldung/dto/SimpleSource.java new file mode 100644 index 0000000000..ec8d80c4af --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/dto/SimpleSource.java @@ -0,0 +1,24 @@ +package com.baeldung.dto; + +public class SimpleSource { + + private String name; + private String description; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/mapstruct/src/main/java/com/baeldung/entity/Division.java b/mapstruct/src/main/java/com/baeldung/entity/Division.java new file mode 100644 index 0000000000..7b1416d6c5 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/entity/Division.java @@ -0,0 +1,33 @@ +package com.baeldung.entity; + +public class Division { + + public Division() { + } + + public Division(int id, String name) { + super(); + this.id = id; + this.name = name; + } + + private int id; + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/mapstruct/src/main/java/com/baeldung/entity/Employee.java b/mapstruct/src/main/java/com/baeldung/entity/Employee.java new file mode 100644 index 0000000000..04044f4dfe --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/entity/Employee.java @@ -0,0 +1,44 @@ +package com.baeldung.entity; + +import java.util.Date; + +public class Employee { + + private int id; + private String name; + private Division division; + private Date startDt; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Division getDivision() { + return division; + } + + public void setDivision(Division division) { + this.division = division; + } + + public Date getStartDt() { + return startDt; + } + + public void setStartDt(Date startDt) { + this.startDt = startDt; + } + +} diff --git a/mapstruct/src/main/java/com/baeldung/entity/SimpleDestination.java b/mapstruct/src/main/java/com/baeldung/entity/SimpleDestination.java new file mode 100644 index 0000000000..d9cba1c372 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/entity/SimpleDestination.java @@ -0,0 +1,24 @@ +package com.baeldung.entity; + +public class SimpleDestination { + + private String name; + private String description; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/mapstruct/src/main/java/com/baeldung/mapper/EmployeeMapper.java b/mapstruct/src/main/java/com/baeldung/mapper/EmployeeMapper.java new file mode 100644 index 0000000000..8e00103d0e --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapper/EmployeeMapper.java @@ -0,0 +1,30 @@ +package com.baeldung.mapper; + +import com.baeldung.dto.DivisionDTO; +import com.baeldung.dto.EmployeeDTO; +import com.baeldung.entity.Division; +import com.baeldung.entity.Employee; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; + +import java.util.List; + +@Mapper +public interface EmployeeMapper { + + @Mappings({ @Mapping(target = "employeeId", source = "entity.id"), @Mapping(target = "employeeName", source = "entity.name"), @Mapping(target = "employeeStartDt", source = "entity.startDt", dateFormat = "dd-MM-yyyy HH:mm:ss") }) + EmployeeDTO employeeToEmployeeDTO(Employee entity); + + @Mappings({ @Mapping(target = "id", source = "dto.employeeId"), @Mapping(target = "name", source = "dto.employeeName"), @Mapping(target = "startDt", source = "dto.employeeStartDt", dateFormat = "dd-MM-yyyy HH:mm:ss") }) + Employee employeeDTOtoEmployee(EmployeeDTO dto); + + DivisionDTO divisionToDivisionDTO(Division entity); + + Division divisionDTOtoDivision(DivisionDTO dto); + + List convertEmployeeDTOListToEmployeeList(List list); + + List convertEmployeeListToEmployeeDTOList(List list); + +} diff --git a/mapstruct/src/main/java/com/baeldung/mapper/SimpleSourceDestinationMapper.java b/mapstruct/src/main/java/com/baeldung/mapper/SimpleSourceDestinationMapper.java new file mode 100644 index 0000000000..f3f2187c20 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapper/SimpleSourceDestinationMapper.java @@ -0,0 +1,14 @@ +package com.baeldung.mapper; + +import com.baeldung.dto.SimpleSource; +import com.baeldung.entity.SimpleDestination; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface SimpleSourceDestinationMapper { + + SimpleDestination sourceToDestination(SimpleSource source); + + SimpleSource destinationToSource(SimpleDestination destination); + +} diff --git a/mapstruct/src/main/resources/applicationContext.xml b/mapstruct/src/main/resources/applicationContext.xml new file mode 100644 index 0000000000..22d8d1b769 --- /dev/null +++ b/mapstruct/src/main/resources/applicationContext.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/mapstruct/src/test/java/com/baeldung/mapper/EmployeeMapperTest.java b/mapstruct/src/test/java/com/baeldung/mapper/EmployeeMapperTest.java new file mode 100644 index 0000000000..7da6c41dc1 --- /dev/null +++ b/mapstruct/src/test/java/com/baeldung/mapper/EmployeeMapperTest.java @@ -0,0 +1,123 @@ +package com.baeldung.mapper; + +import com.baeldung.dto.DivisionDTO; +import com.baeldung.dto.EmployeeDTO; +import com.baeldung.entity.Division; +import com.baeldung.entity.Employee; +import org.junit.Test; +import org.mapstruct.factory.Mappers; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class EmployeeMapperTest { + + EmployeeMapper mapper = Mappers.getMapper(EmployeeMapper.class); + + private static final String DATE_FORMAT = "dd-MM-yyyy HH:mm:ss"; + + @Test + public void givenEmployeeDTOwithDiffNametoEmployee_whenMaps_thenCorrect() { + EmployeeDTO dto = new EmployeeDTO(); + dto.setEmployeeId(1); + dto.setEmployeeName("John"); + + Employee entity = mapper.employeeDTOtoEmployee(dto); + + assertEquals(dto.getEmployeeId(), entity.getId()); + assertEquals(dto.getEmployeeName(), entity.getName()); + } + + @Test + public void givenEmployeewithDiffNametoEmployeeDTO_whenMaps_thenCorrect() { + Employee entity = new Employee(); + entity.setId(1); + entity.setName("John"); + + EmployeeDTO dto = mapper.employeeToEmployeeDTO(entity); + + assertEquals(dto.getEmployeeId(), entity.getId()); + assertEquals(dto.getEmployeeName(), entity.getName()); + } + + @Test + public void givenEmployeeDTOwithNestedMappingToEmployee_whenMaps_thenCorrect() { + EmployeeDTO dto = new EmployeeDTO(); + dto.setDivision(new DivisionDTO(1, "Division1")); + + Employee entity = mapper.employeeDTOtoEmployee(dto); + + assertEquals(dto.getDivision().getId(), entity.getDivision().getId()); + assertEquals(dto.getDivision().getName(), entity.getDivision().getName()); + } + + @Test + public void givenEmployeeWithNestedMappingToEmployeeDTO_whenMaps_thenCorrect() { + Employee entity = new Employee(); + entity.setDivision(new Division(1, "Division1")); + + EmployeeDTO dto = mapper.employeeToEmployeeDTO(entity); + + assertEquals(dto.getDivision().getId(), entity.getDivision().getId()); + assertEquals(dto.getDivision().getName(), entity.getDivision().getName()); + } + + @Test + public void givenEmployeeListToEmployeeDTOList_whenMaps_thenCorrect() { + List employeeList = new ArrayList<>(); + Employee emp = new Employee(); + emp.setId(1); + emp.setName("EmpName"); + emp.setDivision(new Division(1, "Division1")); + employeeList.add(emp); + + List employeeDtoList = mapper.convertEmployeeListToEmployeeDTOList(employeeList); + EmployeeDTO employeeDTO = employeeDtoList.get(0); + assertEquals(employeeDTO.getEmployeeId(), emp.getId()); + assertEquals(employeeDTO.getEmployeeName(), emp.getName()); + assertEquals(employeeDTO.getDivision().getId(), emp.getDivision().getId()); + assertEquals(employeeDTO.getDivision().getName(), emp.getDivision().getName()); + } + + @Test + public void givenEmployeeDTOListToEmployeeList_whenMaps_thenCorrect() { + List employeeDTOList = new ArrayList<>(); + EmployeeDTO empDTO = new EmployeeDTO(); + empDTO.setEmployeeId(1); + empDTO.setEmployeeName("EmpName"); + empDTO.setDivision(new DivisionDTO(1, "Division1")); + employeeDTOList.add(empDTO); + + List employeeList = mapper.convertEmployeeDTOListToEmployeeList(employeeDTOList); + Employee employee = employeeList.get(0); + assertEquals(employee.getId(), empDTO.getEmployeeId()); + assertEquals(employee.getName(), empDTO.getEmployeeName()); + assertEquals(employee.getDivision().getId(), empDTO.getDivision().getId()); + assertEquals(employee.getDivision().getName(), empDTO.getDivision().getName()); + } + + @Test + public void givenEmployeeWithStartDateMappingToEmployeeDTO_whenMaps_thenCorrect() throws ParseException { + Employee entity = new Employee(); + entity.setStartDt(new Date()); + + EmployeeDTO dto = mapper.employeeToEmployeeDTO(entity); + SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT); + assertEquals(format.parse(dto.getEmployeeStartDt()).toString(), entity.getStartDt().toString()); + } + + @Test + public void givenEmployeeDTOWithStartDateMappingToEmployee_whenMaps_thenCorrect() throws ParseException { + EmployeeDTO dto = new EmployeeDTO(); + dto.setEmployeeStartDt("01-04-2016 01:00:00"); + + Employee entity = mapper.employeeDTOtoEmployee(dto); + SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT); + assertEquals(format.parse(dto.getEmployeeStartDt()).toString(), entity.getStartDt().toString()); + } +} diff --git a/mapstruct/src/test/java/com/baeldung/mapper/SimpleSourceDestinationMapperTest.java b/mapstruct/src/test/java/com/baeldung/mapper/SimpleSourceDestinationMapperTest.java new file mode 100644 index 0000000000..a7addf33a7 --- /dev/null +++ b/mapstruct/src/test/java/com/baeldung/mapper/SimpleSourceDestinationMapperTest.java @@ -0,0 +1,44 @@ +package com.baeldung.mapper; + +import static org.junit.Assert.assertEquals; + +import com.baeldung.dto.SimpleSource; +import com.baeldung.entity.SimpleDestination; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:applicationContext.xml") +public class SimpleSourceDestinationMapperTest { + + @Autowired + SimpleSourceDestinationMapper simpleSourceDestinationMapper; + + @Test + public void givenSimpleSourceToSimpleDestination_whenMaps_thenCorrect() { + SimpleSource simpleSource = new SimpleSource(); + simpleSource.setName("SourceName"); + simpleSource.setDescription("SourceDescription"); + + SimpleDestination destination = simpleSourceDestinationMapper.sourceToDestination(simpleSource); + + assertEquals(simpleSource.getName(), destination.getName()); + assertEquals(simpleSource.getDescription(), destination.getDescription()); + } + + @Test + public void givenSimpleDestinationToSourceDestination_whenMaps_thenCorrect() { + SimpleDestination destination = new SimpleDestination(); + destination.setName("DestinationName"); + destination.setDescription("DestinationDescription"); + + SimpleSource source = simpleSourceDestinationMapper.destinationToSource(destination); + + assertEquals(destination.getName(), source.getName()); + assertEquals(destination.getDescription(), source.getDescription()); + } + +} diff --git a/mockito-mocks-spring-beans/pom.xml b/mockito-mocks-spring-beans/pom.xml deleted file mode 100644 index 64dc7d83c9..0000000000 --- a/mockito-mocks-spring-beans/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - 4.0.0 - - com.baeldung - mockito-mocks-spring-beans - 0.0.1-SNAPSHOT - jar - - mocks - Injecting Mockito Mocks into Spring Beans - - - org.springframework.boot - spring-boot-starter-parent - 1.3.1.RELEASE - - - - - UTF-8 - 1.8 - - - - - org.springframework.boot - spring-boot-starter - 1.3.1.RELEASE - - - org.springframework.boot - spring-boot-starter-test - 1.3.1.RELEASE - test - - - org.mockito - mockito-all - 1.10.19 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/mockito/.classpath b/mockito/.classpath deleted file mode 100644 index 8ebf6d9c31..0000000000 --- a/mockito/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mockito/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/mockito/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/mockito/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/mockito/.project b/mockito/.project deleted file mode 100644 index 1c6c0deddc..0000000000 --- a/mockito/.project +++ /dev/null @@ -1,36 +0,0 @@ - - - mockito - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/mockito/.settings/.jsdtscope b/mockito/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/mockito/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/mockito/.settings/org.eclipse.jdt.core.prefs b/mockito/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/mockito/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/mockito/.settings/org.eclipse.jdt.ui.prefs b/mockito/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/mockito/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/mockito/.settings/org.eclipse.m2e.core.prefs b/mockito/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/mockito/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/mockito/.settings/org.eclipse.m2e.wtp.prefs b/mockito/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/mockito/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/mockito/.settings/org.eclipse.wst.common.component b/mockito/.settings/org.eclipse.wst.common.component deleted file mode 100644 index e98377cb0f..0000000000 --- a/mockito/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/mockito/.settings/org.eclipse.wst.common.project.facet.core.xml b/mockito/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f4ef8aa0a5..0000000000 --- a/mockito/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/mockito/.settings/org.eclipse.wst.jsdt.ui.superType.container b/mockito/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/mockito/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/mockito/.settings/org.eclipse.wst.jsdt.ui.superType.name b/mockito/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/mockito/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/mockito/.settings/org.eclipse.wst.validation.prefs b/mockito/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index cacf5451ae..0000000000 --- a/mockito/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,14 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.303.v201202090300 -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/mockito/.settings/org.eclipse.wst.ws.service.policy.prefs b/mockito/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/mockito/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/mockito/.springBeans b/mockito/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/mockito/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/mockito/README.md b/mockito/README.md index 5ecc5722b0..5e7cd19f78 100644 --- a/mockito/README.md +++ b/mockito/README.md @@ -6,4 +6,5 @@ ### Relevant Articles: - [Mockito Verify Cookbook](http://www.baeldung.com/mockito-verify) - [Mockito When/Then Cookbook](http://www.baeldung.com/mockito-behavior) - +- [Mockito – Using Spies](http://www.baeldung.com/mockito-spy) +- [Mockito – @Mock, @Spy, @Captor and @InjectMocks](http://www.baeldung.com/mockito-annotations) diff --git a/mockito/pom.xml b/mockito/pom.xml index a73eea7647..16c7cb0dd8 100644 --- a/mockito/pom.xml +++ b/mockito/pom.xml @@ -1,128 +1,143 @@ - - 4.0.0 - org.baeldung - mockito - 0.1-SNAPSHOT + + 4.0.0 + org.baeldung + mockito + 0.1-SNAPSHOT - mockito + mockito - + - + - - com.google.guava - guava - ${guava.version} - + + com.google.guava + guava + ${guava.version} + - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + - + - + - - junit - junit - ${junit.version} - test - + + junit + junit + ${junit.version} + test + - - org.hamcrest - hamcrest-core - ${org.hamcrest.version} - test - - - org.hamcrest - hamcrest-library - ${org.hamcrest.version} - test - + + org.hamcrest + hamcrest-core + ${org.hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + - - org.mockito - mockito-core - ${mockito.version} - test - + + org.mockito + mockito-core + ${mockito.version} + test + - + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito + ${powermock.version} + test + - - mockito - - - src/main/resources - true - - + - + + mockito + + + src/main/resources + true + + - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - + - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + - + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + - + - - - 4.1.5.RELEASE - 3.2.5.RELEASE + - - 4.3.10.Final - 5.1.35 + + + 4.1.5.RELEASE + 3.2.5.RELEASE - - 1.7.13 - 1.1.3 + + 4.3.10.Final + 5.1.35 - - 5.1.3.Final + + 1.7.13 + 1.1.3 - - 19.0 - 3.4 + + 5.1.3.Final - - 1.3 - 4.12 - 1.10.19 + + 19.0 + 3.4 - 4.4.1 - 4.5 + + 1.3 + 4.12 + 1.10.19 + 1.6.4 - 2.4.1 + 4.4.1 + 4.5 - - 3.3 - 2.6 - 2.18.1 - 2.7 - 1.4.14 + 2.4.1 - + + 3.3 + 2.6 + 2.18.1 + 2.7 + 1.4.14 + + \ No newline at end of file diff --git a/mockito/src/main/webapp/WEB-INF/api-servlet.xml b/mockito/src/main/webapp/WEB-INF/api-servlet.xml deleted file mode 100644 index 4c74be8912..0000000000 --- a/mockito/src/main/webapp/WEB-INF/api-servlet.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/mockito/src/main/webapp/WEB-INF/web.xml b/mockito/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 935beae648..0000000000 --- a/mockito/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - Spring MVC Application - - - - contextClass - - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - contextConfigLocation - org.baeldung.config - - - - org.springframework.web.context.ContextLoaderListener - - - - - api - org.springframework.web.servlet.DispatcherServlet - 1 - - - api - / - - - - - - - \ No newline at end of file diff --git a/mockito/src/test/java/com/baeldung/powermockito/introduction/CollaboratorForPartialMocking.java b/mockito/src/test/java/com/baeldung/powermockito/introduction/CollaboratorForPartialMocking.java new file mode 100644 index 0000000000..771444f13d --- /dev/null +++ b/mockito/src/test/java/com/baeldung/powermockito/introduction/CollaboratorForPartialMocking.java @@ -0,0 +1,20 @@ +package com.baeldung.powermockito.introduction; + +public class CollaboratorForPartialMocking { + + public static String staticMethod() { + return "Hello Baeldung!"; + } + + public final String finalMethod() { + return "Hello Baeldung!"; + } + + private String privateMethod() { + return "Hello Baeldung!"; + } + + public String privateMethodCaller() { + return privateMethod() + " Welcome to the Java world."; + } +} \ No newline at end of file diff --git a/mockito/src/test/java/com/baeldung/powermockito/introduction/CollaboratorWithFinalMethods.java b/mockito/src/test/java/com/baeldung/powermockito/introduction/CollaboratorWithFinalMethods.java new file mode 100644 index 0000000000..8287454782 --- /dev/null +++ b/mockito/src/test/java/com/baeldung/powermockito/introduction/CollaboratorWithFinalMethods.java @@ -0,0 +1,9 @@ +package com.baeldung.powermockito.introduction; + +public class CollaboratorWithFinalMethods { + + public final String helloMethod() { + return "Hello World!"; + } + +} diff --git a/mockito/src/test/java/com/baeldung/powermockito/introduction/CollaboratorWithStaticMethods.java b/mockito/src/test/java/com/baeldung/powermockito/introduction/CollaboratorWithStaticMethods.java new file mode 100644 index 0000000000..2795ae97f1 --- /dev/null +++ b/mockito/src/test/java/com/baeldung/powermockito/introduction/CollaboratorWithStaticMethods.java @@ -0,0 +1,16 @@ +package com.baeldung.powermockito.introduction; + +public class CollaboratorWithStaticMethods { + + public static String firstMethod(String name) { + return "Hello " + name + " !"; + } + + public static String secondMethod() { + return "Hello no one!"; + } + + public static String thirdMethod() { + return "Hello no one again!"; + } +} \ No newline at end of file diff --git a/mockito/src/test/java/com/baeldung/powermockito/introduction/PowerMockitoTest.java b/mockito/src/test/java/com/baeldung/powermockito/introduction/PowerMockitoTest.java new file mode 100644 index 0000000000..6f12f3e459 --- /dev/null +++ b/mockito/src/test/java/com/baeldung/powermockito/introduction/PowerMockitoTest.java @@ -0,0 +1,78 @@ +package com.baeldung.powermockito.introduction; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static org.junit.Assert.assertEquals; +import static org.powermock.api.mockito.PowerMockito.*; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(fullyQualifiedNames = "com.baeldung.powermockito.introduction.*") +public class PowerMockitoTest { + + @Test + public void givenFinalMethods_whenUsingPowerMockito_thenCorrect() throws Exception { + CollaboratorWithFinalMethods mock = mock(CollaboratorWithFinalMethods.class); + whenNew(CollaboratorWithFinalMethods.class).withNoArguments().thenReturn(mock); + + CollaboratorWithFinalMethods collaborator = new CollaboratorWithFinalMethods(); + verifyNew(CollaboratorWithFinalMethods.class).withNoArguments(); + + when(collaborator.helloMethod()).thenReturn("Hello Baeldung!"); + String welcome = collaborator.helloMethod(); + Mockito.verify(collaborator).helloMethod(); + assertEquals("Hello Baeldung!", welcome); + } + + @Test(expected = RuntimeException.class) + public void givenStaticMethods_whenUsingPowerMockito_thenCorrect() { + mockStatic(CollaboratorWithStaticMethods.class); + + when(CollaboratorWithStaticMethods.firstMethod(Mockito.anyString())).thenReturn("Hello Baeldung!"); + when(CollaboratorWithStaticMethods.secondMethod()).thenReturn("Nothing special"); + doThrow(new RuntimeException()).when(CollaboratorWithStaticMethods.class); + CollaboratorWithStaticMethods.thirdMethod(); + + String firstWelcome = CollaboratorWithStaticMethods.firstMethod("Whoever"); + String secondWelcome = CollaboratorWithStaticMethods.firstMethod("Whatever"); + + assertEquals("Hello Baeldung!", firstWelcome); + assertEquals("Hello Baeldung!", secondWelcome); + + verifyStatic(Mockito.times(2)); + CollaboratorWithStaticMethods.firstMethod(Mockito.anyString()); + + verifyStatic(Mockito.never()); + CollaboratorWithStaticMethods.secondMethod(); + + CollaboratorWithStaticMethods.thirdMethod(); + } + + @Test + public void givenPartialMocking_whenUsingPowerMockito_thenCorrect() throws Exception { + String returnValue; + + spy(CollaboratorForPartialMocking.class); + when(CollaboratorForPartialMocking.staticMethod()).thenReturn("I am a static mock method."); + returnValue = CollaboratorForPartialMocking.staticMethod(); + verifyStatic(); + CollaboratorForPartialMocking.staticMethod(); + assertEquals("I am a static mock method.", returnValue); + + CollaboratorForPartialMocking collaborator = new CollaboratorForPartialMocking(); + CollaboratorForPartialMocking mock = spy(collaborator); + + when(mock.finalMethod()).thenReturn("I am a final mock method."); + returnValue = mock.finalMethod(); + Mockito.verify(mock).finalMethod(); + assertEquals("I am a final mock method.", returnValue); + + when(mock, "privateMethod").thenReturn("I am a private mock method."); + returnValue = mock.privateMethodCaller(); + verifyPrivate(mock).invoke("privateMethod"); + assertEquals("I am a private mock method. Welcome to the Java world.", returnValue); + } +} \ No newline at end of file diff --git a/mockito/src/test/java/org/baeldung/mockito/MockitoAnnotationTest.java b/mockito/src/test/java/org/baeldung/mockito/MockitoAnnotationTest.java index 3acc2c937b..ec68c38f70 100644 --- a/mockito/src/test/java/org/baeldung/mockito/MockitoAnnotationTest.java +++ b/mockito/src/test/java/org/baeldung/mockito/MockitoAnnotationTest.java @@ -1,20 +1,14 @@ package org.baeldung.mockito; -import static org.junit.Assert.assertEquals; +import org.junit.Before; +import org.junit.Test; +import org.mockito.*; import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; +import static org.junit.Assert.assertEquals; //@RunWith(MockitoJUnitRunner.class) public class MockitoAnnotationTest { diff --git a/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java b/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java index 399c511d4e..de6e7fca72 100644 --- a/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java +++ b/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java @@ -1,20 +1,17 @@ package org.baeldung.mockito; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; - -import org.junit.Test; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import static org.mockito.Mockito.*; public class MockitoConfigExamplesTest { diff --git a/mockito/src/test/java/org/baeldung/mockito/MockitoMockTest.java b/mockito/src/test/java/org/baeldung/mockito/MockitoMockTest.java new file mode 100644 index 0000000000..5a1996fa97 --- /dev/null +++ b/mockito/src/test/java/org/baeldung/mockito/MockitoMockTest.java @@ -0,0 +1,69 @@ +package org.baeldung.mockito; + +import static org.mockito.Mockito.*; +import static org.junit.Assert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.containsString; +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import org.junit.Test; +import org.junit.Rule; +import org.junit.rules.ExpectedException; +import org.mockito.MockSettings; +import org.mockito.exceptions.verification.TooLittleActualInvocations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +public class MockitoMockTest { + + private static class CustomAnswer implements Answer { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return false; + } + } + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void whenUsingSimpleMock_thenCorrect() { + MyList listMock = mock(MyList.class); + when(listMock.add(anyString())).thenReturn(false); + boolean added = listMock.add(randomAlphabetic(6)); + + verify(listMock).add(anyString()); + assertThat(added, is(false)); + } + + @Test + public void whenUsingMockWithName_thenCorrect() { + MyList listMock = mock(MyList.class, "myMock"); + when(listMock.add(anyString())).thenReturn(false); + listMock.add(randomAlphabetic(6)); + + thrown.expect(TooLittleActualInvocations.class); + thrown.expectMessage(containsString("myMock.add")); + + verify(listMock, times(2)).add(anyString()); + } + + @Test + public void whenUsingMockWithAnswer_thenCorrect() { + MyList listMock = mock(MyList.class, new CustomAnswer()); + boolean added = listMock.add(randomAlphabetic(6)); + + verify(listMock).add(anyString()); + assertThat(added, is(false)); + } + + @Test + public void whenUsingMockWithSettings_thenCorrect() { + MockSettings customSettings = withSettings().defaultAnswer(new CustomAnswer()); + MyList listMock = mock(MyList.class, customSettings); + boolean added = listMock.add(randomAlphabetic(6)); + + verify(listMock).add(anyString()); + assertThat(added, is(false)); + } +} \ No newline at end of file diff --git a/mockito/src/test/java/org/baeldung/mockito/MockitoSpyTest.java b/mockito/src/test/java/org/baeldung/mockito/MockitoSpyTest.java index adfd3ed1ae..8682e16e5d 100644 --- a/mockito/src/test/java/org/baeldung/mockito/MockitoSpyTest.java +++ b/mockito/src/test/java/org/baeldung/mockito/MockitoSpyTest.java @@ -1,16 +1,16 @@ package org.baeldung.mockito; -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; - import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.Spy; import org.mockito.runners.MockitoJUnitRunner; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; + @RunWith(MockitoJUnitRunner.class) public class MockitoSpyTest { diff --git a/mockito/src/test/java/org/baeldung/mockito/MockitoVerifyExamplesTest.java b/mockito/src/test/java/org/baeldung/mockito/MockitoVerifyExamplesTest.java index 6875a9f819..6beae34138 100644 --- a/mockito/src/test/java/org/baeldung/mockito/MockitoVerifyExamplesTest.java +++ b/mockito/src/test/java/org/baeldung/mockito/MockitoVerifyExamplesTest.java @@ -1,26 +1,18 @@ package org.baeldung.mockito; -import static org.hamcrest.Matchers.hasItem; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.atMost; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; - -import java.util.List; - +import com.google.common.collect.Lists; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mockito; import org.mockito.exceptions.verification.NoInteractionsWanted; -import com.google.common.collect.Lists; +import java.util.List; + +import static org.hamcrest.Matchers.hasItem; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; public class MockitoVerifyExamplesTest { @@ -115,10 +107,10 @@ public class MockitoVerifyExamplesTest { @Test public final void whenVerifyingAnInteractionWithArgumentCapture_thenCorrect() { final List mockedList = mock(MyList.class); - mockedList.addAll(Lists. newArrayList("someElement")); + mockedList.addAll(Lists.newArrayList("someElement")); final ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(List.class); verify(mockedList).addAll(argumentCaptor.capture()); - final List capturedArgument = argumentCaptor.> getValue(); + final List capturedArgument = argumentCaptor.>getValue(); assertThat(capturedArgument, hasItem("someElement")); } diff --git a/mockito/src/test/java/org/baeldung/mockito/MyDictionary.java b/mockito/src/test/java/org/baeldung/mockito/MyDictionary.java index 3fb2c30646..a613b28f59 100644 --- a/mockito/src/test/java/org/baeldung/mockito/MyDictionary.java +++ b/mockito/src/test/java/org/baeldung/mockito/MyDictionary.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; public class MyDictionary { + Map wordMap; public MyDictionary() { diff --git a/mocks/jmockit/README.md b/mocks/jmockit/README.md new file mode 100644 index 0000000000..db78b2a3ac --- /dev/null +++ b/mocks/jmockit/README.md @@ -0,0 +1,9 @@ +========= + +## JMockit related tutorials + + +### Relevant Articles: +- [JMockit 101](http://www.baeldung.com/jmockit-101) +- [A Guide to JMockit Expectations](http://www.baeldung.com/jmockit-expectations) +- [JMockit Advanced Topics](http://www.baeldung.com/jmockit-advanced-topics) diff --git a/mocks/jmockit/pom.xml b/mocks/jmockit/pom.xml new file mode 100644 index 0000000000..8b03313a51 --- /dev/null +++ b/mocks/jmockit/pom.xml @@ -0,0 +1,68 @@ + + 4.0.0 + + + com.baeldung + mocks + 1.0.0-SNAPSHOT + ../pom.xml + + + jmockit + jmockit + + + 4.12 + 1.24 + + + 3.3 + 2.18.1 + + + + + junit + junit + ${junit.version} + test + + + + org.jmockit + jmockit + ${jmockit.version} + test + + + + + jmockit + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + + \ No newline at end of file diff --git a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/AdvancedCollaborator.java b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/AdvancedCollaborator.java new file mode 100644 index 0000000000..4d25f466a6 --- /dev/null +++ b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/AdvancedCollaborator.java @@ -0,0 +1,20 @@ +package org.baeldung.mocks.jmockit; + +public class AdvancedCollaborator { + int i; + private int privateField = 5; + public AdvancedCollaborator(){} + public AdvancedCollaborator(String string) throws Exception{ + i = string.length(); + } + public String methodThatCallsPrivateMethod(int i){ + return privateMethod() + i; + } + public int methodThatReturnsThePrivateField(){ + return privateField; + } + private String privateMethod(){ + return "default:"; + } + class InnerAdvancedCollaborator{} +} diff --git a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Collaborator.java b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Collaborator.java new file mode 100644 index 0000000000..60da12fa7c --- /dev/null +++ b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Collaborator.java @@ -0,0 +1,12 @@ +package org.baeldung.mocks.jmockit; + +public class Collaborator { + + public boolean collaborate(String string){ + return false; + } + + public void receive(boolean bool){ + //NOOP + } +} diff --git a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/ExpectationsCollaborator.java b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/ExpectationsCollaborator.java new file mode 100644 index 0000000000..8209464936 --- /dev/null +++ b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/ExpectationsCollaborator.java @@ -0,0 +1,19 @@ +package org.baeldung.mocks.jmockit; + +import java.util.List; + +public interface ExpectationsCollaborator { + String methodForAny1(String s, int i, Boolean b); + void methodForAny2(Long l, List lst); + String methodForWith1(String s, int i); + void methodForWith2(Boolean b, List l); + String methodForNulls1(String s, List l); + void methodForNulls2(String s, List l); + void methodForTimes1(); + void methodForTimes2(); + void methodForTimes3(); + void methodForArgThat(Object o); + String methodReturnsString(); + int methodReturnsInt(); + Object methodForDelegate(int i); +} diff --git a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Model.java b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Model.java new file mode 100644 index 0000000000..79ae24c2f5 --- /dev/null +++ b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Model.java @@ -0,0 +1,7 @@ +package org.baeldung.mocks.jmockit; + +public class Model { + public String getInfo() { + return "info"; + } +} diff --git a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Performer.java b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Performer.java new file mode 100644 index 0000000000..4f8e8adb24 --- /dev/null +++ b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Performer.java @@ -0,0 +1,10 @@ +package org.baeldung.mocks.jmockit; + +public class Performer { + private Collaborator collaborator; + + public void perform(Model model){ + boolean value = collaborator.collaborate(model.getInfo()); + collaborator.receive(value); + } +} diff --git a/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/AdvancedCollaboratorTest.java b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/AdvancedCollaboratorTest.java new file mode 100644 index 0000000000..aaabe44f66 --- /dev/null +++ b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/AdvancedCollaboratorTest.java @@ -0,0 +1,110 @@ +package org.baeldung.mocks.jmockit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.ArrayList; +import java.util.List; + +import org.baeldung.mocks.jmockit.AdvancedCollaborator.InnerAdvancedCollaborator; +import org.junit.Test; +import org.junit.runner.RunWith; + +import mockit.Deencapsulation; +import mockit.Expectations; +import mockit.Invocation; +import mockit.Mock; +import mockit.MockUp; +import mockit.Mocked; +import mockit.Tested; +import mockit.integration.junit4.JMockit; + +@RunWith(JMockit.class) +public class AdvancedCollaboratorTest & Comparable>> { + + @Tested + private AdvancedCollaborator mock; + + @Mocked + private MultiMock multiMock; + + @Test + public void testToMockUpPrivateMethod() { + new MockUp() { + @Mock + private String privateMethod() { + return "mocked: "; + } + }; + String res = mock.methodThatCallsPrivateMethod(1); + assertEquals("mocked: 1", res); + } + + @Test + public void testToMockUpDifficultConstructor() throws Exception { + new MockUp() { + @Mock + public void $init(Invocation invocation, String string) { + ((AdvancedCollaborator) invocation.getInvokedInstance()).i = 1; + } + }; + AdvancedCollaborator coll = new AdvancedCollaborator(null); + assertEquals(1, coll.i); + } + + @Test + public void testToCallPrivateMethodsDirectly() { + Object value = Deencapsulation.invoke(mock, "privateMethod"); + assertEquals("default:", value); + } + + @Test + public void testToSetPrivateFieldDirectly() { + Deencapsulation.setField(mock, "privateField", 10); + assertEquals(10, mock.methodThatReturnsThePrivateField()); + } + + @Test + public void testToGetPrivateFieldDirectly() { + int value = Deencapsulation.getField(mock, "privateField"); + assertEquals(5, value); + } + + @Test + public void testToCreateNewInstanceDirectly() { + AdvancedCollaborator coll = Deencapsulation.newInstance(AdvancedCollaborator.class, "foo"); + assertEquals(3, coll.i); + } + + @Test + public void testToCreateNewInnerClassInstanceDirectly() { + InnerAdvancedCollaborator innerCollaborator = Deencapsulation.newInnerInstance(InnerAdvancedCollaborator.class, mock); + assertNotNull(innerCollaborator); + } + + @Test + @SuppressWarnings("unchecked") + public void testMultipleInterfacesWholeTest() { + new Expectations() { + { + multiMock.get(5); result = "foo"; + multiMock.compareTo((List) any); result = 0; + } + }; + assertEquals("foo", multiMock.get(5)); + assertEquals(0, multiMock.compareTo(new ArrayList<>())); + } + + @Test + @SuppressWarnings("unchecked") + public & Comparable>> void testMultipleInterfacesOneMethod(@Mocked M mock) { + new Expectations() { + { + mock.get(5); result = "foo"; + mock.compareTo((List) any); + result = 0; } + }; + assertEquals("foo", mock.get(5)); + assertEquals(0, mock.compareTo(new ArrayList<>())); + } +} diff --git a/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/ExpectationsTest.java b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/ExpectationsTest.java new file mode 100644 index 0000000000..1c72647133 --- /dev/null +++ b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/ExpectationsTest.java @@ -0,0 +1,158 @@ +package org.baeldung.mocks.jmockit; + +import mockit.Delegate; +import mockit.Expectations; +import mockit.Mocked; +import mockit.StrictExpectations; +import mockit.Verifications; +import mockit.integration.junit4.JMockit; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@RunWith(JMockit.class) +@SuppressWarnings("unchecked") +public class ExpectationsTest { + + @Test + public void testForAny(@Mocked ExpectationsCollaborator mock) throws Exception { + new Expectations() {{ + mock.methodForAny1(anyString, anyInt, anyBoolean); + result = "any"; + }}; + + assertEquals("any", mock.methodForAny1("barfooxyz", 0, Boolean.FALSE)); + mock.methodForAny2(2L, new ArrayList<>()); + + new Verifications() {{ + mock.methodForAny2(anyLong, (List) any); + }}; + } + + @Test + public void testForWith(@Mocked ExpectationsCollaborator mock) throws Exception { + new Expectations() {{ + mock.methodForWith1(withSubstring("foo"), withNotEqual(1)); + result = "with"; + }}; + + assertEquals("with", mock.methodForWith1("barfooxyz", 2)); + mock.methodForWith2(Boolean.TRUE, new ArrayList<>()); + + new Verifications() {{ + mock.methodForWith2(withNotNull(), withInstanceOf(List.class)); + }}; + } + + @Test + public void testWithNulls(@Mocked ExpectationsCollaborator mock) { + new Expectations() {{ + mock.methodForNulls1(anyString, null); + result = "null"; + }}; + + assertEquals("null", mock.methodForNulls1("blablabla", new ArrayList())); + mock.methodForNulls2("blablabla", null); + + new Verifications() {{ + mock.methodForNulls2(anyString, (List) withNull()); + }}; + } + + @Test + public void testWithTimes(@Mocked ExpectationsCollaborator mock) { + new Expectations() {{ + mock.methodForTimes1(); + times = 2; + mock.methodForTimes2(); + }}; + + mock.methodForTimes1(); + mock.methodForTimes1(); + mock.methodForTimes2(); + mock.methodForTimes3(); + mock.methodForTimes3(); + mock.methodForTimes3(); + + new Verifications() {{ + mock.methodForTimes3(); + minTimes = 1; + maxTimes = 3; + }}; + } + + @Test + public void testCustomArgumentMatching(@Mocked ExpectationsCollaborator mock) { + new Expectations() {{ + mock.methodForArgThat(withArgThat(new BaseMatcher() { + @Override + public boolean matches(Object item) { + return item instanceof Model && "info".equals(((Model) item).getInfo()); + } + + @Override + public void describeTo(Description description) { + } + })); + }}; + mock.methodForArgThat(new Model()); + } + + @Test + public void testResultAndReturns(@Mocked ExpectationsCollaborator mock) { + new StrictExpectations() {{ + mock.methodReturnsString(); + result = "foo"; + result = new Exception(); + result = "bar"; + mock.methodReturnsInt(); + result = new int[]{1, 2, 3}; + mock.methodReturnsString(); + returns("foo", "bar"); + mock.methodReturnsInt(); + result = 1; + }}; + + assertEquals("Should return foo", "foo", mock.methodReturnsString()); + try { + mock.methodReturnsString(); + } catch (Exception e) { + // NOOP + } + assertEquals("Should return bar", "bar", mock.methodReturnsString()); + assertEquals("Should return 1", 1, mock.methodReturnsInt()); + assertEquals("Should return 2", 2, mock.methodReturnsInt()); + assertEquals("Should return 3", 3, mock.methodReturnsInt()); + assertEquals("Should return foo", "foo", mock.methodReturnsString()); + assertEquals("Should return bar", "bar", mock.methodReturnsString()); + assertEquals("Should return 1", 1, mock.methodReturnsInt()); + } + + @Test + public void testDelegate(@Mocked ExpectationsCollaborator mock) { + new Expectations() {{ + mock.methodForDelegate(anyInt); + result = new Delegate() { + public int delegate(int i) throws Exception { + if (i < 3) { + return 5; + } else { + throw new Exception(); + } + } + }; + }}; + + assertEquals("Should return 5", 5, mock.methodForDelegate(1)); + try { + mock.methodForDelegate(3); + } catch (Exception e) { + } + } +} diff --git a/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/PerformerTest.java b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/PerformerTest.java new file mode 100644 index 0000000000..2b1b3be0f7 --- /dev/null +++ b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/PerformerTest.java @@ -0,0 +1,32 @@ +package org.baeldung.mocks.jmockit; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import mockit.*; +import mockit.integration.junit4.JMockit; + +@RunWith(JMockit.class) +public class PerformerTest { + + @Injectable + private Collaborator collaborator; + + @Tested + private Performer performer; + + @Test + public void testThePerformMethod(@Mocked Model model) { + new Expectations() {{ + model.getInfo();result = "bar"; + collaborator.collaborate("bar"); result = true; + }}; + + performer.perform(model); + + new Verifications() {{ + collaborator.receive(true); + }}; + } + +} diff --git a/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/ReusingTest.java b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/ReusingTest.java new file mode 100644 index 0000000000..729cb30cd2 --- /dev/null +++ b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/ReusingTest.java @@ -0,0 +1,57 @@ +package org.baeldung.mocks.jmockit; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import mockit.Expectations; +import mockit.Injectable; +import mockit.Mocked; +import mockit.Tested; +import mockit.Verifications; +import mockit.integration.junit4.JMockit; + +@RunWith(JMockit.class) +public class ReusingTest { + + @Injectable + private Collaborator collaborator; + + @Mocked + private Model model; + + @Tested + private Performer performer; + + @Before + public void setup(){ + new Expectations(){{ + model.getInfo(); result = "foo"; minTimes = 0; + collaborator.collaborate("foo"); result = true; minTimes = 0; + }}; + } + + @Test + public void testWithSetup() { + performer.perform(model); + verifyTrueCalls(1); + } + + protected void verifyTrueCalls(int calls){ + new Verifications(){{ + collaborator.receive(true); times = calls; + }}; + } + + final class TrueCallsVerification extends Verifications{ + public TrueCallsVerification(int calls){ + collaborator.receive(true); times = calls; + } + } + + @Test + public void testWithFinalClass() { + performer.perform(model); + new TrueCallsVerification(1); + } +} diff --git a/mocks/mock-comparisons/README.md b/mocks/mock-comparisons/README.md new file mode 100644 index 0000000000..7795487b77 --- /dev/null +++ b/mocks/mock-comparisons/README.md @@ -0,0 +1,7 @@ +========= + +## Mock comparison realated tutorials + + +### Relevant Articles: +- [Mockito vs EasyMock vs JMockit](http://www.baeldung.com/mockito-vs-easymock-vs-jmockit) diff --git a/mocks/mock-comparisons/pom.xml b/mocks/mock-comparisons/pom.xml new file mode 100644 index 0000000000..692bfffd53 --- /dev/null +++ b/mocks/mock-comparisons/pom.xml @@ -0,0 +1,91 @@ + + 4.0.0 + + + com.baeldung + mocks + 1.0.0-SNAPSHOT + ../pom.xml + + + mock-comparisons + mock-comparisons + + + 4.12 + 1.10.19 + 3.4 + 1.24 + + UTF-8 + + + 3.3 + 2.18.1 + + + + + junit + junit + ${junit.version} + test + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + org.easymock + easymock + ${easymock.version} + test + + + + org.jmockit + jmockit + ${jmockit.version} + test + + + + + + mock-comparisons + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + + + + + \ No newline at end of file diff --git a/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java new file mode 100644 index 0000000000..914b0034d2 --- /dev/null +++ b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java @@ -0,0 +1,29 @@ +package org.baeldung.mocks.testCase; + +public class LoginController { + + public LoginService loginService; + + public String login(UserForm userForm) { + if (null == userForm) { + return "ERROR"; + } else { + boolean logged; + + try { + logged = loginService.login(userForm); + } catch (Exception e) { + return "ERROR"; + } + + if (logged) { + loginService.setCurrentUser(userForm.getUsername()); + return "OK"; + } else { + return "KO"; + } + } + } + + // standard setters and getters +} diff --git a/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java new file mode 100644 index 0000000000..2cbff6c9d4 --- /dev/null +++ b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java @@ -0,0 +1,9 @@ +package org.baeldung.mocks.testCase; + +public class LoginDao { + + public int login(UserForm userForm) { + //actual call to a third party library + return 0; + } +} diff --git a/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java new file mode 100644 index 0000000000..d6a31a8047 --- /dev/null +++ b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java @@ -0,0 +1,33 @@ +package org.baeldung.mocks.testCase; + +public class LoginService { + + private LoginDao loginDao; + + private String currentUser; + + public boolean login(UserForm userForm) { + assert null != userForm; + + int loginResults = loginDao.login(userForm); + + switch (loginResults) { + case 1: + return true; + default: + return false; + } + } + + public void setCurrentUser(String username) { + if (null != username) { + this.currentUser = username; + } + } + + public void setLoginDao(LoginDao loginDao) { + this.loginDao = loginDao; + } + + // standard setters and getters +} diff --git a/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java new file mode 100644 index 0000000000..14136d0f31 --- /dev/null +++ b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java @@ -0,0 +1,15 @@ +package org.baeldung.mocks.testCase; + +public class UserForm { + + // public access modifiers as only for testing + + public String password; + + public String username; + + public String getUsername() { + return username; + } + +} diff --git a/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java b/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java new file mode 100644 index 0000000000..25d2b91ede --- /dev/null +++ b/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java @@ -0,0 +1,143 @@ +package org.baeldung.mocks.easymock; + +import org.baeldung.mocks.testCase.LoginController; +import org.baeldung.mocks.testCase.LoginDao; +import org.baeldung.mocks.testCase.LoginService; +import org.baeldung.mocks.testCase.UserForm; +import org.easymock.*; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(EasyMockRunner.class) +public class LoginControllerTest { + + @Mock + private LoginDao loginDao; + + @Mock + private LoginService loginService; + + @TestSubject + private LoginController loginController = new LoginController(); + + @Test + public void assertThatNoMethodHasBeenCalled() { + EasyMock.replay(loginService); + loginController.login(null); + + // no method called + EasyMock.verify(loginService); + } + + @Test + public void assertTwoMethodsHaveBeenCalled() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + EasyMock.expect(loginService.login(userForm)).andReturn(true); + loginService.setCurrentUser("foo"); + EasyMock.replay(loginService); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + EasyMock.verify(loginService); + } + + @Test + public void assertOnlyOneMethodHasBeenCalled() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + EasyMock.expect(loginService.login(userForm)).andReturn(false); + EasyMock.replay(loginService); + + String login = loginController.login(userForm); + + Assert.assertEquals("KO", login); + EasyMock.verify(loginService); + } + + @Test + public void mockExceptionThrowing() { + UserForm userForm = new UserForm(); + EasyMock.expect(loginService.login(userForm)).andThrow(new IllegalArgumentException()); + EasyMock.replay(loginService); + + String login = loginController.login(userForm); + + Assert.assertEquals("ERROR", login); + EasyMock.verify(loginService); + } + + @Test + public void mockAnObjectToPassAround() { + UserForm userForm = EasyMock.mock(UserForm.class); + EasyMock.expect(userForm.getUsername()).andReturn("foo"); + EasyMock.expect(loginService.login(userForm)).andReturn(true); + loginService.setCurrentUser("foo"); + EasyMock.replay(userForm); + EasyMock.replay(loginService); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + EasyMock.verify(userForm); + EasyMock.verify(loginService); + } + + @Test + public void argumentMatching() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + // default matcher + EasyMock.expect(loginService.login(EasyMock.isA(UserForm.class))).andReturn(true); + // complex matcher + loginService.setCurrentUser(specificArgumentMatching("foo")); + EasyMock.replay(loginService); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + EasyMock.verify(loginService); + } + + private static String specificArgumentMatching(final String expected) { + EasyMock.reportMatcher(new IArgumentMatcher() { + @Override + public boolean matches(Object argument) { + return argument instanceof String && ((String) argument).startsWith(expected); + } + + @Override + public void appendTo(StringBuffer buffer) { + //NOOP + } + }); + return null; + } + + @Test + public void partialMocking() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + // use partial mock + LoginService loginServicePartial = EasyMock.partialMockBuilder(LoginService.class). + addMockedMethod("setCurrentUser").createMock(); + loginServicePartial.setCurrentUser("foo"); + // let service's login use implementation so let's mock DAO call + EasyMock.expect(loginDao.login(userForm)).andReturn(1); + + loginServicePartial.setLoginDao(loginDao); + loginController.loginService = loginServicePartial; + + EasyMock.replay(loginDao); + EasyMock.replay(loginServicePartial); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + // verify mocked call + EasyMock.verify(loginServicePartial); + EasyMock.verify(loginDao); + } +} diff --git a/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java b/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java new file mode 100644 index 0000000000..621342fed2 --- /dev/null +++ b/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java @@ -0,0 +1,159 @@ +package org.baeldung.mocks.jmockit; + +import mockit.*; +import mockit.integration.junit4.JMockit; +import org.baeldung.mocks.testCase.LoginController; +import org.baeldung.mocks.testCase.LoginDao; +import org.baeldung.mocks.testCase.LoginService; +import org.baeldung.mocks.testCase.UserForm; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(JMockit.class) +public class LoginControllerTest { + + @Injectable + private LoginDao loginDao; + + @Injectable + private LoginService loginService; + + @Tested + private LoginController loginController; + + @Test + public void assertThatNoMethodHasBeenCalled() { + loginController.login(null); + // no method called + new FullVerifications(loginService) { + }; + } + + @Test + public void assertTwoMethodsHaveBeenCalled() { + final UserForm userForm = new UserForm(); + userForm.username = "foo"; + new Expectations() {{ + loginService.login(userForm); + result = true; + loginService.setCurrentUser("foo"); + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + new FullVerifications(loginService) { + }; + } + + @Test + public void assertOnlyOneMethodHasBeenCalled() { + final UserForm userForm = new UserForm(); + userForm.username = "foo"; + new Expectations() {{ + loginService.login(userForm); + result = false; + // no expectation for setCurrentUser + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("KO", login); + new FullVerifications(loginService) { + }; + } + + @Test + public void mockExceptionThrowing() { + final UserForm userForm = new UserForm(); + new Expectations() {{ + loginService.login(userForm); + result = new IllegalArgumentException(); + // no expectation for setCurrentUser + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("ERROR", login); + new FullVerifications(loginService) { + }; + } + + @Test + public void mockAnObjectToPassAround(@Mocked final UserForm userForm) { + new Expectations() {{ + userForm.getUsername(); + result = "foo"; + loginService.login(userForm); + result = true; + loginService.setCurrentUser("foo"); + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + new FullVerifications(loginService) { + }; + new FullVerifications(userForm) { + }; + } + + @Test + public void argumentMatching() { + final UserForm userForm = new UserForm(); + userForm.username = "foo"; + // default matcher + new Expectations() {{ + loginService.login((UserForm) any); + result = true; + // complex matcher + loginService.setCurrentUser(withArgThat(new BaseMatcher() { + @Override + public boolean matches(Object item) { + return item instanceof String && ((String) item).startsWith("foo"); + } + + @Override + public void describeTo(Description description) { + //NOOP + } + })); + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + new FullVerifications(loginService) { + }; + } + + @Test + public void partialMocking() { + // use partial mock + final LoginService partialLoginService = new LoginService(); + partialLoginService.setLoginDao(loginDao); + loginController.loginService = partialLoginService; + + final UserForm userForm = new UserForm(); + userForm.username = "foo"; + // let service's login use implementation so let's mock DAO call + new Expectations() {{ + loginDao.login(userForm); + result = 1; + // no expectation for loginService.login + partialLoginService.setCurrentUser("foo"); + }}; + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + // verify mocked call + new FullVerifications(partialLoginService) { + }; + new FullVerifications(loginDao) { + }; + } +} diff --git a/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java b/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java new file mode 100644 index 0000000000..59b28a2cb4 --- /dev/null +++ b/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java @@ -0,0 +1,125 @@ +package org.baeldung.mocks.mockito; + +import org.baeldung.mocks.testCase.LoginController; +import org.baeldung.mocks.testCase.LoginDao; +import org.baeldung.mocks.testCase.LoginService; +import org.baeldung.mocks.testCase.UserForm; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.*; + +public class LoginControllerTest { + + @Mock + private LoginDao loginDao; + + @Spy + @InjectMocks + private LoginService spiedLoginService; + + @Mock + private LoginService loginService; + + @InjectMocks + private LoginController loginController; + + @Before + public void setUp() { + loginController = new LoginController(); + MockitoAnnotations.initMocks(this); + } + + @Test + public void assertThatNoMethodHasBeenCalled() { + loginController.login(null); + // no method called + Mockito.verifyZeroInteractions(loginService); + } + + @Test + public void assertTwoMethodsHaveBeenCalled() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + Mockito.when(loginService.login(userForm)).thenReturn(true); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + Mockito.verify(loginService).login(userForm); + Mockito.verify(loginService).setCurrentUser("foo"); + } + + @Test + public void assertOnlyOneMethodHasBeenCalled() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + Mockito.when(loginService.login(userForm)).thenReturn(false); + + String login = loginController.login(userForm); + + Assert.assertEquals("KO", login); + Mockito.verify(loginService).login(userForm); + Mockito.verifyNoMoreInteractions(loginService); + } + + @Test + public void mockExceptionThrowing() { + UserForm userForm = new UserForm(); + Mockito.when(loginService.login(userForm)).thenThrow(IllegalArgumentException.class); + + String login = loginController.login(userForm); + + Assert.assertEquals("ERROR", login); + Mockito.verify(loginService).login(userForm); + Mockito.verifyZeroInteractions(loginService); + } + + @Test + public void mockAnObjectToPassAround() { + UserForm userForm = Mockito.when(Mockito.mock(UserForm.class).getUsername()).thenReturn("foo").getMock(); + Mockito.when(loginService.login(userForm)).thenReturn(true); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + Mockito.verify(loginService).login(userForm); + Mockito.verify(loginService).setCurrentUser("foo"); + } + + @Test + public void argumentMatching() { + UserForm userForm = new UserForm(); + userForm.username = "foo"; + // default matcher + Mockito.when(loginService.login(Mockito.any(UserForm.class))).thenReturn(true); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + Mockito.verify(loginService).login(userForm); + // complex matcher + Mockito.verify(loginService).setCurrentUser(Mockito.argThat(new ArgumentMatcher() { + @Override + public boolean matches(Object argument) { + return argument instanceof String && ((String) argument).startsWith("foo"); + } + })); + } + + @Test + public void partialMocking() { + // use partial mock + loginController.loginService = spiedLoginService; + UserForm userForm = new UserForm(); + userForm.username = "foo"; + // let service's login use implementation so let's mock DAO call + Mockito.when(loginDao.login(userForm)).thenReturn(1); + + String login = loginController.login(userForm); + + Assert.assertEquals("OK", login); + // verify mocked call + Mockito.verify(spiedLoginService).setCurrentUser("foo"); + } +} diff --git a/mocks/pom.xml b/mocks/pom.xml new file mode 100644 index 0000000000..ec02c255ef --- /dev/null +++ b/mocks/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../pom.xml + + + mocks + mocks + pom + + + mock-comparisons + jmockit + + + diff --git a/mutation-testing/README.md b/mutation-testing/README.md new file mode 100644 index 0000000000..5dd60620ba --- /dev/null +++ b/mutation-testing/README.md @@ -0,0 +1,6 @@ +========= + +## Mutation Testing + +### Relevant Articles: +- [Introduction to Mutation Testing Using the PITest Library](http://www.baeldung.com/java-mutation-testing-with-pitest) diff --git a/mutation-testing/pom.xml b/mutation-testing/pom.xml new file mode 100644 index 0000000000..cdee59fcb4 --- /dev/null +++ b/mutation-testing/pom.xml @@ -0,0 +1,77 @@ + + 4.0.0 + com.baeldung + mutation-testing + 0.1-SNAPSHOT + mutation-testing + + + org.pitest + pitest-parent + 1.1.10 + pom + + + junit + junit + 4.9 + + + + + + org.pitest + pitest-maven + 1.1.10 + + + com.baeldung.testing.mutation.* + + + com.baeldung.mutation.test.* + + + + + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 + + + + prepare-agent + + + + report + prepare-package + + report + + + + jacoco-check + + check + + + + + PACKAGE + + + LINE + COVEREDRATIO + 0.50 + + + + + + + + + + + diff --git a/mutation-testing/src/main/java/com/baeldung/testing/mutation/Palindrome.java b/mutation-testing/src/main/java/com/baeldung/testing/mutation/Palindrome.java new file mode 100644 index 0000000000..0b166f1557 --- /dev/null +++ b/mutation-testing/src/main/java/com/baeldung/testing/mutation/Palindrome.java @@ -0,0 +1,15 @@ +package com.baeldung.testing.mutation; + +public class Palindrome { + + public boolean isPalindrome(String inputString) { + if (inputString.length() == 0) { + return true; + } else { + char firstChar = inputString.charAt(0); + char lastChar = inputString.charAt(inputString.length() - 1); + String mid = inputString.substring(1, inputString.length() - 1); + return (firstChar == lastChar) && isPalindrome(mid); + } + } +} diff --git a/mutation-testing/src/test/java/com/baeldung/mutation/test/TestPalindrome.java b/mutation-testing/src/test/java/com/baeldung/mutation/test/TestPalindrome.java new file mode 100644 index 0000000000..3add6290f6 --- /dev/null +++ b/mutation-testing/src/test/java/com/baeldung/mutation/test/TestPalindrome.java @@ -0,0 +1,34 @@ +package com.baeldung.mutation.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.baeldung.testing.mutation.Palindrome; + +public class TestPalindrome { + @Test + public void whenEmptyString_thanAccept() { + Palindrome palindromeTester = new Palindrome(); + assertTrue(palindromeTester.isPalindrome("noon")); + } + + @Test + public void whenPalindrom_thanAccept() { + Palindrome palindromeTester = new Palindrome(); + assertTrue(palindromeTester.isPalindrome("noon")); + } + + @Test + public void whenNotPalindrom_thanReject(){ + Palindrome palindromeTester = new Palindrome(); + assertFalse(palindromeTester.isPalindrome("box")); + } + + @Test + public void whenNearPalindrom_thanReject(){ + Palindrome palindromeTester = new Palindrome(); + assertFalse(palindromeTester.isPalindrome("neon")); + } +} diff --git a/okhttp/src/main/java/org/baeldung/okhttp/ProgressRequestWrapper.java b/okhttp/src/main/java/org/baeldung/okhttp/ProgressRequestWrapper.java index 42df4ac1ee..6a98f8d20a 100644 --- a/okhttp/src/main/java/org/baeldung/okhttp/ProgressRequestWrapper.java +++ b/okhttp/src/main/java/org/baeldung/okhttp/ProgressRequestWrapper.java @@ -1,16 +1,11 @@ package org.baeldung.okhttp; -import okhttp3.RequestBody; import okhttp3.MediaType; +import okhttp3.RequestBody; +import okio.*; import java.io.IOException; -import okio.Buffer; -import okio.BufferedSink; -import okio.ForwardingSink; -import okio.Okio; -import okio.Sink; - public class ProgressRequestWrapper extends RequestBody { protected RequestBody delegate; @@ -65,9 +60,8 @@ public class ProgressRequestWrapper extends RequestBody { } - public static interface ProgressListener { - - public void onRequestProgress(long bytesWritten, long contentLength); + public interface ProgressListener { + void onRequestProgress(long bytesWritten, long contentLength); } } diff --git a/orika/pom.xml b/orika/pom.xml new file mode 100644 index 0000000000..c335b0dc22 --- /dev/null +++ b/orika/pom.xml @@ -0,0 +1,60 @@ + + 4.0.0 + com.baeldung + orika + 1.0 + + + 1.7.5 + 1.7.5 + 1.4.6 + 4.3 + + + Orika + + + + + org.slf4j + slf4j-api + ${slf4j-api.version} + + + + org.slf4j + jcl-over-slf4j + ${jcl-over-slf4j.version} + + + + ma.glasnost.orika + orika-core + ${orika-core.version} + + + + junit + junit + ${junit.version} + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 7 + 7 + + + + + + diff --git a/orika/src/main/java/com/baeldung/orika/Dest.java b/orika/src/main/java/com/baeldung/orika/Dest.java new file mode 100644 index 0000000000..4f050230ce --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/Dest.java @@ -0,0 +1,37 @@ +package com.baeldung.orika; + +public class Dest { + @Override + public String toString() { + return "Dest [name=" + name + ", age=" + age + "]"; + } + + private String name; + private int age; + + public Dest() { + + } + + public Dest(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/Name.java b/orika/src/main/java/com/baeldung/orika/Name.java new file mode 100644 index 0000000000..fcf0214548 --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/Name.java @@ -0,0 +1,28 @@ +package com.baeldung.orika; + +public class Name { + private String firstName; + private String lastName; + + public Name(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/Person.java b/orika/src/main/java/com/baeldung/orika/Person.java new file mode 100644 index 0000000000..90ae8dee5e --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/Person.java @@ -0,0 +1,48 @@ +package com.baeldung.orika; + +public class Person { + @Override + public String toString() { + return "Person [name=" + name + ", nickname=" + nickname + ", age=" + + age + "]"; + } + + private String name; + private String nickname; + private int age; + + public Person() { + + } + + public Person(String name, String nickname, int age) { + this.name = name; + this.nickname = nickname; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/Person3.java b/orika/src/main/java/com/baeldung/orika/Person3.java new file mode 100644 index 0000000000..8661edfc10 --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/Person3.java @@ -0,0 +1,38 @@ +package com.baeldung.orika; + +public class Person3 { + private String name; + private String dtob; + + public Person3() { + + } + + public Person3(String name, String dtob) { + this.name = name; + this.dtob = dtob; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDtob() { + return dtob; + } + + public void setDtob(String dtob) { + this.dtob = dtob; + } + + @Override + public String toString() { + return "Person3 [name=" + name + ", dtob=" + dtob + "]"; + } + + +} diff --git a/orika/src/main/java/com/baeldung/orika/PersonContainer.java b/orika/src/main/java/com/baeldung/orika/PersonContainer.java new file mode 100644 index 0000000000..aaec136bb9 --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/PersonContainer.java @@ -0,0 +1,18 @@ +package com.baeldung.orika; + +public class PersonContainer { + private Name name; + + public PersonContainer(Name name) { + this.name = name; + } + + public Name getName() { + return name; + } + + public void setName(Name name) { + this.name = name; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/PersonCustomMapper.java b/orika/src/main/java/com/baeldung/orika/PersonCustomMapper.java new file mode 100644 index 0000000000..d839eea30e --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/PersonCustomMapper.java @@ -0,0 +1,36 @@ +package com.baeldung.orika; + +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MappingContext; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +class PersonCustomMapper extends CustomMapper { + + @Override + public void mapAtoB(Personne3 a, Person3 b, MappingContext context) { + Date date = new Date(a.getDtob()); + DateFormat format = new SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss'Z'"); + String isoDate = format.format(date); + b.setDtob(isoDate); + } + + @Override + public void mapBtoA(Person3 b, Personne3 a, MappingContext context) { + DateFormat format = new SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss'Z'"); + Date date = null; + try { + date = format.parse(b.getDtob()); + + } catch (ParseException e) { + e.printStackTrace(); + } + long timestamp = date.getTime(); + a.setDtob(timestamp); + } +} diff --git a/orika/src/main/java/com/baeldung/orika/PersonListContainer.java b/orika/src/main/java/com/baeldung/orika/PersonListContainer.java new file mode 100644 index 0000000000..97ae15eb48 --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/PersonListContainer.java @@ -0,0 +1,20 @@ +package com.baeldung.orika; + +import java.util.List; + +public class PersonListContainer { + private List names; + + public PersonListContainer(List names) { + this.names = names; + } + + public List getNames() { + return names; + } + + public void setNames(List names) { + this.names = names; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/PersonNameArray.java b/orika/src/main/java/com/baeldung/orika/PersonNameArray.java new file mode 100644 index 0000000000..f2e98be537 --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/PersonNameArray.java @@ -0,0 +1,18 @@ +package com.baeldung.orika; + +public class PersonNameArray { + private String[] nameArray; + + public PersonNameArray(String[] nameArray) { + this.nameArray = nameArray; + } + + public String[] getNameArray() { + return nameArray; + } + + public void setNameArray(String[] nameArray) { + this.nameArray = nameArray; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/PersonNameList.java b/orika/src/main/java/com/baeldung/orika/PersonNameList.java new file mode 100644 index 0000000000..70798ebd35 --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/PersonNameList.java @@ -0,0 +1,20 @@ +package com.baeldung.orika; + +import java.util.List; + +public class PersonNameList { + private List nameList; + + public PersonNameList(List nameList) { + this.nameList = nameList; + } + + public List getNameList() { + return nameList; + } + + public void setNameList(List nameList) { + this.nameList = nameList; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/PersonNameMap.java b/orika/src/main/java/com/baeldung/orika/PersonNameMap.java new file mode 100644 index 0000000000..8126cdfc3a --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/PersonNameMap.java @@ -0,0 +1,20 @@ +package com.baeldung.orika; + +import java.util.Map; + +public class PersonNameMap { + private Map nameMap; + + public PersonNameMap(Map nameMap) { + this.nameMap = nameMap; + } + + public Map getNameMap() { + return nameMap; + } + + public void setNameMap(Map nameList) { + this.nameMap = nameList; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/PersonNameParts.java b/orika/src/main/java/com/baeldung/orika/PersonNameParts.java new file mode 100644 index 0000000000..7cfdcdd75b --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/PersonNameParts.java @@ -0,0 +1,28 @@ +package com.baeldung.orika; + +public class PersonNameParts { + private String firstName; + private String lastName; + + public PersonNameParts(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/Personne.java b/orika/src/main/java/com/baeldung/orika/Personne.java new file mode 100644 index 0000000000..47789dd323 --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/Personne.java @@ -0,0 +1,44 @@ +package com.baeldung.orika; + +public class Personne { + private String nom; + private String surnom; + private int age; + + public Personne(String nom, String surnom, int age) { + this.nom = nom; + this.surnom = surnom; + this.age = age; + } + + public String getNom() { + return nom; + } + + public void setNom(String nom) { + this.nom = nom; + } + + public String getSurnom() { + return surnom; + } + + public void setSurnom(String surnom) { + this.surnom = surnom; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public String toString() { + return "Personne [nom=" + nom + ", surnom=" + surnom + ", age=" + age + + "]"; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/Personne3.java b/orika/src/main/java/com/baeldung/orika/Personne3.java new file mode 100644 index 0000000000..35323c612a --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/Personne3.java @@ -0,0 +1,37 @@ +package com.baeldung.orika; + +public class Personne3 { + private String name; + private long dtob; + + public Personne3() { + + } + + public Personne3(String name, long dtob) { + this.name = name; + this.dtob = dtob; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getDtob() { + return dtob; + } + + public void setDtob(long dtob) { + this.dtob = dtob; + } + + @Override + public String toString() { + return "Personne3 [name=" + name + ", dtob=" + dtob + "]"; + } + +} diff --git a/orika/src/main/java/com/baeldung/orika/Source.java b/orika/src/main/java/com/baeldung/orika/Source.java new file mode 100644 index 0000000000..a973bab388 --- /dev/null +++ b/orika/src/main/java/com/baeldung/orika/Source.java @@ -0,0 +1,36 @@ +package com.baeldung.orika; + +public class Source { + @Override + public String toString() { + return "Source [name=" + name + ", age=" + age + "]"; + } + + private String name; + private int age; + + public Source() { + } + + public Source(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/orika/src/test/java/com/baeldung/orika/OrikaTest.java b/orika/src/test/java/com/baeldung/orika/OrikaTest.java new file mode 100644 index 0000000000..18dfcfa44e --- /dev/null +++ b/orika/src/test/java/com/baeldung/orika/OrikaTest.java @@ -0,0 +1,367 @@ +package com.baeldung.orika; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import ma.glasnost.orika.BoundMapperFacade; +import ma.glasnost.orika.CustomMapper; +import ma.glasnost.orika.MapperFacade; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.impl.DefaultMapperFactory; + +import org.junit.Before; +import org.junit.Test; + +public class OrikaTest { + MapperFactory mapperFactory; + CustomMapper customMapper; + // constant to help us cover time zone differences + private final long GMT_DIFFERENCE = 46800000; + + @Before + public void before() { + mapperFactory = new DefaultMapperFactory.Builder().build(); + customMapper = new PersonCustomMapper(); + } + + @Test + public void givenSrcAndDest_whenMaps_thenCorrect() { + mapperFactory.classMap(Source.class, Dest.class); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Source src = new Source("Baeldung", 10); + Dest dest = mapper.map(src, Dest.class); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), src.getName()); + } + + @Test + public void givenSrcAndDest_whenMapsReverse_thenCorrect() { + mapperFactory.classMap(Source.class, Dest.class).byDefault(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Dest src = new Dest("Baeldung", 10); + Source dest = mapper.map(src, Source.class); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), src.getName()); + } + + @Test + public void givenSrcAndDest_whenMapsByObject_thenCorrect() { + mapperFactory.classMap(Source.class, Dest.class).byDefault(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Source src = new Source("Baeldung", 10); + Dest dest = new Dest(); + mapper.map(src, dest); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), src.getName()); + } + + @Test + public void givenSrcAndDest_whenMapsUsingBoundMapper_thenCorrect() { + BoundMapperFacade boundMapper = mapperFactory + .getMapperFacade(Source.class, Dest.class); + Source src = new Source("baeldung", 10); + Dest dest = boundMapper.map(src); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), src.getName()); + } + + @Test + public void givenSrcAndDest_whenMapsUsingBoundMapperInReverse_thenCorrect() { + BoundMapperFacade boundMapper = mapperFactory + .getMapperFacade(Source.class, Dest.class); + Dest src = new Dest("baeldung", 10); + Source dest = boundMapper.mapReverse(src); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), src.getName()); + } + + @Test + public void givenSrcAndDest_whenMapsUsingBoundMapperByObject_thenCorrect() { + BoundMapperFacade boundMapper = mapperFactory + .getMapperFacade(Source.class, Dest.class); + Source src = new Source("baeldung", 10); + Dest dest = new Dest(); + boundMapper.map(src, dest); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), src.getName()); + } + + @Test + public void givenSrcAndDest_whenMapsUsingBoundMapperByObjectInReverse_thenCorrect() { + BoundMapperFacade boundMapper = mapperFactory + .getMapperFacade(Source.class, Dest.class); + Dest src = new Dest("baeldung", 10); + Source dest = new Source(); + boundMapper.mapReverse(src, dest); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), src.getName()); + } + + @Test + public void givenSrcAndDestWithDifferentFieldNames_whenMaps_thenCorrect() { + mapperFactory.classMap(Personne.class, Person.class) + .field("nom", "name").field("surnom", "nickname") + .field("age", "age").register(); + + MapperFacade mapper = mapperFactory.getMapperFacade(); + + Personne frenchPerson = new Personne("Claire", "cla", 25); + Person englishPerson = mapper.map(frenchPerson, Person.class); + + assertEquals(englishPerson.getName(), frenchPerson.getNom()); + assertEquals(englishPerson.getNickname(), frenchPerson.getSurnom()); + assertEquals(englishPerson.getAge(), frenchPerson.getAge()); + + } + + @Test + public void givenBothDifferentAndSameFieldNames_whenFailsToMapSameNameFieldAutomatically_thenCorrect() { + mapperFactory.classMap(Personne.class, Person.class) + .field("nom", "name").field("surnom", "nickname").register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Personne frenchPerson = new Personne("Claire", "cla", 25); + + Person englishPerson = mapper.map(frenchPerson, Person.class); + assertFalse(englishPerson.getAge() == frenchPerson.getAge()); + + } + + @Test + public void givenBothDifferentAndSameFieldNames_whenMapsSameNameFieldByDefault_thenCorrect() { + mapperFactory.classMap(Personne.class, Person.class) + .field("nom", "name").field("surnom", "nickname").byDefault() + .register(); + + MapperFacade mapper = mapperFactory.getMapperFacade(); + Personne frenchPerson = new Personne("Claire", "cla", 25); + + Person englishPerson = mapper.map(frenchPerson, Person.class); + assertEquals(englishPerson.getName(), frenchPerson.getNom()); + assertEquals(englishPerson.getNickname(), frenchPerson.getSurnom()); + assertEquals(englishPerson.getAge(), frenchPerson.getAge()); + + } + + @Test + public void givenUnidirectionalMappingSetup_whenMapsUnidirectionally_thenCorrect() { + mapperFactory.classMap(Personne.class, Person.class) + .fieldAToB("nom", "name").fieldAToB("surnom", "nickname") + .fieldAToB("age", "age").register(); + ; + MapperFacade mapper = mapperFactory.getMapperFacade(); + Personne frenchPerson = new Personne("Claire", "cla", 25); + + Person englishPerson = mapper.map(frenchPerson, Person.class); + assertEquals(englishPerson.getName(), frenchPerson.getNom()); + assertEquals(englishPerson.getNickname(), frenchPerson.getSurnom()); + assertEquals(englishPerson.getAge(), frenchPerson.getAge()); + + } + + + @Test + public void givenSrcAndDest_whenCanExcludeField_thenCorrect() { + mapperFactory.classMap(Personne.class, Person.class).exclude("nom") + .field("surnom", "nickname").field("age", "age").register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + + Personne frenchPerson = new Personne("Claire", "cla", 25); + Person englishPerson = mapper.map(frenchPerson, Person.class); + + assertEquals(null, englishPerson.getName()); + assertEquals(englishPerson.getNickname(), frenchPerson.getSurnom()); + assertEquals(englishPerson.getAge(), frenchPerson.getAge()); + } + + @Test + public void givenSpecificConstructorToUse_whenMaps_thenCorrect() { + mapperFactory.classMap(Personne.class, Person.class).constructorB() + .field("nom", "name").field("surnom", "nickname") + .field("age", "age").register(); + ; + MapperFacade mapper = mapperFactory.getMapperFacade(); + Personne frenchPerson = new Personne("Claire", "cla", 25); + + Person englishPerson = mapper.map(frenchPerson, Person.class); + assertEquals(englishPerson.getName(), frenchPerson.getNom()); + assertEquals(englishPerson.getNickname(), frenchPerson.getSurnom()); + assertEquals(englishPerson.getAge(), frenchPerson.getAge()); + + } + + @Test + public void givenSrcWithListAndDestWithPrimitiveAttributes_whenMaps_thenCorrect() { + mapperFactory.classMap(PersonNameList.class, PersonNameParts.class) + .field("nameList[0]", "firstName") + .field("nameList[1]", "lastName").register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + List nameList = Arrays.asList(new String[]{"Sylvester", + "Stallone"}); + PersonNameList src = new PersonNameList(nameList); + PersonNameParts dest = mapper.map(src, PersonNameParts.class); + assertEquals(dest.getFirstName(), "Sylvester"); + assertEquals(dest.getLastName(), "Stallone"); + } + + @Test + public void givenSrcWithArrayAndDestWithPrimitiveAttributes_whenMaps_thenCorrect() { + mapperFactory.classMap(PersonNameArray.class, PersonNameParts.class) + .field("nameArray[0]", "firstName") + .field("nameArray[1]", "lastName").register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + String[] nameArray = new String[]{"Vin", "Diesel"}; + PersonNameArray src = new PersonNameArray(nameArray); + PersonNameParts dest = mapper.map(src, PersonNameParts.class); + assertEquals(dest.getFirstName(), "Vin"); + assertEquals(dest.getLastName(), "Diesel"); + } + + @Test + public void givenSrcWithMapAndDestWithPrimitiveAttributes_whenMaps_thenCorrect() { + mapperFactory.classMap(PersonNameMap.class, PersonNameParts.class) + .field("nameMap['first']", "firstName") + .field("nameMap[\"last\"]", "lastName").register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Map nameMap = new HashMap<>(); + nameMap.put("first", "Leornado"); + nameMap.put("last", "DiCaprio"); + PersonNameMap src = new PersonNameMap(nameMap); + PersonNameParts dest = mapper.map(src, PersonNameParts.class); + assertEquals(dest.getFirstName(), "Leornado"); + assertEquals(dest.getLastName(), "DiCaprio"); + } + + @Test + public void givenSrcWithNestedFields_whenMaps_thenCorrect() { + mapperFactory.classMap(PersonContainer.class, PersonNameParts.class) + .field("name.firstName", "firstName") + .field("name.lastName", "lastName").register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + PersonContainer src = new PersonContainer(new Name("Nick", "Canon")); + PersonNameParts dest = mapper.map(src, PersonNameParts.class); + assertEquals(dest.getFirstName(), "Nick"); + assertEquals(dest.getLastName(), "Canon"); + } + + @Test + public void givenSrcWithNullField_whenMapsThenCorrect() { + mapperFactory.classMap(Source.class, Dest.class).byDefault(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Source src = new Source(null, 10); + Dest dest = mapper.map(src, Dest.class); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), src.getName()); + } + + @Test + public void givenSrcWithNullAndGlobalConfigForNoNull_whenFailsToMap_ThenCorrect() { + MapperFactory mapperFactory = new DefaultMapperFactory.Builder() + .mapNulls(false).build(); + mapperFactory.classMap(Source.class, Dest.class); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Source src = new Source(null, 10); + Dest dest = new Dest("Clinton", 55); + mapper.map(src, dest); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), "Clinton"); + } + + @Test + public void givenSrcWithNullAndLocalConfigForNoNull_whenFailsToMap_ThenCorrect() { + mapperFactory.classMap(Source.class, Dest.class).field("age", "age") + .mapNulls(false).field("name", "name").byDefault().register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Source src = new Source(null, 10); + Dest dest = new Dest("Clinton", 55); + mapper.map(src, dest); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), "Clinton"); + } + + @Test + public void givenDestWithNullReverseMappedToSource_whenMapsByDefault_thenCorrect() { + mapperFactory.classMap(Source.class, Dest.class).byDefault(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Dest src = new Dest(null, 10); + Source dest = new Source("Vin", 44); + mapper.map(src, dest); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), src.getName()); + } + + @Test + public void givenDestWithNullReverseMappedToSourceAndLocalConfigForNoNull_whenFailsToMap_thenCorrect() { + mapperFactory.classMap(Source.class, Dest.class).field("age", "age") + .mapNullsInReverse(false).field("name", "name").byDefault() + .register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Dest src = new Dest(null, 10); + Source dest = new Source("Vin", 44); + mapper.map(src, dest); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), "Vin"); + } + + @Test + public void givenSrcWithNullAndFieldLevelConfigForNoNull_whenFailsToMap_ThenCorrect() { + mapperFactory.classMap(Source.class, Dest.class).field("age", "age") + .fieldMap("name", "name").mapNulls(false).add().byDefault() + .register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + Source src = new Source(null, 10); + Dest dest = new Dest("Clinton", 55); + mapper.map(src, dest); + assertEquals(dest.getAge(), src.getAge()); + assertEquals(dest.getName(), "Clinton"); + } + + @Test + public void givenSrcAndDest_whenCustomMapperWorks_thenCorrect() { + mapperFactory.classMap(Personne3.class, Person3.class) + .customize(customMapper).register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + long timestamp = new Long("1182882159000"); + Personne3 personne3 = new Personne3("Leornardo", timestamp); + Person3 person3 = mapper.map(personne3, Person3.class); + + String timestampTest = person3.getDtob(); + // since different timezones will resolve the timestamp to a different + // datetime string, it suffices to check only for format rather than + // specific date + assertTrue(timestampTest.charAt(10) == 'T' + && timestampTest.charAt(19) == 'Z'); + } + + @Test + public void givenSrcAndDest_whenCustomMapperWorksBidirectionally_thenCorrect() { + mapperFactory.classMap(Personne3.class, Person3.class) + .customize(customMapper).register(); + MapperFacade mapper = mapperFactory.getMapperFacade(); + + String dateTime = "2007-06-26T21:22:39Z"; + long timestamp = new Long("1182882159000"); + Person3 person3 = new Person3("Leornardo", dateTime); + Personne3 personne3 = mapper.map(person3, Personne3.class); + long timestampToTest = personne3.getDtob(); + /* + * since different timezones will resolve the datetime to a different + * unix timestamp, we must provide a range of tolerance + */ + assertTrue(timestampToTest == timestamp + || timestampToTest >= timestamp - GMT_DIFFERENCE + || timestampToTest <= timestamp + GMT_DIFFERENCE); + + } + +} diff --git a/patterns/pom.xml b/patterns/pom.xml new file mode 100644 index 0000000000..7c23b6f55d --- /dev/null +++ b/patterns/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + com.baeldung.enterprise.patterns + patterns + war + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.eclipse.jetty + jetty-maven-plugin + 9.4.0.M1 + + + /front-controller + + + + + + diff --git a/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/FrontControllerServlet.java b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/FrontControllerServlet.java new file mode 100644 index 0000000000..a8962f5108 --- /dev/null +++ b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/FrontControllerServlet.java @@ -0,0 +1,38 @@ +package com.baeldung.enterprise.patterns.front.controller; + +import com.baeldung.enterprise.patterns.front.controller.commands.FrontCommand; +import com.baeldung.enterprise.patterns.front.controller.commands.UnknownCommand; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class FrontControllerServlet extends HttpServlet { + @Override + protected void doGet( + HttpServletRequest request, + HttpServletResponse response + ) throws ServletException, IOException { + FrontCommand command = getCommand(request); + command.init(getServletContext(), request, response); + command.process(); + } + + private FrontCommand getCommand(HttpServletRequest request) { + try { + Class type = Class.forName( + String.format( + "com.baeldung.enterprise.patterns.front.controller.commands.%sCommand", + request.getParameter("command") + ) + ); + return (FrontCommand) type + .asSubclass(FrontCommand.class) + .newInstance(); + } catch (Exception e) { + return new UnknownCommand(); + } + } +} diff --git a/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/commands/FrontCommand.java b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/commands/FrontCommand.java new file mode 100644 index 0000000000..12a008faeb --- /dev/null +++ b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/commands/FrontCommand.java @@ -0,0 +1,32 @@ +package com.baeldung.enterprise.patterns.front.controller.commands; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public abstract class FrontCommand { + protected ServletContext context; + protected HttpServletRequest request; + protected HttpServletResponse response; + + public void init( + ServletContext servletContext, + HttpServletRequest servletRequest, + HttpServletResponse servletResponse + ) { + this.context = servletContext; + this.request = servletRequest; + this.response = servletResponse; + } + + public abstract void process() throws ServletException, IOException; + + protected void forward(String target) throws ServletException, IOException { + target = String.format("/WEB-INF/jsp/%s.jsp", target); + RequestDispatcher dispatcher = context.getRequestDispatcher(target); + dispatcher.forward(request, response); + } +} diff --git a/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/commands/SearchCommand.java b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/commands/SearchCommand.java new file mode 100644 index 0000000000..0c5bd64bbc --- /dev/null +++ b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/commands/SearchCommand.java @@ -0,0 +1,21 @@ +package com.baeldung.enterprise.patterns.front.controller.commands; + +import com.baeldung.enterprise.patterns.front.controller.data.Book; +import com.baeldung.enterprise.patterns.front.controller.data.BookshelfImpl; + +import javax.servlet.ServletException; +import java.io.IOException; + +public class SearchCommand extends FrontCommand { + @Override + public void process() throws ServletException, IOException { + Book book = new BookshelfImpl().getInstance() + .findByTitle(request.getParameter("title")); + if (book != null) { + request.setAttribute("book", book); + forward("book-found"); + } else { + forward("book-notfound"); + } + } +} diff --git a/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/commands/UnknownCommand.java b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/commands/UnknownCommand.java new file mode 100644 index 0000000000..90103c8f42 --- /dev/null +++ b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/commands/UnknownCommand.java @@ -0,0 +1,11 @@ +package com.baeldung.enterprise.patterns.front.controller.commands; + +import javax.servlet.ServletException; +import java.io.IOException; + +public class UnknownCommand extends FrontCommand { + @Override + public void process() throws ServletException, IOException { + forward("unknown"); + } +} diff --git a/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/data/Book.java b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/data/Book.java new file mode 100644 index 0000000000..634e05c3a0 --- /dev/null +++ b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/data/Book.java @@ -0,0 +1,40 @@ +package com.baeldung.enterprise.patterns.front.controller.data; + +public class Book { + private String author; + private String title; + private Double price; + + public Book() { + } + + public Book(String author, String title, Double price) { + this.author = author; + this.title = title; + this.price = price; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } +} diff --git a/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/data/Bookshelf.java b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/data/Bookshelf.java new file mode 100644 index 0000000000..524e000bd9 --- /dev/null +++ b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/data/Bookshelf.java @@ -0,0 +1,15 @@ +package com.baeldung.enterprise.patterns.front.controller.data; + +public interface Bookshelf { + + default void init() { + add(new Book("Wilson, Robert Anton & Shea, Robert", "Illuminati", 9.99)); + add(new Book("Fowler, Martin", "Patterns of Enterprise Application Architecture", 27.88)); + } + + Bookshelf getInstance(); + + boolean add(E book); + + Book findByTitle(String title); +} diff --git a/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/data/BookshelfImpl.java b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/data/BookshelfImpl.java new file mode 100644 index 0000000000..3862418857 --- /dev/null +++ b/patterns/src/main/java/com/baeldung/enterprise/patterns/front/controller/data/BookshelfImpl.java @@ -0,0 +1,24 @@ +package com.baeldung.enterprise.patterns.front.controller.data; + +import java.util.ArrayList; + +public class BookshelfImpl extends ArrayList implements Bookshelf { + private static Bookshelf INSTANCE; + + @Override + public Bookshelf getInstance() { + if (INSTANCE == null) { + INSTANCE = new BookshelfImpl(); + INSTANCE.init(); + } + return INSTANCE; + } + + @Override + public Book findByTitle(String title) { + return this.stream() + .filter(book -> book.getTitle().toLowerCase().contains(title.toLowerCase())) + .findFirst() + .orElse(null); + } +} diff --git a/patterns/src/main/resources/front controller.png b/patterns/src/main/resources/front controller.png new file mode 100644 index 0000000000..af22a38e37 Binary files /dev/null and b/patterns/src/main/resources/front controller.png differ diff --git a/patterns/src/main/resources/front controller.puml b/patterns/src/main/resources/front controller.puml new file mode 100644 index 0000000000..cbc2dc8bd9 --- /dev/null +++ b/patterns/src/main/resources/front controller.puml @@ -0,0 +1,22 @@ +@startuml +scale 1.5 +class Handler { +doGet +doPost +} + +abstract class AbstractCommand { +process +} +class ConcreteCommand1 { +process +} +class ConcreteCommand2 { +process +} + +Handler .right.> AbstractCommand +AbstractCommand <|-- ConcreteCommand1 +AbstractCommand <|-- ConcreteCommand2 + +@enduml \ No newline at end of file diff --git a/patterns/src/main/webapp/WEB-INF/jsp/book-found.jsp b/patterns/src/main/webapp/WEB-INF/jsp/book-found.jsp new file mode 100644 index 0000000000..42e08b4a46 --- /dev/null +++ b/patterns/src/main/webapp/WEB-INF/jsp/book-found.jsp @@ -0,0 +1,12 @@ + + + + Bookshelf: Title found + + +

    Our Bookshelf contains this title:

    +

    ${book.getTitle()}

    +

    Author: ${book.getAuthor()}

    + + + diff --git a/patterns/src/main/webapp/WEB-INF/jsp/book-notfound.jsp b/patterns/src/main/webapp/WEB-INF/jsp/book-notfound.jsp new file mode 100644 index 0000000000..2f8ac01755 --- /dev/null +++ b/patterns/src/main/webapp/WEB-INF/jsp/book-notfound.jsp @@ -0,0 +1,10 @@ + + + + Bookshelf: Title not found + + +

    Our Bookshelf doesn't contains this title:

    +

    ${param.get("title")}

    + + diff --git a/patterns/src/main/webapp/WEB-INF/jsp/unknown.jsp b/patterns/src/main/webapp/WEB-INF/jsp/unknown.jsp new file mode 100644 index 0000000000..b52b2de8d5 --- /dev/null +++ b/patterns/src/main/webapp/WEB-INF/jsp/unknown.jsp @@ -0,0 +1,9 @@ + + + + Bookshelf: Command unknown + + +

    Sorry, this command is not known!

    + + diff --git a/patterns/src/main/webapp/WEB-INF/web.xml b/patterns/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..77113db09b --- /dev/null +++ b/patterns/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,15 @@ + + + + front-controller + com.baeldung.enterprise.patterns.front.controller.FrontControllerServlet + + + front-controller + / + + diff --git a/play-framework/student-api/.gitignore b/play-framework/student-api/.gitignore new file mode 100644 index 0000000000..eb372fc719 --- /dev/null +++ b/play-framework/student-api/.gitignore @@ -0,0 +1,8 @@ +logs +target +/.idea +/.idea_modules +/.classpath +/.project +/.settings +/RUNNING_PID diff --git a/play-framework/student-api/LICENSE b/play-framework/student-api/LICENSE new file mode 100644 index 0000000000..4baedcb95f --- /dev/null +++ b/play-framework/student-api/LICENSE @@ -0,0 +1,8 @@ +This software is licensed under the Apache 2 license, quoted below. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with +the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific +language governing permissions and limitations under the License. \ No newline at end of file diff --git a/play-framework/student-api/README b/play-framework/student-api/README new file mode 100644 index 0000000000..f21d092edf --- /dev/null +++ b/play-framework/student-api/README @@ -0,0 +1,49 @@ +This is your new Play application +================================= + +This file will be packaged with your application when using `activator dist`. + +There are several demonstration files available in this template. + +Controllers +=========== + +- HomeController.java: + + Shows how to handle simple HTTP requests. + +- AsyncController.java: + + Shows how to do asynchronous programming when handling a request. + +- CountController.java: + + Shows how to inject a component into a controller and use the component when + handling requests. + +Components +========== + +- Module.java: + + Shows how to use Guice to bind all the components needed by your application. + +- Counter.java: + + An example of a component that contains state, in this case a simple counter. + +- ApplicationTimer.java: + + An example of a component that starts when the application starts and stops + when the application stops. + +Filters +======= + +- Filters.java: + + Creates the list of HTTP filters used by your application. + +- ExampleFilter.java + + A simple filter that adds a header to every response. \ No newline at end of file diff --git a/play-framework/student-api/app/Filters.java b/play-framework/student-api/app/Filters.java new file mode 100644 index 0000000000..255de8ca93 --- /dev/null +++ b/play-framework/student-api/app/Filters.java @@ -0,0 +1,46 @@ +import javax.inject.*; +import play.*; +import play.mvc.EssentialFilter; +import play.http.HttpFilters; +import play.mvc.*; + +import filters.ExampleFilter; + +/** + * This class configures filters that run on every request. This + * class is queried by Play to get a list of filters. + * + * Play will automatically use filters from any class called + * Filters that is placed the root package. You can load filters + * from a different class by adding a `play.http.filters` setting to + * the application.conf configuration file. + */ +@Singleton +public class Filters implements HttpFilters { + + private final Environment env; + private final EssentialFilter exampleFilter; + + /** + * @param env Basic environment settings for the current application. + * @param exampleFilter A demonstration filter that adds a header to + */ + @Inject + public Filters(Environment env, ExampleFilter exampleFilter) { + this.env = env; + this.exampleFilter = exampleFilter; + } + + @Override + public EssentialFilter[] filters() { + // Use the example filter if we're running development mode. If + // we're running in production or test mode then don't use any + // filters at all. + if (env.mode().equals(Mode.DEV)) { + return new EssentialFilter[] { exampleFilter }; + } else { + return new EssentialFilter[] {}; + } + } + +} diff --git a/play-framework/student-api/app/Module.java b/play-framework/student-api/app/Module.java new file mode 100644 index 0000000000..6e7d1766ef --- /dev/null +++ b/play-framework/student-api/app/Module.java @@ -0,0 +1,31 @@ +import com.google.inject.AbstractModule; +import java.time.Clock; + +import services.ApplicationTimer; +import services.AtomicCounter; +import services.Counter; + +/** + * This class is a Guice module that tells Guice how to bind several + * different types. This Guice module is created when the Play + * application starts. + * + * Play will automatically use any class called `Module` that is in + * the root package. You can create modules in other locations by + * adding `play.modules.enabled` settings to the `application.conf` + * configuration file. + */ +public class Module extends AbstractModule { + + @Override + public void configure() { + // Use the system clock as the default implementation of Clock + bind(Clock.class).toInstance(Clock.systemDefaultZone()); + // Ask Guice to create an instance of ApplicationTimer when the + // application starts. + bind(ApplicationTimer.class).asEagerSingleton(); + // Set AtomicCounter as the implementation for Counter. + bind(Counter.class).to(AtomicCounter.class); + } + +} diff --git a/play-framework/student-api/app/controllers/AsyncController.java b/play-framework/student-api/app/controllers/AsyncController.java new file mode 100644 index 0000000000..92c84bb755 --- /dev/null +++ b/play-framework/student-api/app/controllers/AsyncController.java @@ -0,0 +1,64 @@ +package controllers; + +import akka.actor.ActorSystem; + +import javax.inject.*; + +import play.*; +import play.mvc.*; + +import java.util.concurrent.Executor; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.TimeUnit; + +import scala.concurrent.duration.Duration; +import scala.concurrent.ExecutionContextExecutor; + +/** + * This controller contains an action that demonstrates how to write + * simple asynchronous code in a controller. It uses a timer to + * asynchronously delay sending a response for 1 second. + * + * @param actorSystem We need the {@link ActorSystem}'s + * {@link Scheduler} to run code after a delay. + * @param exec We need a Java {@link Executor} to apply the result + * of the {@link CompletableFuture} and a Scala + * {@link ExecutionContext} so we can use the Akka {@link Scheduler}. + * An {@link ExecutionContextExecutor} implements both interfaces. + */ +@Singleton +public class AsyncController extends Controller { + + private final ActorSystem actorSystem; + private final ExecutionContextExecutor exec; + + @Inject + public AsyncController(ActorSystem actorSystem, ExecutionContextExecutor exec) { + this.actorSystem = actorSystem; + this.exec = exec; + } + + /** + * An action that returns a plain text message after a delay + * of 1 second. + *

    + * The configuration in the routes file means that this method + * will be called when the application receives a GET request with + * a path of /message. + */ + public CompletionStage message() { + return getFutureMessage(1, TimeUnit.SECONDS).thenApplyAsync(Results::ok, exec); + } + + private CompletionStage getFutureMessage(long time, TimeUnit timeUnit) { + CompletableFuture future = new CompletableFuture<>(); + actorSystem.scheduler().scheduleOnce( + Duration.create(time, timeUnit), + () -> future.complete("Hi!"), + exec + ); + return future; + } + +} diff --git a/play-framework/student-api/app/controllers/CountController.java b/play-framework/student-api/app/controllers/CountController.java new file mode 100644 index 0000000000..02fcb15f8e --- /dev/null +++ b/play-framework/student-api/app/controllers/CountController.java @@ -0,0 +1,35 @@ +package controllers; + +import javax.inject.*; +import play.*; +import play.mvc.*; + +import services.Counter; + +/** + * This controller demonstrates how to use dependency injection to + * bind a component into a controller class. The class contains an + * action that shows an incrementing count to users. The {@link Counter} + * object is injected by the Guice dependency injection system. + */ +@Singleton +public class CountController extends Controller { + + private final Counter counter; + + @Inject + public CountController(Counter counter) { + this.counter = counter; + } + + /** + * An action that responds with the {@link Counter}'s current + * count. The result is plain text. This action is mapped to + * GET requests with a path of /count + * requests by an entry in the routes config file. + */ + public Result count() { + return ok(Integer.toString(counter.nextCount())); + } + +} diff --git a/play-framework/student-api/app/controllers/HomeController.java b/play-framework/student-api/app/controllers/HomeController.java new file mode 100644 index 0000000000..6a79856eb4 --- /dev/null +++ b/play-framework/student-api/app/controllers/HomeController.java @@ -0,0 +1,23 @@ +package controllers; + +import play.mvc.*; + +import views.html.*; + +/** + * This controller contains an action to handle HTTP requests + * to the application's home page. + */ +public class HomeController extends Controller { + + /** + * An action that renders an HTML page with a welcome message. + * The configuration in the routes file means that + * this method will be called when the application receives a + * GET request with a path of /. + */ + public Result index() { + return ok(index.render("Your new application is ready.")); + } + +} diff --git a/play-framework/student-api/app/controllers/StudentController.java b/play-framework/student-api/app/controllers/StudentController.java new file mode 100644 index 0000000000..8b759b9598 --- /dev/null +++ b/play-framework/student-api/app/controllers/StudentController.java @@ -0,0 +1,63 @@ +package controllers; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import models.Student; +import models.StudentStore; +import play.libs.Json; +import play.mvc.Controller; +import play.mvc.Result; +import util.Util; + +import java.util.Set; + +public class StudentController extends Controller { + public Result create() { + JsonNode json = request().body().asJson(); + if (json == null) { + return badRequest(Util.createResponse("Expecting Json data", false)); + } + Student student = StudentStore.getInstance().addStudent(Json.fromJson(json, Student.class)); + JsonNode jsonObject = Json.toJson(student); + return created(Util.createResponse(jsonObject, true)); + } + + public Result update() { + JsonNode json = request().body().asJson(); + if (json == null) { + return badRequest(Util.createResponse("Expecting Json data", false)); + } + Student student = StudentStore.getInstance().updateStudent(Json.fromJson(json, Student.class)); + if (student == null) { + return notFound(Util.createResponse("Student not found", false)); + } + + JsonNode jsonObject = Json.toJson(student); + return ok(Util.createResponse(jsonObject, true)); + } + + public Result retrieve(int id) { + if (StudentStore.getInstance().getStudent(id) == null) { + return notFound(Util.createResponse("Student with id:" + id + " not found", false)); + } + JsonNode jsonObjects = Json.toJson(StudentStore.getInstance().getStudent(id)); + return ok(Util.createResponse(jsonObjects, true)); + } + + public Result listStudents() { + Set result = StudentStore.getInstance().getAllStudents(); + ObjectMapper mapper = new ObjectMapper(); + + JsonNode jsonData = mapper.convertValue(result, JsonNode.class); + return ok(Util.createResponse(jsonData, true)); + + } + + public Result delete(int id) { + if (!StudentStore.getInstance().deleteStudent(id)) { + return notFound(Util.createResponse("Student with id:" + id + " not found", false)); + } + return ok(Util.createResponse("Student with id:" + id + " deleted", true)); + } + +} diff --git a/play-framework/student-api/app/filters/ExampleFilter.java b/play-framework/student-api/app/filters/ExampleFilter.java new file mode 100644 index 0000000000..67a6a36cc3 --- /dev/null +++ b/play-framework/student-api/app/filters/ExampleFilter.java @@ -0,0 +1,45 @@ +package filters; + +import akka.stream.Materializer; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Executor; +import java.util.function.Function; +import javax.inject.*; +import play.mvc.*; +import play.mvc.Http.RequestHeader; + + +/** + * This is a simple filter that adds a header to all requests. It's + * added to the application's list of filters by the + * {@link Filters} class. + */ +@Singleton +public class ExampleFilter extends Filter { + + private final Executor exec; + + /** + * @param mat This object is needed to handle streaming of requests + * and responses. + * @param exec This class is needed to execute code asynchronously. + * It is used below by the thenAsyncApply method. + */ + @Inject + public ExampleFilter(Materializer mat, Executor exec) { + super(mat); + this.exec = exec; + } + + @Override + public CompletionStage apply( + Function> next, + RequestHeader requestHeader) { + + return next.apply(requestHeader).thenApplyAsync( + result -> result.withHeader("X-ExampleFilter", "foo"), + exec + ); + } + +} diff --git a/play-framework/student-api/app/models/Student.java b/play-framework/student-api/app/models/Student.java new file mode 100644 index 0000000000..dc539767bd --- /dev/null +++ b/play-framework/student-api/app/models/Student.java @@ -0,0 +1,47 @@ +package models; +public class Student { + private String firstName; + private String lastName; + private int age; + private int id; + public Student(){} + public Student(String firstName, String lastName, int age) { + super(); + this.firstName = firstName; + this.lastName = lastName; + this.age = age; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + +} diff --git a/play-framework/student-api/app/models/StudentStore.java b/play-framework/student-api/app/models/StudentStore.java new file mode 100644 index 0000000000..add6a5dbd6 --- /dev/null +++ b/play-framework/student-api/app/models/StudentStore.java @@ -0,0 +1,46 @@ +package models; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class StudentStore { + private static StudentStore instance; + private Map students = new HashMap<>(); + + public static StudentStore getInstance() { + if (instance == null) { + instance = new StudentStore(); + } + return instance; + } + + public Student addStudent(Student student) { + int id = students.size(); + student.setId(id); + students.put(id, student); + return student; + } + + public Student getStudent(int id) { + return students.get(id); + } + + public Set getAllStudents() { + return new HashSet<>(students.values()); + } + + public Student updateStudent(Student student) { + int id = student.getId(); + if (students.containsKey(id)) { + students.put(id, student); + return student; + } + return null; + } + + public boolean deleteStudent(int id) { + return students.remove(id) != null; + } +} \ No newline at end of file diff --git a/play-framework/student-api/app/services/ApplicationTimer.java b/play-framework/student-api/app/services/ApplicationTimer.java new file mode 100644 index 0000000000..a951562b1d --- /dev/null +++ b/play-framework/student-api/app/services/ApplicationTimer.java @@ -0,0 +1,50 @@ +package services; + +import java.time.Clock; +import java.time.Instant; +import java.util.concurrent.CompletableFuture; +import javax.inject.*; +import play.Logger; +import play.inject.ApplicationLifecycle; + +/** + * This class demonstrates how to run code when the + * application starts and stops. It starts a timer when the + * application starts. When the application stops it prints out how + * long the application was running for. + * + * This class is registered for Guice dependency injection in the + * {@link Module} class. We want the class to start when the application + * starts, so it is registered as an "eager singleton". See the code + * in the {@link Module} class to see how this happens. + * + * This class needs to run code when the server stops. It uses the + * application's {@link ApplicationLifecycle} to register a stop hook. + */ +@Singleton +public class ApplicationTimer { + + private final Clock clock; + private final ApplicationLifecycle appLifecycle; + private final Instant start; + + @Inject + public ApplicationTimer(Clock clock, ApplicationLifecycle appLifecycle) { + this.clock = clock; + this.appLifecycle = appLifecycle; + // This code is called when the application starts. + start = clock.instant(); + Logger.info("ApplicationTimer demo: Starting application at " + start); + + // When the application starts, register a stop hook with the + // ApplicationLifecycle object. The code inside the stop hook will + // be run when the application stops. + appLifecycle.addStopHook(() -> { + Instant stop = clock.instant(); + Long runningTime = stop.getEpochSecond() - start.getEpochSecond(); + Logger.info("ApplicationTimer demo: Stopping application at " + clock.instant() + " after " + runningTime + "s."); + return CompletableFuture.completedFuture(null); + }); + } + +} diff --git a/play-framework/student-api/app/services/AtomicCounter.java b/play-framework/student-api/app/services/AtomicCounter.java new file mode 100644 index 0000000000..41f741cbf7 --- /dev/null +++ b/play-framework/student-api/app/services/AtomicCounter.java @@ -0,0 +1,26 @@ +package services; + +import java.util.concurrent.atomic.AtomicInteger; +import javax.inject.*; + +/** + * This class is a concrete implementation of the {@link Counter} trait. + * It is configured for Guice dependency injection in the {@link Module} + * class. + * + * This class has a {@link Singleton} annotation because we need to make + * sure we only use one counter per application. Without this + * annotation we would get a new instance every time a {@link Counter} is + * injected. + */ +@Singleton +public class AtomicCounter implements Counter { + + private final AtomicInteger atomicCounter = new AtomicInteger(); + + @Override + public int nextCount() { + return atomicCounter.getAndIncrement(); + } + +} diff --git a/play-framework/student-api/app/services/Counter.java b/play-framework/student-api/app/services/Counter.java new file mode 100644 index 0000000000..dadad8b09d --- /dev/null +++ b/play-framework/student-api/app/services/Counter.java @@ -0,0 +1,13 @@ +package services; + +/** + * This interface demonstrates how to create a component that is injected + * into a controller. The interface represents a counter that returns a + * incremented number each time it is called. + * + * The {@link Modules} class binds this interface to the + * {@link AtomicCounter} implementation. + */ +public interface Counter { + int nextCount(); +} diff --git a/play-framework/student-api/app/util/Util.java b/play-framework/student-api/app/util/Util.java new file mode 100644 index 0000000000..a853a4cb43 --- /dev/null +++ b/play-framework/student-api/app/util/Util.java @@ -0,0 +1,17 @@ +package util; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import play.libs.Json; + +public class Util { + public static ObjectNode createResponse(Object response, boolean ok) { + ObjectNode result = Json.newObject(); + result.put("isSuccessfull", ok); + if (response instanceof String) + result.put("body", (String) response); + else result.put("body", (JsonNode) response); + + return result; + } +} \ No newline at end of file diff --git a/play-framework/student-api/app/views/index.scala.html b/play-framework/student-api/app/views/index.scala.html new file mode 100644 index 0000000000..4539f5a10b --- /dev/null +++ b/play-framework/student-api/app/views/index.scala.html @@ -0,0 +1,20 @@ +@* + * This template takes a single argument, a String containing a + * message to display. + *@ +@(message: String) + +@* + * Call the `main` template with two arguments. The first + * argument is a `String` with the title of the page, the second + * argument is an `Html` object containing the body of the page. + *@ +@main("Welcome to Play") { + + @* + * Get an `Html` object by calling the built-in Play welcome + * template and passing a `String` message. + *@ + @play20.welcome(message, style = "Java") + +} diff --git a/play-framework/student-api/app/views/main.scala.html b/play-framework/student-api/app/views/main.scala.html new file mode 100644 index 0000000000..9414f4be6e --- /dev/null +++ b/play-framework/student-api/app/views/main.scala.html @@ -0,0 +1,23 @@ +@* + * This template is called from the `index` template. This template + * handles the rendering of the page header and body tags. It takes + * two arguments, a `String` for the title of the page and an `Html` + * object to insert into the body of the page. + *@ +@(title: String)(content: Html) + + + + + @* Here's where we render the page title `String`. *@ + @title + + + + + + @* And here's where we render the `Html` object containing + * the page content. *@ + @content + + diff --git a/play-framework/student-api/bin/activator b/play-framework/student-api/bin/activator new file mode 100644 index 0000000000..a8b11d482f --- /dev/null +++ b/play-framework/student-api/bin/activator @@ -0,0 +1,397 @@ +#!/usr/bin/env bash + +### ------------------------------- ### +### Helper methods for BASH scripts ### +### ------------------------------- ### + +realpath () { +( + TARGET_FILE="$1" + FIX_CYGPATH="$2" + + cd "$(dirname "$TARGET_FILE")" + TARGET_FILE=$(basename "$TARGET_FILE") + + COUNT=0 + while [ -L "$TARGET_FILE" -a $COUNT -lt 100 ] + do + TARGET_FILE=$(readlink "$TARGET_FILE") + cd "$(dirname "$TARGET_FILE")" + TARGET_FILE=$(basename "$TARGET_FILE") + COUNT=$(($COUNT + 1)) + done + + # make sure we grab the actual windows path, instead of cygwin's path. + if [[ "x$FIX_CYGPATH" != "x" ]]; then + echo "$(cygwinpath "$(pwd -P)/$TARGET_FILE")" + else + echo "$(pwd -P)/$TARGET_FILE" + fi +) +} + + +# Uses uname to detect if we're in the odd cygwin environment. +is_cygwin() { + local os=$(uname -s) + case "$os" in + CYGWIN*) return 0 ;; + *) return 1 ;; + esac +} + +# TODO - Use nicer bash-isms here. +CYGWIN_FLAG=$(if is_cygwin; then echo true; else echo false; fi) + + +# This can fix cygwin style /cygdrive paths so we get the +# windows style paths. +cygwinpath() { + local file="$1" + if [[ "$CYGWIN_FLAG" == "true" ]]; then + echo $(cygpath -w $file) + else + echo $file + fi +} + +# Make something URI friendly +make_url() { + url="$1" + local nospaces=${url// /%20} + if is_cygwin; then + echo "/${nospaces//\\//}" + else + echo "$nospaces" + fi +} + +declare -a residual_args +declare -a java_args +declare -a scalac_args +declare -a sbt_commands +declare java_cmd=java +declare java_version +declare -r real_script_path="$(realpath "$0")" +declare -r sbt_home="$(realpath "$(dirname "$(dirname "$real_script_path")")")" +declare -r sbt_bin_dir="$(dirname "$real_script_path")" +declare -r app_version="1.3.10" + +declare -r script_name=activator +declare -r java_opts=( "${ACTIVATOR_OPTS[@]}" "${SBT_OPTS[@]}" "${JAVA_OPTS[@]}" "${java_opts[@]}" ) +userhome="$HOME" +if is_cygwin; then + # cygwin sets home to something f-d up, set to real windows homedir + userhome="$USERPROFILE" +fi +declare -r activator_user_home_dir="${userhome}/.activator" +declare -r java_opts_config_home="${activator_user_home_dir}/activatorconfig.txt" +declare -r java_opts_config_version="${activator_user_home_dir}/${app_version}/activatorconfig.txt" + +echoerr () { + echo 1>&2 "$@" +} +vlog () { + [[ $verbose || $debug ]] && echoerr "$@" +} +dlog () { + [[ $debug ]] && echoerr "$@" +} + +jar_file () { + echo "$(cygwinpath "${sbt_home}/libexec/activator-launch-${app_version}.jar")" +} + +acquire_sbt_jar () { + sbt_jar="$(jar_file)" + + if [[ ! -f "$sbt_jar" ]]; then + echoerr "Could not find launcher jar: $sbt_jar" + exit 2 + fi +} + +execRunner () { + # print the arguments one to a line, quoting any containing spaces + [[ $verbose || $debug ]] && echo "# Executing command line:" && { + for arg; do + if printf "%s\n" "$arg" | grep -q ' '; then + printf "\"%s\"\n" "$arg" + else + printf "%s\n" "$arg" + fi + done + echo "" + } + + # THis used to be exec, but we loose the ability to re-hook stty then + # for cygwin... Maybe we should flag the feature here... + "$@" +} + +addJava () { + dlog "[addJava] arg = '$1'" + java_args=( "${java_args[@]}" "$1" ) +} +addSbt () { + dlog "[addSbt] arg = '$1'" + sbt_commands=( "${sbt_commands[@]}" "$1" ) +} +addResidual () { + dlog "[residual] arg = '$1'" + residual_args=( "${residual_args[@]}" "$1" ) +} +addDebugger () { + addJava "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$1" +} + +get_mem_opts () { + # if we detect any of these settings in ${JAVA_OPTS} we need to NOT output our settings. + # The reason is the Xms/Xmx, if they don't line up, cause errors. + if [[ "${JAVA_OPTS}" == *-Xmx* ]] || [[ "${JAVA_OPTS}" == *-Xms* ]] || [[ "${JAVA_OPTS}" == *-XX:MaxPermSize* ]] || [[ "${JAVA_OPTS}" == *-XX:MaxMetaspaceSize* ]] || [[ "${JAVA_OPTS}" == *-XX:ReservedCodeCacheSize* ]]; then + echo "" + else + # a ham-fisted attempt to move some memory settings in concert + # so they need not be messed around with individually. + local mem=${1:-1024} + local codecache=$(( $mem / 8 )) + (( $codecache > 128 )) || codecache=128 + (( $codecache < 512 )) || codecache=512 + local class_metadata_size=$(( $codecache * 2 )) + local class_metadata_opt=$([[ "$java_version" < "1.8" ]] && echo "MaxPermSize" || echo "MaxMetaspaceSize") + + echo "-Xms${mem}m -Xmx${mem}m -XX:ReservedCodeCacheSize=${codecache}m -XX:${class_metadata_opt}=${class_metadata_size}m" + fi +} + +require_arg () { + local type="$1" + local opt="$2" + local arg="$3" + if [[ -z "$arg" ]] || [[ "${arg:0:1}" == "-" ]]; then + echo "$opt requires <$type> argument" + exit 1 + fi +} + +is_function_defined() { + declare -f "$1" > /dev/null +} + +# If we're *not* running in a terminal, and we don't have any arguments, then we need to add the 'ui' parameter +detect_terminal_for_ui() { + [[ ! -t 0 ]] && [[ "${#residual_args}" == "0" ]] && { + addResidual "ui" + } + # SPECIAL TEST FOR MAC + [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]] && [[ "${#residual_args}" == "0" ]] && { + echo "Detected MAC OSX launched script...." + echo "Swapping to UI" + addResidual "ui" + } +} + +process_args () { + while [[ $# -gt 0 ]]; do + case "$1" in + -h|-help) usage; exit 1 ;; + -v|-verbose) verbose=1 && shift ;; + -d|-debug) debug=1 && shift ;; + + -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; + -mem) require_arg integer "$1" "$2" && sbt_mem="$2" && shift 2 ;; + -jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;; + -batch) exec &1 | awk -F '"' '/version/ {print $2}') + vlog "[process_args] java_version = '$java_version'" +} + +# Detect that we have java installed. +checkJava() { + local required_version="$1" + # Now check to see if it's a good enough version + if [[ "$java_version" == "" ]]; then + echo + echo No java installations was detected. + echo Please go to http://www.java.com/getjava/ and download + echo + exit 1 + elif [[ ! "$java_version" > "$required_version" ]]; then + echo + echo The java installation you have is not up to date + echo $script_name requires at least version $required_version+, you have + echo version $java_version + echo + echo Please go to http://www.java.com/getjava/ and download + echo a valid Java Runtime and install before running $script_name. + echo + exit 1 + fi +} + + +run() { + # no jar? download it. + [[ -f "$sbt_jar" ]] || acquire_sbt_jar "$sbt_version" || { + # still no jar? uh-oh. + echo "Download failed. Obtain the sbt-launch.jar manually and place it at $sbt_jar" + exit 1 + } + + # process the combined args, then reset "$@" to the residuals + process_args "$@" + detect_terminal_for_ui + set -- "${residual_args[@]}" + argumentCount=$# + + # TODO - java check should be configurable... + checkJava "1.6" + + #If we're in cygwin, we should use the windows config, and terminal hacks + if [[ "$CYGWIN_FLAG" == "true" ]]; then + stty -icanon min 1 -echo > /dev/null 2>&1 + addJava "-Djline.terminal=jline.UnixTerminal" + addJava "-Dsbt.cygwin=true" + fi + + # run sbt + execRunner "$java_cmd" \ + "-Dactivator.home=$(make_url "$sbt_home")" \ + ${SBT_OPTS:-$default_sbt_opts} \ + $(get_mem_opts $sbt_mem) \ + ${JAVA_OPTS} \ + ${java_args[@]} \ + -jar "$sbt_jar" \ + "${sbt_commands[@]}" \ + "${residual_args[@]}" + + exit_code=$? + + # Clean up the terminal from cygwin hacks. + if [[ "$CYGWIN_FLAG" == "true" ]]; then + stty icanon echo > /dev/null 2>&1 + fi + exit $exit_code +} + + +declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy" +declare -r sbt_opts_file=".sbtopts" +declare -r etc_sbt_opts_file="${sbt_home}/conf/sbtopts" +declare -r win_sbt_opts_file="${sbt_home}/conf/sbtconfig.txt" + +usage() { + cat < path to global settings/plugins directory (default: ~/.sbt) + -sbt-boot path to shared boot directory (default: ~/.sbt/boot in 0.11 series) + -ivy path to local Ivy repository (default: ~/.ivy2) + -mem set memory options (default: $sbt_mem, which is $(get_mem_opts $sbt_mem)) + -no-share use all local caches; no sharing + -no-global uses global caches, but does not use global ~/.sbt directory. + -jvm-debug Turn on JVM debugging, open at the given port. + -batch Disable interactive mode + + # sbt version (default: from project/build.properties if present, else latest release) + -sbt-version use the specified version of sbt + -sbt-jar use the specified jar as the sbt launcher + -sbt-rc use an RC version of sbt + -sbt-snapshot use a snapshot version of sbt + + # java version (default: java from PATH, currently $(java -version 2>&1 | grep version)) + -java-home alternate JAVA_HOME + + # jvm options and output control + JAVA_OPTS environment variable, if unset uses "$java_opts" + SBT_OPTS environment variable, if unset uses "$default_sbt_opts" + ACTIVATOR_OPTS Environment variable, if unset uses "" + .sbtopts if this file exists in the current directory, it is + prepended to the runner args + /etc/sbt/sbtopts if this file exists, it is prepended to the runner args + -Dkey=val pass -Dkey=val directly to the java runtime + -J-X pass option -X directly to the java runtime + (-J is stripped) + -S-X add -X to sbt's scalacOptions (-S is stripped) + +In the case of duplicated or conflicting options, the order above +shows precedence: JAVA_OPTS lowest, command line options highest. +EOM +} + + + +process_my_args () { + while [[ $# -gt 0 ]]; do + case "$1" in + -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;; + -no-share) addJava "$noshare_opts" && shift ;; + -no-global) addJava "-Dsbt.global.base=$(pwd)/project/.sbtboot" && shift ;; + -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; + -sbt-dir) require_arg path "$1" "$2" && addJava "-Dsbt.global.base=$2" && shift 2 ;; + -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; + -batch) exec ^&1') do ( + if %%~j==java set JAVAINSTALLED=1 + if %%~j==openjdk set JAVAINSTALLED=1 +) + +rem Detect the same thing about javac +if "%_JAVACCMD%"=="" ( + if not "%JAVA_HOME%"=="" ( + if exist "%JAVA_HOME%\bin\javac.exe" set "_JAVACCMD=%JAVA_HOME%\bin\javac.exe" + ) +) +if "%_JAVACCMD%"=="" set _JAVACCMD=javac +for /F %%j in ('"%_JAVACCMD%" -version 2^>^&1') do ( + if %%~j==javac set JAVACINSTALLED=1 +) + +rem BAT has no logical or, so we do it OLD SCHOOL! Oppan Redmond Style +set JAVAOK=true +if not defined JAVAINSTALLED set JAVAOK=false +if not defined JAVACINSTALLED set JAVAOK=false + +if "%JAVAOK%"=="false" ( + echo. + echo A Java JDK is not installed or can't be found. + if not "%JAVA_HOME%"=="" ( + echo JAVA_HOME = "%JAVA_HOME%" + ) + echo. + echo Please go to + echo http://www.oracle.com/technetwork/java/javase/downloads/index.html + echo and download a valid Java JDK and install before running Activator. + echo. + echo If you think this message is in error, please check + echo your environment variables to see if "java.exe" and "javac.exe" are + echo available via JAVA_HOME or PATH. + echo. + if defined DOUBLECLICKED pause + exit /B 1 +) + +rem Check what Java version is being used to determine what memory options to use +for /f "tokens=3" %%g in ('java -version 2^>^&1 ^| findstr /i "version"') do ( + set JAVA_VERSION=%%g +) + +rem Strips away the " characters +set JAVA_VERSION=%JAVA_VERSION:"=% + +rem TODO Check if there are existing mem settings in JAVA_OPTS/CFG_OPTS and use those instead of the below +for /f "delims=. tokens=1-3" %%v in ("%JAVA_VERSION%") do ( + set MAJOR=%%v + set MINOR=%%w + set BUILD=%%x + + set META_SIZE=-XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=256M + if "!MINOR!" LSS "8" ( + set META_SIZE=-XX:PermSize=64M -XX:MaxPermSize=256M + ) + + set MEM_OPTS=!META_SIZE! + ) + +rem We use the value of the JAVA_OPTS environment variable if defined, rather than the config. +set _JAVA_OPTS=%JAVA_OPTS% +if "%_JAVA_OPTS%"=="" set _JAVA_OPTS=%CFG_OPTS% + +set DEBUG_OPTS= + +rem Loop through the arguments, building remaining args in args variable +set args= +:argsloop +if not "%~1"=="" ( + rem Checks if the argument contains "-D" and if true, adds argument 1 with 2 and puts an equal sign between them. + rem This is done since batch considers "=" to be a delimiter so we need to circumvent this behavior with a small hack. + set arg1=%~1 + if "!arg1:~0,2!"=="-D" ( + set "args=%args% "%~1"="%~2"" + shift + shift + goto argsloop + ) + + if "%~1"=="-jvm-debug" ( + if not "%~2"=="" ( + rem This piece of magic somehow checks that an argument is a number + for /F "delims=0123456789" %%i in ("%~2") do ( + set var="%%i" + ) + if defined var ( + rem Not a number, assume no argument given and default to 9999 + set JPDA_PORT=9999 + ) else ( + rem Port was given, shift arguments + set JPDA_PORT=%~2 + shift + ) + ) else ( + set JPDA_PORT=9999 + ) + shift + + set DEBUG_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=!JPDA_PORT! + goto argsloop + ) + rem else + set "args=%args% "%~1"" + shift + goto argsloop +) + +:run + +if "!args!"=="" ( + if defined DOUBLECLICKED ( + set CMDS="ui" + ) else set CMDS=!args! +) else set CMDS=!args! + +rem We add a / in front, so we get file:///C: instead of file://C: +rem Java considers the later a UNC path. +rem We also attempt a solid effort at making it URI friendly. +rem We don't even bother with UNC paths. +set JAVA_FRIENDLY_HOME_1=/!ACTIVATOR_HOME:\=/! +set JAVA_FRIENDLY_HOME=/!JAVA_FRIENDLY_HOME_1: =%%20! + +rem Checks if the command contains spaces to know if it should be wrapped in quotes or not +set NON_SPACED_CMD=%_JAVACMD: =% +if "%_JAVACMD%"=="%NON_SPACED_CMD%" %_JAVACMD% %DEBUG_OPTS% %MEM_OPTS% %ACTIVATOR_OPTS% %SBT_OPTS% %_JAVA_OPTS% "-Dactivator.home=%JAVA_FRIENDLY_HOME%" -jar "%ACTIVATOR_HOME%\libexec\%ACTIVATOR_LAUNCH_JAR%" %CMDS% +if NOT "%_JAVACMD%"=="%NON_SPACED_CMD%" "%_JAVACMD%" %DEBUG_OPTS% %MEM_OPTS% %ACTIVATOR_OPTS% %SBT_OPTS% %_JAVA_OPTS% "-Dactivator.home=%JAVA_FRIENDLY_HOME%" -jar "%ACTIVATOR_HOME%\libexec\%ACTIVATOR_LAUNCH_JAR%" %CMDS% + +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end + +@endlocal + +exit /B %ERROR_CODE% diff --git a/play-framework/student-api/build.sbt b/play-framework/student-api/build.sbt new file mode 100644 index 0000000000..0f5ea736f6 --- /dev/null +++ b/play-framework/student-api/build.sbt @@ -0,0 +1,13 @@ +name := """student-api""" + +version := "1.0-SNAPSHOT" + +lazy val root = (project in file(".")).enablePlugins(PlayJava) + +scalaVersion := "2.11.7" + +libraryDependencies ++= Seq( + javaJdbc, + cache, + javaWs +) diff --git a/play-framework/student-api/conf/application.conf b/play-framework/student-api/conf/application.conf new file mode 100644 index 0000000000..489d3f9b3e --- /dev/null +++ b/play-framework/student-api/conf/application.conf @@ -0,0 +1,353 @@ +# This is the main configuration file for the application. +# https://www.playframework.com/documentation/latest/ConfigFile +# ~~~~~ +# Play uses HOCON as its configuration file format. HOCON has a number +# of advantages over other config formats, but there are two things that +# can be used when modifying settings. +# +# You can include other configuration files in this main application.conf file: +#include "extra-config.conf" +# +# You can declare variables and substitute for them: +#mykey = ${some.value} +# +# And if an environment variable exists when there is no other subsitution, then +# HOCON will fall back to substituting environment variable: +#mykey = ${JAVA_HOME} + +## Akka +# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration +# https://www.playframework.com/documentation/latest/JavaAkka#Configuration +# ~~~~~ +# Play uses Akka internally and exposes Akka Streams and actors in Websockets and +# other streaming HTTP responses. +akka { + # "akka.log-config-on-start" is extraordinarly useful because it log the complete + # configuration at INFO level, including defaults and overrides, so it s worth + # putting at the very top. + # + # Put the following in your conf/logback.xml file: + # + # + # + # And then uncomment this line to debug the configuration. + # + #log-config-on-start = true +} + +## Secret key +# http://www.playframework.com/documentation/latest/ApplicationSecret +# ~~~~~ +# The secret key is used to sign Play's session cookie. +# This must be changed for production, but we don't recommend you change it in this file. +play.crypto.secret = "changeme" + +## Modules +# https://www.playframework.com/documentation/latest/Modules +# ~~~~~ +# Control which modules are loaded when Play starts. Note that modules are +# the replacement for "GlobalSettings", which are deprecated in 2.5.x. +# Please see https://www.playframework.com/documentation/latest/GlobalSettings +# for more information. +# +# You can also extend Play functionality by using one of the publically available +# Play modules: https://playframework.com/documentation/latest/ModuleDirectory +play.modules { + # By default, Play will load any class called Module that is defined + # in the root package (the "app" directory), or you can define them + # explicitly below. + # If there are any built-in modules that you want to disable, you can list them here. + #enabled += my.application.Module + + # If there are any built-in modules that you want to disable, you can list them here. + #disabled += "" +} + +## IDE +# https://www.playframework.com/documentation/latest/IDE +# ~~~~~ +# Depending on your IDE, you can add a hyperlink for errors that will jump you +# directly to the code location in the IDE in dev mode. The following line makes +# use of the IntelliJ IDEA REST interface: +#play.editor="http://localhost:63342/api/file/?file=%s&line=%s" + +## Internationalisation +# https://www.playframework.com/documentation/latest/JavaI18N +# https://www.playframework.com/documentation/latest/ScalaI18N +# ~~~~~ +# Play comes with its own i18n settings, which allow the user's preferred language +# to map through to internal messages, or allow the language to be stored in a cookie. +play.i18n { + # The application languages + langs = [ "en" ] + + # Whether the language cookie should be secure or not + #langCookieSecure = true + + # Whether the HTTP only attribute of the cookie should be set to true + #langCookieHttpOnly = true +} + +## Play HTTP settings +# ~~~~~ +play.http { + ## Router + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # Define the Router object to use for this application. + # This router will be looked up first when the application is starting up, + # so make sure this is the entry point. + # Furthermore, it's assumed your route file is named properly. + # So for an application router like `my.application.Router`, + # you may need to define a router file `conf/my.application.routes`. + # Default to Routes in the root package (aka "apps" folder) (and conf/routes) + #router = my.application.Router + + ## Action Creator + # https://www.playframework.com/documentation/latest/JavaActionCreator + # ~~~~~ + #actionCreator = null + + ## ErrorHandler + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # If null, will attempt to load a class called ErrorHandler in the root package, + #errorHandler = null + + ## Filters + # https://www.playframework.com/documentation/latest/ScalaHttpFilters + # https://www.playframework.com/documentation/latest/JavaHttpFilters + # ~~~~~ + # Filters run code on every request. They can be used to perform + # common logic for all your actions, e.g. adding common headers. + # Defaults to "Filters" in the root package (aka "apps" folder) + # Alternatively you can explicitly register a class here. + #filters = my.application.Filters + + ## Session & Flash + # https://www.playframework.com/documentation/latest/JavaSessionFlash + # https://www.playframework.com/documentation/latest/ScalaSessionFlash + # ~~~~~ + session { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + + # Sets the max-age field of the cookie to 5 minutes. + # NOTE: this only sets when the browser will discard the cookie. Play will consider any + # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout, + # you need to put a timestamp in the session and check it at regular intervals to possibly expire it. + #maxAge = 300 + + # Sets the domain on the session cookie. + #domain = "example.com" + } + + flash { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + } +} + +## Netty Provider +# https://www.playframework.com/documentation/latest/SettingsNetty +# ~~~~~ +play.server.netty { + # Whether the Netty wire should be logged + #log.wire = true + + # If you run Play on Linux, you can use Netty's native socket transport + # for higher performance with less garbage. + #transport = "native" +} + +## WS (HTTP Client) +# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS +# ~~~~~ +# The HTTP client primarily used for REST APIs. The default client can be +# configured directly, but you can also create different client instances +# with customized settings. You must enable this by adding to build.sbt: +# +# libraryDependencies += ws // or javaWs if using java +# +play.ws { + # Sets HTTP requests not to follow 302 requests + #followRedirects = false + + # Sets the maximum number of open HTTP connections for the client. + #ahc.maxConnectionsTotal = 50 + + ## WS SSL + # https://www.playframework.com/documentation/latest/WsSSL + # ~~~~~ + ssl { + # Configuring HTTPS with Play WS does not require programming. You can + # set up both trustManager and keyManager for mutual authentication, and + # turn on JSSE debugging in development with a reload. + #debug.handshake = true + #trustManager = { + # stores = [ + # { type = "JKS", path = "exampletrust.jks" } + # ] + #} + } +} + +## Cache +# https://www.playframework.com/documentation/latest/JavaCache +# https://www.playframework.com/documentation/latest/ScalaCache +# ~~~~~ +# Play comes with an integrated cache API that can reduce the operational +# overhead of repeated requests. You must enable this by adding to build.sbt: +# +# libraryDependencies += cache +# +play.cache { + # If you want to bind several caches, you can bind the individually + #bindCaches = ["db-cache", "user-cache", "session-cache"] +} + +## Filters +# https://www.playframework.com/documentation/latest/Filters +# ~~~~~ +# There are a number of built-in filters that can be enabled and configured +# to give Play greater security. You must enable this by adding to build.sbt: +# +# libraryDependencies += filters +# +play.filters { + ## CORS filter configuration + # https://www.playframework.com/documentation/latest/CorsFilter + # ~~~~~ + # CORS is a protocol that allows web applications to make requests from the browser + # across different domains. + # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has + # dependencies on CORS settings. + cors { + # Filter paths by a whitelist of path prefixes + #pathPrefixes = ["/some/path", ...] + + # The allowed origins. If null, all origins are allowed. + #allowedOrigins = ["http://www.example.com"] + + # The allowed HTTP methods. If null, all methods are allowed + #allowedHttpMethods = ["GET", "POST"] + } + + ## CSRF Filter + # https://www.playframework.com/documentation/latest/ScalaCsrf#Applying-a-global-CSRF-filter + # https://www.playframework.com/documentation/latest/JavaCsrf#Applying-a-global-CSRF-filter + # ~~~~~ + # Play supports multiple methods for verifying that a request is not a CSRF request. + # The primary mechanism is a CSRF token. This token gets placed either in the query string + # or body of every form submitted, and also gets placed in the users session. + # Play then verifies that both tokens are present and match. + csrf { + # Sets the cookie to be sent only over HTTPS + #cookie.secure = true + + # Defaults to CSRFErrorHandler in the root package. + #errorHandler = MyCSRFErrorHandler + } + + ## Security headers filter configuration + # https://www.playframework.com/documentation/latest/SecurityHeaders + # ~~~~~ + # Defines security headers that prevent XSS attacks. + # If enabled, then all options are set to the below configuration by default: + headers { + # The X-Frame-Options header. If null, the header is not set. + #frameOptions = "DENY" + + # The X-XSS-Protection header. If null, the header is not set. + #xssProtection = "1; mode=block" + + # The X-Content-Type-Options header. If null, the header is not set. + #contentTypeOptions = "nosniff" + + # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set. + #permittedCrossDomainPolicies = "master-only" + + # The Content-Security-Policy header. If null, the header is not set. + #contentSecurityPolicy = "default-src 'self'" + } + + ## Allowed hosts filter configuration + # https://www.playframework.com/documentation/latest/AllowedHostsFilter + # ~~~~~ + # Play provides a filter that lets you configure which hosts can access your application. + # This is useful to prevent cache poisoning attacks. + hosts { + # Allow requests to example.com, its subdomains, and localhost:9000. + #allowed = [".example.com", "localhost:9000"] + } +} + +## Evolutions +# https://www.playframework.com/documentation/latest/Evolutions +# ~~~~~ +# Evolutions allows database scripts to be automatically run on startup in dev mode +# for database migrations. You must enable this by adding to build.sbt: +# +# libraryDependencies += evolutions +# +play.evolutions { + # You can disable evolutions for a specific datasource if necessary + #db.default.enabled = false +} + +## Database Connection Pool +# https://www.playframework.com/documentation/latest/SettingsJDBC +# ~~~~~ +# Play doesn't require a JDBC database to run, but you can easily enable one. +# +# libraryDependencies += jdbc +# +play.db { + # The combination of these two settings results in "db.default" as the + # default JDBC pool: + #config = "db" + #default = "default" + + # Play uses HikariCP as the default connection pool. You can override + # settings by changing the prototype: + prototype { + # Sets a fixed JDBC connection pool size of 50 + #hikaricp.minimumIdle = 50 + #hikaricp.maximumPoolSize = 50 + } +} + +## JDBC Datasource +# https://www.playframework.com/documentation/latest/JavaDatabase +# https://www.playframework.com/documentation/latest/ScalaDatabase +# ~~~~~ +# Once JDBC datasource is set up, you can work with several different +# database options: +# +# Slick (Scala preferred option): https://www.playframework.com/documentation/latest/PlaySlick +# JPA (Java preferred option): https://playframework.com/documentation/latest/JavaJPA +# EBean: https://playframework.com/documentation/latest/JavaEbean +# Anorm: https://www.playframework.com/documentation/latest/ScalaAnorm +# +db { + # You can declare as many datasources as you want. + # By convention, the default datasource is named `default` + + # https://www.playframework.com/documentation/latest/Developing-with-the-H2-Database + #default.driver = org.h2.Driver + #default.url = "jdbc:h2:mem:play" + #default.username = sa + #default.password = "" + + # You can turn on SQL logging for any datasource + # https://www.playframework.com/documentation/latest/Highlights25#Logging-SQL-statements + #default.logSql=true +} diff --git a/play-framework/student-api/conf/logback.xml b/play-framework/student-api/conf/logback.xml new file mode 100644 index 0000000000..86ec12c0af --- /dev/null +++ b/play-framework/student-api/conf/logback.xml @@ -0,0 +1,41 @@ + + + + + + + ${application.home:-.}/logs/application.log + + %date [%level] from %logger in %thread - %message%n%xException + + + + + + %coloredLevel %logger{15} - %message%n%xException{10} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/play-framework/student-api/conf/routes b/play-framework/student-api/conf/routes new file mode 100644 index 0000000000..ab55792683 --- /dev/null +++ b/play-framework/student-api/conf/routes @@ -0,0 +1,12 @@ +# Routes +# This file defines all application routes (Higher priority routes first) +# ~~~~ + +GET / controllers.StudentController.listStudents() +POST /:id controllers.StudentController.retrieve(id:Int) +POST / controllers.StudentController.create() +PUT / controllers.StudentController.update() +DELETE /:id controllers.StudentController.delete(id:Int) + +# Map static resources from the /public folder to the /assets URL path +GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) diff --git a/play-framework/student-api/libexec/activator-launch-1.3.10.jar b/play-framework/student-api/libexec/activator-launch-1.3.10.jar new file mode 100644 index 0000000000..69050e7dec Binary files /dev/null and b/play-framework/student-api/libexec/activator-launch-1.3.10.jar differ diff --git a/play-framework/student-api/project/build.properties b/play-framework/student-api/project/build.properties new file mode 100644 index 0000000000..6d9fa6badb --- /dev/null +++ b/play-framework/student-api/project/build.properties @@ -0,0 +1,4 @@ +#Activator-generated Properties +#Wed Sep 07 12:29:40 EAT 2016 +template.uuid=c373963b-f5ad-433b-8e74-178e7ae25b1c +sbt.version=0.13.11 diff --git a/play-framework/student-api/project/plugins.sbt b/play-framework/student-api/project/plugins.sbt new file mode 100644 index 0000000000..51c5b2a35a --- /dev/null +++ b/play-framework/student-api/project/plugins.sbt @@ -0,0 +1,21 @@ +// The Play plugin +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.6") + +// Web plugins +addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.1.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-jshint" % "1.0.3") +addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.7") +addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0") +addSbtPlugin("org.irundaia.sbt" % "sbt-sassify" % "1.4.2") + +// Play enhancer - this automatically generates getters/setters for public fields +// and rewrites accessors of these fields to use the getters/setters. Remove this +// plugin if you prefer not to have this feature, or disable on a per project +// basis using disablePlugins(PlayEnhancer) in your build.sbt +addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.1.0") + +// Play Ebean support, to enable, uncomment this line, and enable in your build.sbt using +// enablePlugins(PlayEbean). +// addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "1.0.0") diff --git a/play-framework/student-api/public/images/favicon.png b/play-framework/student-api/public/images/favicon.png new file mode 100644 index 0000000000..c7d92d2ae4 Binary files /dev/null and b/play-framework/student-api/public/images/favicon.png differ diff --git a/play-framework/student-api/public/javascripts/hello.js b/play-framework/student-api/public/javascripts/hello.js new file mode 100644 index 0000000000..02ee13c7ca --- /dev/null +++ b/play-framework/student-api/public/javascripts/hello.js @@ -0,0 +1,3 @@ +if (window.console) { + console.log("Welcome to your Play application's JavaScript!"); +} diff --git a/spring-cloud-data-flow/data-flow-server/src/main/resources/application.properties b/play-framework/student-api/public/stylesheets/main.css similarity index 100% rename from spring-cloud-data-flow/data-flow-server/src/main/resources/application.properties rename to play-framework/student-api/public/stylesheets/main.css diff --git a/play-framework/student-api/test/ApplicationTest.java b/play-framework/student-api/test/ApplicationTest.java new file mode 100644 index 0000000000..3d7c4875aa --- /dev/null +++ b/play-framework/student-api/test/ApplicationTest.java @@ -0,0 +1,45 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.*; + +import play.mvc.*; +import play.test.*; +import play.data.DynamicForm; +import play.data.validation.ValidationError; +import play.data.validation.Constraints.RequiredValidator; +import play.i18n.Lang; +import play.libs.F; +import play.libs.F.*; +import play.twirl.api.Content; + +import static play.test.Helpers.*; +import static org.junit.Assert.*; + + +/** + * + * Simple (JUnit) tests that can call all parts of a play app. + * If you are interested in mocking a whole application, see the wiki for more details. + * + */ +public class ApplicationTest { + + @Test + public void simpleCheck() { + int a = 1 + 1; + assertEquals(2, a); + } + + @Test + public void renderTemplate() { + Content html = views.html.index.render("Your new application is ready."); + assertEquals("text/html", html.contentType()); + assertTrue(html.body().contains("Your new application is ready.")); + } + + +} diff --git a/play-framework/student-api/test/IntegrationTest.java b/play-framework/student-api/test/IntegrationTest.java new file mode 100644 index 0000000000..c53c71e124 --- /dev/null +++ b/play-framework/student-api/test/IntegrationTest.java @@ -0,0 +1,25 @@ +import org.junit.*; + +import play.mvc.*; +import play.test.*; + +import static play.test.Helpers.*; +import static org.junit.Assert.*; + +import static org.fluentlenium.core.filter.FilterConstructor.*; + +public class IntegrationTest { + + /** + * add your integration test here + * in this example we just check if the welcome page is being shown + */ + @Test + public void test() { + running(testServer(3333, fakeApplication(inMemoryDatabase())), HTMLUNIT, browser -> { + browser.goTo("http://localhost:3333"); + assertTrue(browser.pageSource().contains("Your new application is ready.")); + }); + } + +} diff --git a/pom.xml b/pom.xml index 5dad868501..5526c1e2a3 100644 --- a/pom.xml +++ b/pom.xml @@ -1,116 +1,139 @@ - - 4.0.0 - org.baeldung - spring-security-login-and-registration - spring-security-login-and-registration - war - 1.0.0-BUILD-SNAPSHOT + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung + parent-modules + 1.0.0-SNAPSHOT - - org.springframework.boot - spring-boot-starter-parent - 1.1.4.RELEASE - + parent-modules + pom - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.security - spring-security-config - runtime - - - - - - - org.slf4j - slf4j-api - - - ch.qos.logback - logback-classic - - - - org.slf4j - jcl-over-slf4j - - + + UTF-8 + - - org.slf4j - log4j-over-slf4j - - - - - javax.inject - javax.inject - ${javax.inject.version} - - - - - javax.servlet - javax.servlet-api - - - - javax.servlet.jsp - javax.servlet.jsp-api - ${javax.servlet.jsp-api.version} - - - - javax.servlet - jstl - - - - - org.springframework.security - spring-security-taglibs - - - - - junit - junit - test - - - - spring-security-login-and-registration - - - src/main/resources - true - - - - - 1.7 - 3.1.1.RELEASE - 3.2.4.RELEASE - 1.6.10 - - - 1.7.6 - 1.1.1 - - - 2.3.2-b01 + + assertj + apache-cxf + + autovalue-tutorial - - 1 - + cdi + core-java + core-java-8 + couchbase-sdk + + + dozer + dependency-injection + deltaspike + + patterns + feign-client + + + gson + gson-jackson-performance + guava + guava18 + guava19 + + handling-spring-static-resources + httpclient + + immutables + + jackson + javaxval + jjwt + jooq-spring + jpa-storedprocedure + json + json-path + junit5 + jee7schedule + + + log4j + + mockito + mocks + mutation-testing + + orika + + querydsl + + + rest-assured + rest-testing + resteasy + okhttp + + spring-all + spring-akka + spring-apache-camel + spring-autowire + spring-batch + spring-boot + spring-cucumber + spring-data-cassandra + spring-data-couchbase-2 + spring-data-elasticsearch + spring-data-neo4j + spring-data-mongodb + spring-data-redis + spring-data-rest + spring-exceptions + spring-freemarker + spring-hibernate3 + spring-hibernate4 + spring-jpa + spring-jms + spring-katharsis + spring-mockito + spring-mvc-java + spring-mvc-no-xml + spring-mvc-xml + spring-mvc-tiles + spring-openid + spring-protobuf + spring-quartz + spring-spel + spring-rest + spring-rest-angular + spring-rest-docs + spring-cloud + spring-cloud-data-flow + + spring-security-basic-auth + spring-security-custom-permission + spring-security-mvc-custom + spring-security-mvc-digest-auth + spring-security-mvc-ldap + spring-security-mvc-login + spring-security-mvc-persisted-remember-me + spring-security-mvc-session + spring-security-rest + spring-security-rest-basic-auth + spring-security-rest-custom + spring-security-rest-digest-auth + spring-security-rest-full + spring-security-x509 + spring-thymeleaf + spring-zuul + spring-mvc-velocity + + jsf + xml + lombok + redis + + wicket + xstream + java-cassandra + annotations + diff --git a/querydsl/pom.xml b/querydsl/pom.xml new file mode 100644 index 0000000000..bed0cf90e5 --- /dev/null +++ b/querydsl/pom.xml @@ -0,0 +1,172 @@ + + + 4.0.0 + + com.baeldung + querydsl + 0.1-SNAPSHOT + jar + + querydsl + http://maven.apache.org + + + UTF-8 + 1.8 + 4.12 + 4.3.1.RELEASE + 5.2.1.Final + 4.1.3 + 1.7.21 + + + + + + + com.querydsl + querydsl-jpa + ${querydsl.version} + + + + com.querydsl + querydsl-apt + ${querydsl.version} + provided + + + + + org.hibernate + hibernate-entitymanager + ${hibernate.version} + compile + + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + 1.0.0.Final + compile + + + + commons-dbcp + commons-dbcp + 1.4 + jar + compile + + + + commons-pool + commons-pool + 1.6 + jar + compile + + + + + org.hsqldb + hsqldb + 2.3.4 + + + + + org.springframework + spring-context + ${spring.version} + + + + org.springframework + spring-webmvc + ${spring.version} + + + + org.springframework + spring-orm + ${spring.version} + jar + compile + + + + org.springframework + spring-aop + ${spring.version} + + + + org.springframework + spring-test + ${spring.version} + jar + test + + + + + ch.qos.logback + logback-classic + 1.1.7 + + + org.slf4j + jcl-over-slf4j + ${slf4j.version} + runtime + + + + + junit + junit + ${junit.version} + test + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + ${java.version} + ${java.version} + -proc:none + + + + + + com.mysema.maven + apt-maven-plugin + 1.1.3 + + + + process + + + target/generated-sources/java + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + + + + + \ No newline at end of file diff --git a/querydsl/src/main/java/org/baeldung/dao/PersonDao.java b/querydsl/src/main/java/org/baeldung/dao/PersonDao.java new file mode 100644 index 0000000000..7df4ebb22d --- /dev/null +++ b/querydsl/src/main/java/org/baeldung/dao/PersonDao.java @@ -0,0 +1,22 @@ +package org.baeldung.dao; + +import java.util.List; +import java.util.Map; + +import org.baeldung.entity.Person; + +public interface PersonDao { + + public Person save(Person person); + + public List findPersonsByFirstnameQueryDSL(String firstname); + + public List findPersonsByFirstnameAndSurnameQueryDSL(String firstname, String surname); + + public List findPersonsByFirstnameInDescendingOrderQueryDSL(String firstname); + + public int findMaxAge(); + + public Map findMaxAgeByName(); + +} \ No newline at end of file diff --git a/querydsl/src/main/java/org/baeldung/dao/PersonDaoImpl.java b/querydsl/src/main/java/org/baeldung/dao/PersonDaoImpl.java new file mode 100644 index 0000000000..9acaf1dd18 --- /dev/null +++ b/querydsl/src/main/java/org/baeldung/dao/PersonDaoImpl.java @@ -0,0 +1,68 @@ +package org.baeldung.dao; + +import java.util.List; +import java.util.Map; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.baeldung.entity.Person; +import org.baeldung.entity.QPerson; +import org.springframework.stereotype.Repository; + +import com.querydsl.core.group.GroupBy; +import com.querydsl.jpa.impl.JPAQuery; + +@Repository +public class PersonDaoImpl implements PersonDao { + + @PersistenceContext + private EntityManager em; + + @Override + public Person save(final Person person) { + em.persist(person); + return person; + } + + @Override + public List findPersonsByFirstnameQueryDSL(final String firstname) { + final JPAQuery query = new JPAQuery<>(em); + final QPerson person = QPerson.person; + + return query.from(person).where(person.firstname.eq(firstname)).fetch(); + } + + @Override + public List findPersonsByFirstnameAndSurnameQueryDSL(final String firstname, final String surname) { + final JPAQuery query = new JPAQuery<>(em); + final QPerson person = QPerson.person; + + return query.from(person).where(person.firstname.eq(firstname).and(person.surname.eq(surname))).fetch(); + } + + @Override + public List findPersonsByFirstnameInDescendingOrderQueryDSL(final String firstname) { + final JPAQuery query = new JPAQuery<>(em); + final QPerson person = QPerson.person; + + return query.from(person).where(person.firstname.eq(firstname)).orderBy(person.surname.desc()).fetch(); + } + + @Override + public int findMaxAge() { + final JPAQuery query = new JPAQuery<>(em); + final QPerson person = QPerson.person; + + return query.from(person).select(person.age.max()).fetchFirst(); + } + + @Override + public Map findMaxAgeByName() { + final JPAQuery query = new JPAQuery<>(em); + final QPerson person = QPerson.person; + + return query.from(person).transform(GroupBy.groupBy(person.firstname).as(GroupBy.max(person.age))); + } + +} \ No newline at end of file diff --git a/querydsl/src/main/java/org/baeldung/entity/Person.java b/querydsl/src/main/java/org/baeldung/entity/Person.java new file mode 100644 index 0000000000..6f04210d90 --- /dev/null +++ b/querydsl/src/main/java/org/baeldung/entity/Person.java @@ -0,0 +1,69 @@ +package org.baeldung.entity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Person { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column + private String firstname; + + @Column + private String surname; + + @Column + private int age; + + Person() { + } + + public Person(final String firstname, final String surname) { + this.firstname = firstname; + this.surname = surname; + } + + public Person(final String firstname, final String surname, final int age) { + this(firstname, surname); + this.age = age; + } + + public Long getId() { + return id; + } + + public void setId(final Long id) { + this.id = id; + } + + public String getFirstname() { + return firstname; + } + + public void setFirstname(final String firstname) { + this.firstname = firstname; + } + + public String getSurname() { + return surname; + } + + public void setSurname(final String surname) { + this.surname = surname; + } + + public int getAge() { + return age; + } + + public void setAge(final int age) { + this.age = age; + } +} \ No newline at end of file diff --git a/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/BlogPost.java b/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/BlogPost.java new file mode 100644 index 0000000000..241bc50b03 --- /dev/null +++ b/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/BlogPost.java @@ -0,0 +1,56 @@ +/* + * (c) Центр ИТ, 2016. Ð’Ñе права защищены. + */ +package org.baeldung.querydsl.intro.entities; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class BlogPost { + + @Id + @GeneratedValue + private Long id; + + private String title; + + private String body; + + @ManyToOne + private User user; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String code) { + this.title = code; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } +} diff --git a/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/User.java b/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/User.java new file mode 100644 index 0000000000..c0681e15d1 --- /dev/null +++ b/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/User.java @@ -0,0 +1,55 @@ +/* + * (c) Центр ИТ, 2016. Ð’Ñе права защищены. + */ +package org.baeldung.querydsl.intro.entities; + +import java.util.HashSet; +import java.util.Set; +import javax.persistence.*; + +@Entity +public class User { + + @Id + @GeneratedValue + private Long id; + + private String login; + + private Boolean disabled; + + @OneToMany(cascade = CascadeType.PERSIST, mappedBy = "user") + private Set blogPosts = new HashSet<>(0); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getLogin() { + return login; + } + + public void setLogin(String name) { + this.login = name; + } + + public Set getBlogPosts() { + return blogPosts; + } + + public void setBlogPosts(Set blogPosts) { + this.blogPosts = blogPosts; + } + + public Boolean getDisabled() { + return disabled; + } + + public void setDisabled(Boolean disabled) { + this.disabled = disabled; + } +} diff --git a/querydsl/src/main/resources/META-INF/persistence.xml b/querydsl/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000000..2964382d48 --- /dev/null +++ b/querydsl/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + + + + + + + + + + + \ No newline at end of file diff --git a/querydsl/src/main/resources/logback.xml b/querydsl/src/main/resources/logback.xml new file mode 100644 index 0000000000..d0a1dc06ac --- /dev/null +++ b/querydsl/src/main/resources/logback.xml @@ -0,0 +1,37 @@ + + + + + + %d{yyyy-MM-dd HH:mm:ss} [%t] %-5p: %c - %m%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/querydsl/src/test/java/org/baeldung/dao/PersonDaoTest.java b/querydsl/src/test/java/org/baeldung/dao/PersonDaoTest.java new file mode 100644 index 0000000000..0e5996a8c8 --- /dev/null +++ b/querydsl/src/test/java/org/baeldung/dao/PersonDaoTest.java @@ -0,0 +1,81 @@ +package org.baeldung.dao; + +import java.util.Map; + +import org.baeldung.entity.Person; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.transaction.TransactionConfiguration; +import org.springframework.transaction.annotation.Transactional; + +import junit.framework.Assert; + +@ContextConfiguration("/test-context.xml") +@RunWith(SpringJUnit4ClassRunner.class) +@Transactional +@TransactionConfiguration(defaultRollback = true) +public class PersonDaoTest { + + @Autowired + private PersonDao personDao; + + // + + @Test + public void testCreation() { + personDao.save(new Person("Erich", "Gamma")); + final Person person = new Person("Kent", "Beck"); + personDao.save(person); + personDao.save(new Person("Ralph", "Johnson")); + + final Person personFromDb = personDao.findPersonsByFirstnameQueryDSL("Kent").get(0); + Assert.assertEquals(person.getId(), personFromDb.getId()); + } + + @Test + public void testMultipleFilter() { + personDao.save(new Person("Erich", "Gamma")); + final Person person = personDao.save(new Person("Ralph", "Beck")); + final Person person2 = personDao.save(new Person("Ralph", "Johnson")); + + final Person personFromDb = personDao.findPersonsByFirstnameAndSurnameQueryDSL("Ralph", "Johnson").get(0); + Assert.assertNotSame(person.getId(), personFromDb.getId()); + Assert.assertEquals(person2.getId(), personFromDb.getId()); + } + + @Test + public void testOrdering() { + final Person person = personDao.save(new Person("Kent", "Gamma")); + personDao.save(new Person("Ralph", "Johnson")); + final Person person2 = personDao.save(new Person("Kent", "Zivago")); + + final Person personFromDb = personDao.findPersonsByFirstnameInDescendingOrderQueryDSL("Kent").get(0); + Assert.assertNotSame(person.getId(), personFromDb.getId()); + Assert.assertEquals(person2.getId(), personFromDb.getId()); + } + + @Test + public void testMaxAge() { + personDao.save(new Person("Kent", "Gamma", 20)); + personDao.save(new Person("Ralph", "Johnson", 35)); + personDao.save(new Person("Kent", "Zivago", 30)); + + final int maxAge = personDao.findMaxAge(); + Assert.assertTrue(maxAge == 35); + } + + @Test + public void testMaxAgeByName() { + personDao.save(new Person("Kent", "Gamma", 20)); + personDao.save(new Person("Ralph", "Johnson", 35)); + personDao.save(new Person("Kent", "Zivago", 30)); + + final Map maxAge = personDao.findMaxAgeByName(); + Assert.assertTrue(maxAge.size() == 2); + Assert.assertSame(35, maxAge.get("Ralph")); + Assert.assertSame(30, maxAge.get("Kent")); + } +} \ No newline at end of file diff --git a/querydsl/src/test/java/org/baeldung/querydsl/intro/QueryDSLTest.java b/querydsl/src/test/java/org/baeldung/querydsl/intro/QueryDSLTest.java new file mode 100644 index 0000000000..682fa2c245 --- /dev/null +++ b/querydsl/src/test/java/org/baeldung/querydsl/intro/QueryDSLTest.java @@ -0,0 +1,215 @@ +/* + * (c) Центр ИТ, 2016. Ð’Ñе права защищены. + */ +package org.baeldung.querydsl.intro; + +import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +import org.baeldung.querydsl.intro.entities.BlogPost; +import org.baeldung.querydsl.intro.entities.QBlogPost; +import org.baeldung.querydsl.intro.entities.QUser; +import org.baeldung.querydsl.intro.entities.User; +import com.querydsl.core.Tuple; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.core.types.dsl.NumberPath; +import com.querydsl.jpa.JPAExpressions; +import com.querydsl.jpa.impl.JPAQueryFactory; +import org.junit.*; + +import static org.junit.Assert.*; + +public class QueryDSLTest { + + private static EntityManagerFactory emf; + + private EntityManager em; + + private JPAQueryFactory queryFactory; + + @BeforeClass + public static void populateDatabase() { + emf = Persistence.createEntityManagerFactory("org.baeldung.querydsl.intro"); + EntityManager em = emf.createEntityManager(); + + em.getTransaction().begin(); + User user1 = new User(); + user1.setLogin("David"); + em.persist(user1); + + User user2 = new User(); + user2.setLogin("Ash"); + em.persist(user2); + + User user3 = new User(); + user3.setLogin("Call"); + em.persist(user3); + + User user4 = new User(); + user4.setLogin("Bishop"); + em.persist(user4); + + BlogPost blogPost1 = new BlogPost(); + blogPost1.setTitle("Hello World!"); + blogPost1.setUser(user1); + em.persist(blogPost1); + + BlogPost blogPost2 = new BlogPost(); + blogPost2.setTitle("My Second Post"); + blogPost2.setUser(user1); + em.persist(blogPost2); + + BlogPost blogPost3 = new BlogPost(); + blogPost3.setTitle("Hello World!"); + blogPost3.setUser(user3); + em.persist(blogPost3); + + em.getTransaction().commit(); + + em.close(); + + } + + @Before + public void setUp() { + em = emf.createEntityManager(); + em.getTransaction().begin(); + queryFactory = new JPAQueryFactory(em); + } + + @Test + public void whenFindByLogin_thenShouldReturnUser() { + + QUser user = QUser.user; + User aUser = queryFactory.selectFrom(user) + .where(user.login.eq("David")) + .fetchOne(); + + assertNotNull(aUser); + assertEquals(aUser.getLogin(), "David"); + + } + + @Test + public void whenUsingOrderBy_thenResultsShouldBeOrdered() { + + QUser user = QUser.user; + List users = queryFactory.selectFrom(user) + .orderBy(user.login.asc()) + .fetch(); + + assertEquals(users.size(), 4); + assertEquals(users.get(0).getLogin(), "Ash"); + assertEquals(users.get(1).getLogin(), "Bishop"); + assertEquals(users.get(2).getLogin(), "Call"); + assertEquals(users.get(3).getLogin(), "David"); + + } + + @Test + public void whenGroupingByTitle_thenReturnsTuples() { + + QBlogPost blogPost = QBlogPost.blogPost; + + NumberPath count = Expressions.numberPath(Long.class, "c"); + + List userTitleCounts = queryFactory.select(blogPost.title, blogPost.id.count().as(count)) + .from(blogPost) + .groupBy(blogPost.title) + .orderBy(count.desc()) + .fetch(); + + assertEquals("Hello World!", userTitleCounts.get(0).get(blogPost.title)); + assertEquals(new Long(2), userTitleCounts.get(0).get(count)); + + assertEquals("My Second Post", userTitleCounts.get(1).get(blogPost.title)); + assertEquals(new Long(1), userTitleCounts.get(1).get(count)); + + } + + @Test + public void whenJoiningWithCondition_thenResultCountShouldMatch() { + + QUser user = QUser.user; + QBlogPost blogPost = QBlogPost.blogPost; + + List users = queryFactory.selectFrom(user) + .innerJoin(user.blogPosts, blogPost) + .on(blogPost.title.eq("Hello World!")) + .fetch(); + + assertEquals(2, users.size()); + } + + @Test + public void whenRefiningWithSubquery_thenResultCountShouldMatch() { + + QUser user = QUser.user; + QBlogPost blogPost = QBlogPost.blogPost; + + List users = queryFactory.selectFrom(user) + .where(user.id.in( + JPAExpressions.select(blogPost.user.id) + .from(blogPost) + .where(blogPost.title.eq("Hello World!")))) + .fetch(); + + assertEquals(2, users.size()); + } + + @Test + public void whenUpdating_thenTheRecordShouldChange() { + + QUser user = QUser.user; + + queryFactory.update(user) + .where(user.login.eq("Ash")) + .set(user.login, "Ash2") + .set(user.disabled, true) + .execute(); + + em.getTransaction().commit(); + + em.getTransaction().begin(); + + assertEquals(Boolean.TRUE, + queryFactory.select(user.disabled) + .from(user) + .where(user.login.eq("Ash2")) + .fetchOne()); + + } + + @Test + public void whenDeleting_thenTheRecordShouldBeAbsent() { + + QUser user = QUser.user; + + queryFactory.delete(user) + .where(user.login.eq("Bishop")) + .execute(); + + em.getTransaction().commit(); + + em.getTransaction().begin(); + + assertNull(queryFactory.selectFrom(user) + .where(user.login.eq("Bishop")) + .fetchOne()); + + } + + @After + public void tearDown() { + em.getTransaction().commit(); + em.close(); + } + + @AfterClass + public static void afterClass() { + emf.close(); + } + +} diff --git a/querydsl/src/test/resources/db.properties b/querydsl/src/test/resources/db.properties new file mode 100644 index 0000000000..efee3669ce --- /dev/null +++ b/querydsl/src/test/resources/db.properties @@ -0,0 +1,6 @@ +#In memory db +db.username=sa +db.password= +db.driver=org.hsqldb.jdbcDriver +db.url=jdbc:hsqldb:mem:app-db +db.dialect=org.hibernate.dialect.HSQLDialect \ No newline at end of file diff --git a/querydsl/src/test/resources/test-context.xml b/querydsl/src/test/resources/test-context.xml new file mode 100644 index 0000000000..13d823a857 --- /dev/null +++ b/querydsl/src/test/resources/test-context.xml @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/querydsl/src/test/resources/test-db.xml b/querydsl/src/test/resources/test-db.xml new file mode 100644 index 0000000000..7f85630b6b --- /dev/null +++ b/querydsl/src/test/resources/test-db.xml @@ -0,0 +1,49 @@ + + + + + + + classpath:db.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/raml/README.MD b/raml/README.MD new file mode 100644 index 0000000000..2a87b46021 --- /dev/null +++ b/raml/README.MD @@ -0,0 +1,2 @@ +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring diff --git a/raml/annotations/README.md b/raml/annotations/README.md new file mode 100644 index 0000000000..4142b33353 --- /dev/null +++ b/raml/annotations/README.md @@ -0,0 +1,7 @@ +========= + +## Define Custom RAML + + +### Relevant Articles: +- [Define Custom RAML Properties Using Annotations](http://www.baeldung.com/raml-custom-properties-with-annotations) diff --git a/raml/annotations/api.raml b/raml/annotations/api.raml new file mode 100644 index 0000000000..e0123536eb --- /dev/null +++ b/raml/annotations/api.raml @@ -0,0 +1,126 @@ +#%RAML 1.0 +title: API for REST Services used in the RAML tutorials on Baeldung.com +documentation: + - title: Overview + content: | + This document defines the interface for the REST services + used in the popular RAML Tutorial series at Baeldung.com. + - title: Disclaimer + content: | + All names used in this definition are purely fictional. + Any similarities between the names used in this tutorial and those of real persons, whether living or dead, are merely coincidental. + - title: Copyright + content: Copyright 2016 by Baeldung.com. All rights reserved. +uses: + mySecuritySchemes: !include libraries/securitySchemes.raml + myDataTypes: !include libraries/dataTypes.raml + myTraits: !include libraries/traits.raml + myResourceTypes: !include libraries/resourceTypes.raml +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: [ mySecuritySchemes.basicAuth ] +annotationTypes: + testCase: + allowedTargets: [ Method ] + allowMultiple: true + usage: | + Use this annotation to declare a test case + within a testSuite declaration. + You may apply this annotation multiple times + within the target testSuite. + properties: + scenario: string + setupScript?: string[] + testScript: string[] + expectedOutput?: string + cleanupScript?: string[] +/foos: + type: myResourceTypes.collection + get: + queryParameters: + name?: string + ownerName?: string + responses: + 200: + body: + example: !include examples/Foos.json + (testCase): + scenario: No Foos + setupScript: deleteAllFoosIfAny + testScript: getAllFoos + expectedOutput: "" + (testCase): + scenario: One Foo + setupScript: [ deleteAllFoosIfAny, addInputFoos ] + testScript: getAllFoos + expectedOutput: '[ { "id": 999, "name": Joe } ]' + cleanupScript: deleteInputFoos + (testCase): + scenario: Multiple Foos + setupScript: [ deleteAllFoosIfAny, addInputFoos ] + testScript: getAllFoos + expectedOutput: '[ { "id": 998, "name": "Bob" }, { "id": 999, "name": "Joe", "ownerName": "Bob" } ]' + cleanupScript: deleteInputFoos + post: + responses: + 200: + body: + example: !include examples/Foo.json + /{fooId}: + type: myResourceTypes.item + get: + responses: + 200: + body: + example: !include examples/Foo.json + put: + responses: + 200: + body: + example: !include examples/Foo.json +/foos/name/{name}: + get: + description: Get all Foos with the name {name} + responses: + 200: + body: + type: myDataTypes.Foo + 404: + body: + type: myDataTypes.Error +/foos/bar/{barId}: + get: + description: Get the Foo for the Bar with barId = {barId} + responses: + 200: + body: + example: !include examples/Foo.json +/bars: + type: myResourceTypes.collection + get: + queryParameters: + name?: string + ownerName?: string + responses: + 200: + body: + example: !include examples/Bars.json + post: + responses: + 200: + body: + example: !include examples/Bar.json + /{barId}: + type: myResourceTypes.item + get: + responses: + 200: + body: + example: !include examples/Bar.json + put: + responses: + 200: + body: + example: !include examples/Bars.json diff --git a/raml/annotations/examples/Bar.json b/raml/annotations/examples/Bar.json new file mode 100644 index 0000000000..0ee1b34edb --- /dev/null +++ b/raml/annotations/examples/Bar.json @@ -0,0 +1,6 @@ +{ + "id" : 1, + "name" : "First Bar", + "city" : "Austin", + "fooId" : 2 +} \ No newline at end of file diff --git a/raml/annotations/examples/Bars.json b/raml/annotations/examples/Bars.json new file mode 100644 index 0000000000..89ea875432 --- /dev/null +++ b/raml/annotations/examples/Bars.json @@ -0,0 +1,19 @@ +[ + { + "id" : 1, + "name" : "First Bar", + "city" : "Austin", + "fooId" : 2 + }, + { + "id" : 2, + "name" : "Second Bar", + "city" : "Dallas", + "fooId" : 1 + }, + { + "id" : 3, + "name" : "Third Bar", + "fooId" : 2 + } +] \ No newline at end of file diff --git a/raml/annotations/examples/Error.json b/raml/annotations/examples/Error.json new file mode 100644 index 0000000000..dca56da7c2 --- /dev/null +++ b/raml/annotations/examples/Error.json @@ -0,0 +1,4 @@ +{ + "message" : "Not found", + "code" : 1001 +} \ No newline at end of file diff --git a/raml/annotations/examples/Foo.json b/raml/annotations/examples/Foo.json new file mode 100644 index 0000000000..1b1b8c891e --- /dev/null +++ b/raml/annotations/examples/Foo.json @@ -0,0 +1,4 @@ +{ + "id" : 1, + "name" : "First Foo" +} \ No newline at end of file diff --git a/raml/annotations/examples/Foos.json b/raml/annotations/examples/Foos.json new file mode 100644 index 0000000000..74f64689f0 --- /dev/null +++ b/raml/annotations/examples/Foos.json @@ -0,0 +1,16 @@ +[ + { + "id" : 1, + "name" : "First Foo", + "ownerName" : "Jack Robinson" + }, + { + "id" : 2, + "name" : "Second Foo" + }, + { + "id" : 3, + "name" : "Third Foo", + "ownerName" : "Chuck Norris" + } +] \ No newline at end of file diff --git a/raml/annotations/extensions/en_US/additionalResources.raml b/raml/annotations/extensions/en_US/additionalResources.raml new file mode 100644 index 0000000000..9ab0d0a243 --- /dev/null +++ b/raml/annotations/extensions/en_US/additionalResources.raml @@ -0,0 +1,13 @@ +#%RAML 1.0 Extension +# File located at: +# /extensions/en_US/additionalResources.raml +masterRef: ../../api.raml +usage: This extension defines additional resources for version 2 of the API. +version: v2 +/foos: + /bar/{barId}: + get: + description: | + Get the foo that is related to the bar having barId = {barId} + queryParameters: + barId?: integer diff --git a/raml/annotations/libraries/dataTypes.raml b/raml/annotations/libraries/dataTypes.raml new file mode 100644 index 0000000000..8a240e62dc --- /dev/null +++ b/raml/annotations/libraries/dataTypes.raml @@ -0,0 +1,19 @@ +#%RAML 1.0 Library +# This is the file /libraries/dataTypes.raml +usage: This library defines the data types for the API +types: + Foo: + properties: + id: integer + name: string + ownerName?: string + Bar: + properties: + id: integer + name: string + city?: string + fooId: integer + Error: + properties: + code: integer + message: string diff --git a/raml/annotations/libraries/resourceTypes.raml b/raml/annotations/libraries/resourceTypes.raml new file mode 100644 index 0000000000..fb054f1a36 --- /dev/null +++ b/raml/annotations/libraries/resourceTypes.raml @@ -0,0 +1,38 @@ +#%RAML 1.0 Library +# This is the file /libraries/resourceTypes.raml +usage: This library defines the resource types for the API +uses: + myTraits: !include traits.raml +resourceTypes: + collection: + usage: Use this resourceType to represent a collection of items + description: A collection of <> + get: + description: | + Get all <>, + optionally filtered + is: [ myTraits.hasResponseCollection ] + post: + description: | + Create a new <> + is: [ myTraits.hasRequestItem ] + item: + usage: Use this resourceType to represent any single item + description: A single <> + get: + description: | + Get a <> + by <>Id + is: [ myTraits.hasResponseItem, myTraits.hasNotFound ] + put: + description: | + Update a <> + by <>Id + is: [ myTraits.hasRequestItem, myTraits.hasResponseItem, myTraits.hasNotFound ] + delete: + description: | + Delete a <> + by <>Id + is: [ myTraits.hasNotFound ] + responses: + 204: diff --git a/raml/annotations/libraries/securitySchemes.raml b/raml/annotations/libraries/securitySchemes.raml new file mode 100644 index 0000000000..621c6ac975 --- /dev/null +++ b/raml/annotations/libraries/securitySchemes.raml @@ -0,0 +1,20 @@ +#%RAML 1.0 Library +# This is the file /libraries/securitySchemes.raml +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: | + Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to + access the content provided by the requested URL. diff --git a/raml/annotations/libraries/traits.raml b/raml/annotations/libraries/traits.raml new file mode 100644 index 0000000000..610747e79f --- /dev/null +++ b/raml/annotations/libraries/traits.raml @@ -0,0 +1,32 @@ +#%RAML 1.0 Library +# This is the file /libraries/traits.raml +usage: This library defines some basic traits +uses: + myDataTypes: !include dataTypes.raml +traits: + hasRequestItem: + usage: Use this trait for resources whose request body is a single item + body: + application/json: + type: <> + hasResponseItem: + usage: Use this trait for resources whose response body is a single item + responses: + 200: + body: + application/json: + type: <> + hasResponseCollection: + usage: Use this trait for resources whose response body is a collection of items + responses: + 200: + body: + application/json: + type: <>[] + hasNotFound: + usage: Use this trait for resources that could respond with a 404 status + responses: + 404: + body: + application/json: + type: myDataTypes.Error diff --git a/raml/annotations/overlays/es_ES/additionalResources.raml b/raml/annotations/overlays/es_ES/additionalResources.raml new file mode 100644 index 0000000000..0edd6a9231 --- /dev/null +++ b/raml/annotations/overlays/es_ES/additionalResources.raml @@ -0,0 +1,11 @@ +#%RAML 1.0 Overlay +# Archivo situado en: +# /overlays/es_ES/additionalResources.raml +masterRef: ../../api.raml +usage: | + Se trata de un español demasiado que describe los recursos adicionales + para la versión 1 del API. +/foos/bar/{barId}: + get: + description: | + Obtener el foo que se relaciona con el bar tomando barId = {barId} diff --git a/raml/annotations/overlays/es_ES/documentationItems.raml b/raml/annotations/overlays/es_ES/documentationItems.raml new file mode 100644 index 0000000000..49dd46fb59 --- /dev/null +++ b/raml/annotations/overlays/es_ES/documentationItems.raml @@ -0,0 +1,22 @@ +#%RAML 1.0 Overlay +# File located at (archivo situado en): +# /overlays/es_ES/documentationItems.raml +masterRef: ../../api.raml +usage: | + To provide user documentation and other descriptive text in Spanish + (Para proporcionar la documentación del usuario y otro texto descriptivo en español) +title: API para servicios REST utilizados en los tutoriales RAML en Baeldung.com +documentation: + - title: Descripción general + content: | + Este documento define la interfaz para los servicios REST + utilizados en la popular serie de RAML Tutorial en Baeldung.com + - title: Renuncia + content: | + Todos los nombres usados ​​en esta definición son pura ficción. + Cualquier similitud entre los nombres utilizados en este tutorial + y los de las personas reales, ya sea vivo o muerto, + no son más que coincidenta. + - title: Derechos de autor + content: | + Derechos de autor 2016 por Baeldung.com. Todos los derechos reservados. diff --git a/raml/modularization/README.md b/raml/modularization/README.md new file mode 100644 index 0000000000..de0e047ea6 --- /dev/null +++ b/raml/modularization/README.md @@ -0,0 +1,6 @@ +========= + +## Modular RESTful API Modeling Language + +### Relevant Articles: +- [Modular RAML Using Includes, Libraries, Overlays and Extensions](http://www.baeldung.com/modular-raml-includes-overlays-libraries-extensions) diff --git a/raml/modularization/api-before-modularization.raml b/raml/modularization/api-before-modularization.raml new file mode 100644 index 0000000000..b580c33983 --- /dev/null +++ b/raml/modularization/api-before-modularization.raml @@ -0,0 +1,119 @@ +#%RAML 1.0 +title: API for REST Services used in the RAML tutorials on Baeldung.com +documentation: + - title: Overview + - content: | + This document defines the interface for the REST services + used in the popular RAML Tutorial series at Baeldung.com. + - title: Disclaimer: + - content: | + All names used in this definition are purely fictional. + Any similarities between the names used in this tutorial and those of real persons, whether living or dead, are merely coincidental. + - title: Copyright + - content: Copyright 2016 by Baeldung.com. All rights reserved. +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: basicAuth +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: | + Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to + access the content provided by the requested URL. +types: + Foo: !include types/Foo.raml + Bar: !include types/Bar.raml + Error: !include types/Error.raml +resourceTypes: + - collection: + usage: Use this resourceType to represent a collection of items + description: A collection of <> + get: + description: | + Get all <>, + optionally filtered + is: [ hasResponseCollection ] + post: + description: | + Create a new <> + is: [ hasRequestItem ] + - item: + usage: Use this resourceType to represent any single item + description: A single <> + get: + description: Get a <> by <> + is: [ hasResponseItem, hasNotFound ] + put: + description: Update a <> by <> + is: [ hasRequestItem, hasResponseItem, hasNotFound ] + delete: + description: Delete a <> by <> + is: [ hasNotFound ] + responses: + 204: +traits: + - hasRequestItem: + body: + application/json: + type: <> + - hasResponseItem: + responses: + 200: + body: + application/json: + type: <> + example: !include examples/<>.json + - hasResponseCollection: + responses: + 200: + body: + application/json: + type: <>[] + example: !include examples/<>.json + - hasNotFound: + responses: + 404: + body: + application/json: + type: Error + example: !include examples/Error.json +/foos: + type: collection + typeName: Foo + get: + queryParameters: + name?: string + ownerName?: string + /{fooId}: + type: item + typeName: Foo + /name/{name}: + get: + description: List all foos with a certain name + typeName: Foo + is: [ hasResponseCollection ] +/bars: + type: collection + typeName: Bar + /{barId}: + type: item + typeName: Bar + /fooId/{fooId}: + get: + description: Get all bars for the matching fooId + typeName: Bar + is: [ hasResponseCollection ] \ No newline at end of file diff --git a/raml/modularization/api-with-libraries.raml b/raml/modularization/api-with-libraries.raml new file mode 100644 index 0000000000..b3081e843a --- /dev/null +++ b/raml/modularization/api-with-libraries.raml @@ -0,0 +1,50 @@ +#%RAML 1.0 +title: API for REST Services used in the RAML tutorials on Baeldung.com +documentation: + - title: Overview + - content: | + This document defines the interface for the REST services + used in the popular RAML Tutorial series at Baeldung.com. + - title: Disclaimer: + - content: | + All names used in this definition are purely fictional. + Any similarities between the names used in this tutorial and those of real persons, whether living or dead, are merely coincidental. + - title: Copyright + - content: Copyright 2016 by Baeldung.com. All rights reserved. +uses: + mySecuritySchemes: !include libraries/security.raml + myDataTypes: !include libraries/dataTypes.raml + myResourceTypes: !include libraries/resourceTypes.raml + myTraits: !include libraries/traits.raml +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: [ mySecuritySchemes.basicAuth ] +/foos: + type: myResourceTypes.collection + typeName: myDataTypes.Foo + get: + queryParameters: + name?: string + ownerName?: string + /{fooId}: + type: myResourceTypes.item + typeName: myDataTypes.Foo + /name/{name}: + get: + description: List all foos with a certain name + typeName: myDataTypes.Foo + is: [ myTraits.hasResponseCollection ] +/bars: + type: myResourceTypes.collection + typeName: myDataTypes.Bar + /{barId}: + type: myResourceTypes.item + typeName: myDataTypes.Bar + /fooId/{fooId}: + get: + description: Get all bars for the matching fooId + type: myResourceTypes.item + typeName: myDataTypes.Bar + is: [ myTraits.hasResponseCollection ] \ No newline at end of file diff --git a/raml/modularization/api-with-typed-fragments.raml b/raml/modularization/api-with-typed-fragments.raml new file mode 100644 index 0000000000..2bb4e317c1 --- /dev/null +++ b/raml/modularization/api-with-typed-fragments.raml @@ -0,0 +1,74 @@ +#%RAML 1.0 +title: API for REST Services used in the RAML tutorials on Baeldung.com +documentation: + - title: Overview + - content: | + This document defines the interface for the REST services + used in the popular RAML Tutorial series at Baeldung.com. + - title: Disclaimer: + - content: | + All names used in this definition are purely fictional. + Any similarities between the names used in this tutorial and those of real persons, whether living or dead, are merely coincidental. + - title: Copyright + - content: Copyright 2016 by Baeldung.com. All rights reserved. +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: [ basicAuth ] +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: | + Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to + access the content provided by the requested URL. +types: + Foo: !include types/Foo.raml + Bar: !include types/Bar.raml + Error: !include types/Error.raml +resourceTypes: + - collection: !include resourceTypes/collection.raml + - item: !include resourceTypes/item.raml +traits: + - hasRequestItem: !include traits/hasRequestItem.raml + - hasResponseItem: !include traits/hasResponseItem.raml + - hasResponseCollection: !include traits/hasResponseCollection.raml + - hasNotFound: !include traits/hasNotFound.raml +/foos: + type: collection + typeName: Foo + get: + queryParameters: + name?: string + ownerName?: string + /{fooId}: + type: item + typeName: Foo + /name/{name}: + get: + description: List all foos with a certain name + typeName: Foo + is: [ hasResponseCollection ] +/bars: + type: collection + typeName: Bar + /{barId}: + type: item + typeName: Bar + /fooId/{fooId}: + get: + description: Get all bars for the matching fooId + typeName: Bar + is: [ hasResponseCollection ] \ No newline at end of file diff --git a/raml/modularization/api.raml b/raml/modularization/api.raml new file mode 100644 index 0000000000..184027cd26 --- /dev/null +++ b/raml/modularization/api.raml @@ -0,0 +1,47 @@ +#%RAML 1.0 +title: Baeldung Foo REST Services API +uses: + security: !include libraries/security.raml +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: [ security.basicAuth ] +types: + Foo: !include types/Foo.raml + Bar: !include types/Bar.raml + Error: !include types/Error.raml +resourceTypes: + - collection: !include resourceTypes/collection.raml + - item: !include resourceTypes/item.raml +traits: + - hasRequestItem: !include traits/hasRequestItem.raml + - hasResponseItem: !include traits/hasResponseItem.raml + - hasResponseCollection: !include traits/hasResponseCollection.raml + - hasNotFound: !include traits/hasNotFound.raml +/foos: + type: collection + typeName: Foo + get: + queryParameters: + name?: string + ownerName?: string + /{fooId}: + type: item + typeName: Foo + /name/{name}: + get: + description: List all foos with a certain name + typeName: Foo + is: [ hasResponseCollection ] +/bars: + type: collection + typeName: Bar + /{barId}: + type: item + typeName: Bar + /fooId/{fooId}: + get: + description: Get all bars for the matching fooId + typeName: Bar + is: [ hasResponseCollection ] \ No newline at end of file diff --git a/raml/modularization/examples/Bar.json b/raml/modularization/examples/Bar.json new file mode 100644 index 0000000000..0ee1b34edb --- /dev/null +++ b/raml/modularization/examples/Bar.json @@ -0,0 +1,6 @@ +{ + "id" : 1, + "name" : "First Bar", + "city" : "Austin", + "fooId" : 2 +} \ No newline at end of file diff --git a/raml/modularization/examples/Bars.json b/raml/modularization/examples/Bars.json new file mode 100644 index 0000000000..89ea875432 --- /dev/null +++ b/raml/modularization/examples/Bars.json @@ -0,0 +1,19 @@ +[ + { + "id" : 1, + "name" : "First Bar", + "city" : "Austin", + "fooId" : 2 + }, + { + "id" : 2, + "name" : "Second Bar", + "city" : "Dallas", + "fooId" : 1 + }, + { + "id" : 3, + "name" : "Third Bar", + "fooId" : 2 + } +] \ No newline at end of file diff --git a/raml/modularization/examples/Error.json b/raml/modularization/examples/Error.json new file mode 100644 index 0000000000..dca56da7c2 --- /dev/null +++ b/raml/modularization/examples/Error.json @@ -0,0 +1,4 @@ +{ + "message" : "Not found", + "code" : 1001 +} \ No newline at end of file diff --git a/raml/modularization/examples/Foo.json b/raml/modularization/examples/Foo.json new file mode 100644 index 0000000000..1b1b8c891e --- /dev/null +++ b/raml/modularization/examples/Foo.json @@ -0,0 +1,4 @@ +{ + "id" : 1, + "name" : "First Foo" +} \ No newline at end of file diff --git a/raml/modularization/examples/Foos.json b/raml/modularization/examples/Foos.json new file mode 100644 index 0000000000..74f64689f0 --- /dev/null +++ b/raml/modularization/examples/Foos.json @@ -0,0 +1,16 @@ +[ + { + "id" : 1, + "name" : "First Foo", + "ownerName" : "Jack Robinson" + }, + { + "id" : 2, + "name" : "Second Foo" + }, + { + "id" : 3, + "name" : "Third Foo", + "ownerName" : "Chuck Norris" + } +] \ No newline at end of file diff --git a/raml/modularization/extensions/en_US/additionalResources.raml b/raml/modularization/extensions/en_US/additionalResources.raml new file mode 100644 index 0000000000..20c6851f23 --- /dev/null +++ b/raml/modularization/extensions/en_US/additionalResources.raml @@ -0,0 +1,16 @@ +#%RAML 1.0 Extension +# File located at: +# /extensions/en_US/additionalResources.raml +masterRef: /api.raml +usage: This extension defines additional resources for version 2 of the API. +version: v2 +/foos: + /bar/{barId}: + get: + description: | + Get the foo that is related to the bar having barId = {barId} + typeName: Foo + queryParameters: + barId?: integer + typeName: Foo + is: [ hasResponseItem ] diff --git a/raml/modularization/libraries/dataTypes.raml b/raml/modularization/libraries/dataTypes.raml new file mode 100644 index 0000000000..8a240e62dc --- /dev/null +++ b/raml/modularization/libraries/dataTypes.raml @@ -0,0 +1,19 @@ +#%RAML 1.0 Library +# This is the file /libraries/dataTypes.raml +usage: This library defines the data types for the API +types: + Foo: + properties: + id: integer + name: string + ownerName?: string + Bar: + properties: + id: integer + name: string + city?: string + fooId: integer + Error: + properties: + code: integer + message: string diff --git a/raml/modularization/libraries/resourceTypes.raml b/raml/modularization/libraries/resourceTypes.raml new file mode 100644 index 0000000000..681ff710d6 --- /dev/null +++ b/raml/modularization/libraries/resourceTypes.raml @@ -0,0 +1,32 @@ +#%RAML 1.0 Library +# This is the file /libraries/resourceTypes.raml +usage: This library defines the resource types for the API +uses: + myTraits: !include traits.raml +resourceTypes: + collection: + usage: Use this resourceType to represent a collection of items + description: A collection of <> + get: + description: | + Get all <>, + optionally filtered + is: [ myTraits.hasResponseCollection ] + post: + description: | + Create a new <> + is: [ myTraits.hasRequestItem ] + item: + usage: Use this resourceType to represent any single item + description: A single <> + get: + description: Get a <> by <> + is: [ myTraits.hasResponseItem, myTraits.hasNotFound ] + put: + description: Update a <> by <> + is: [ myTraits.hasRequestItem, myTraits.hasResponseItem, myTraits.hasNotFound ] + delete: + description: Delete a <> by <> + is: [ myTraits.hasNotFound ] + responses: + 204: diff --git a/raml/modularization/libraries/securitySchemes.raml b/raml/modularization/libraries/securitySchemes.raml new file mode 100644 index 0000000000..621c6ac975 --- /dev/null +++ b/raml/modularization/libraries/securitySchemes.raml @@ -0,0 +1,20 @@ +#%RAML 1.0 Library +# This is the file /libraries/securitySchemes.raml +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: | + Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to + access the content provided by the requested URL. diff --git a/raml/modularization/libraries/traits.raml b/raml/modularization/libraries/traits.raml new file mode 100644 index 0000000000..c101d94c02 --- /dev/null +++ b/raml/modularization/libraries/traits.raml @@ -0,0 +1,33 @@ +#%RAML 1.0 Library +# This is the file /libraries/traits.raml +usage: This library defines some basic traits +traits: + hasRequestItem: + usage: Use this trait for resources whose request body is a single item + body: + application/json: + type: <> + hasResponseItem: + usage: Use this trait for resources whose response body is a single item + responses: + 200: + body: + application/json: + type: <> + example: !include /examples/<>.json + hasResponseCollection: + usage: Use this trait for resources whose response body is a collection of items + responses: + 200: + body: + application/json: + type: <>[] + example: !include /examples/<>.json + hasNotFound: + usage: Use this trait for resources that could respond with a 404 status + responses: + 404: + body: + application/json: + type: Error + example: !include /examples/Error.json diff --git a/raml/modularization/overlays/es_ES/additionalResources.raml b/raml/modularization/overlays/es_ES/additionalResources.raml new file mode 100644 index 0000000000..e8748fd726 --- /dev/null +++ b/raml/modularization/overlays/es_ES/additionalResources.raml @@ -0,0 +1,13 @@ +#%RAML 1.0 Overlay +# Archivo situado en: +# /overlays/es_ES/additionalResources.raml +masterRef: /api.raml +usage: | + Se trata de un español demasiado que describe los recursos adicionales + para la versión 2 del API. +version: v2 +/foos: + /bar/{barId}: + get: + description: | + Obtener el foo que se relaciona con el bar tomando barId = {barId} diff --git a/raml/modularization/overlays/es_ES/documentationItems.raml b/raml/modularization/overlays/es_ES/documentationItems.raml new file mode 100644 index 0000000000..dc6ca3eaef --- /dev/null +++ b/raml/modularization/overlays/es_ES/documentationItems.raml @@ -0,0 +1,23 @@ +#%RAML 1.0 Overlay +# File located at (archivo situado en): +# /overlays/es_ES/documentationItems.raml +masterRef: /api.raml +usage: | + To provide user documentation and other descriptive text in Spanish + (Para proporcionar la documentación del usuario y otro texto descriptivo en español) +title: API para servicios REST utilizados en los tutoriales RAML en Baeldung.com +documentation: + - title: Descripción general + - content: | + Este documento define la interfaz para los servicios REST + utilizados en la popular serie de RAML Tutorial en Baeldung.com + - title: Renuncia + - content: | + Todos los nombres usados ​​en esta definición son pura ficción. + Cualquier similitud entre los nombres utilizados en este tutorial + y los de las personas reales, ya sea vivo o muerto, + no son más que coincidenta. + + - title: Derechos de autor + - content: | + Derechos de autor 2016 por Baeldung.com. Todos los derechos reservados. diff --git a/raml/modularization/resourceTypes/collection.raml b/raml/modularization/resourceTypes/collection.raml new file mode 100644 index 0000000000..0cab417f14 --- /dev/null +++ b/raml/modularization/resourceTypes/collection.raml @@ -0,0 +1,12 @@ +#%RAML 1.0 ResourceType +usage: Use this resourceType to represent a collection of items +description: A collection of <> +get: + description: | + Get all <>, + optionally filtered + is: [ hasResponseCollection ] +post: + description: | + Create a new <> + is: [ hasRequestItem ] diff --git a/raml/modularization/resourceTypes/item.raml b/raml/modularization/resourceTypes/item.raml new file mode 100644 index 0000000000..59f057ca98 --- /dev/null +++ b/raml/modularization/resourceTypes/item.raml @@ -0,0 +1,14 @@ +#%RAML 1.0 ResourceType +usage: Use this resourceType to represent any single item +description: A single <> +get: + description: Get a <> by <> + is: [ hasResponseItem, hasNotFound ] +put: + description: Update a <> by <> + is: [ hasRequestItem, hasResponseItem, hasNotFound ] +delete: + description: Delete a <> by <> + is: [ hasNotFound ] + responses: + 204: diff --git a/raml/modularization/traits/hasNotFound.raml b/raml/modularization/traits/hasNotFound.raml new file mode 100644 index 0000000000..8d2d940c03 --- /dev/null +++ b/raml/modularization/traits/hasNotFound.raml @@ -0,0 +1,8 @@ +#%RAML 1.0 Trait +usage: Use this trait for resources that could respond with a 404 status +responses: + 404: + body: + application/json: + type: Error + example: !include /examples/Error.json diff --git a/raml/modularization/traits/hasRequestItem.raml b/raml/modularization/traits/hasRequestItem.raml new file mode 100644 index 0000000000..06281781c0 --- /dev/null +++ b/raml/modularization/traits/hasRequestItem.raml @@ -0,0 +1,5 @@ +#%RAML 1.0 Trait +usage: Use this trait for resources whose request body is a single item +body: + application/json: + type: <> diff --git a/raml/modularization/traits/hasResponseCollection.raml b/raml/modularization/traits/hasResponseCollection.raml new file mode 100644 index 0000000000..47dc1c2d5f --- /dev/null +++ b/raml/modularization/traits/hasResponseCollection.raml @@ -0,0 +1,8 @@ +#%RAML 1.0 Trait +usage: Use this trait for resources whose response body is a collection of items +responses: + 200: + body: + application/json: + type: <>[] + example: !include /examples/<>.json diff --git a/raml/modularization/traits/hasResponseItem.raml b/raml/modularization/traits/hasResponseItem.raml new file mode 100644 index 0000000000..94d3ba0756 --- /dev/null +++ b/raml/modularization/traits/hasResponseItem.raml @@ -0,0 +1,8 @@ +#%RAML 1.0 Trait +usage: Use this trait for resources whose response body is a single item +responses: + 200: + body: + application/json: + type: <> + example: !include /examples/<>.json diff --git a/raml/modularization/types/Bar.raml b/raml/modularization/types/Bar.raml new file mode 100644 index 0000000000..92255a75fe --- /dev/null +++ b/raml/modularization/types/Bar.raml @@ -0,0 +1,7 @@ +#%RAML 1.0 DataType + +properties: + id: integer + name: string + city?: string + fooId: integer diff --git a/raml/modularization/types/Error.raml b/raml/modularization/types/Error.raml new file mode 100644 index 0000000000..8d54b5f181 --- /dev/null +++ b/raml/modularization/types/Error.raml @@ -0,0 +1,5 @@ +#%RAML 1.0 DataType + + properties: + code: integer + message: string diff --git a/raml/modularization/types/Foo.raml b/raml/modularization/types/Foo.raml new file mode 100644 index 0000000000..1702865e05 --- /dev/null +++ b/raml/modularization/types/Foo.raml @@ -0,0 +1,6 @@ +#%RAML 1.0 DataType + +properties: + id: integer + name: string + ownerName?: string diff --git a/redis/pom.xml b/redis/pom.xml new file mode 100644 index 0000000000..a5d3af8097 --- /dev/null +++ b/redis/pom.xml @@ -0,0 +1,56 @@ + + + + 4.0.0 + com.baeldung + redis + 0.1-SNAPSHOT + + redis + http://maven.apache.org + + + + redis.clients + jedis + 2.8.1 + + + + com.github.kstyrc + embedded-redis + 0.6 + + + + junit + junit + ${junit.version} + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + + + + UTF-8 + + 4.12 + + diff --git a/redis/src/test/java/com/baeldung/JedisTest.java b/redis/src/test/java/com/baeldung/JedisTest.java new file mode 100644 index 0000000000..766fd7b5e9 --- /dev/null +++ b/redis/src/test/java/com/baeldung/JedisTest.java @@ -0,0 +1,225 @@ +package com.baeldung; + +import java.io.IOException; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; +import redis.clients.jedis.Pipeline; +import redis.clients.jedis.Response; +import redis.clients.jedis.Transaction; +import redis.embedded.RedisServer; + +/** + * Unit test for Redis Java library - Jedis. + */ +public class JedisTest { + + private Jedis jedis; + private static RedisServer redisServer; + + public JedisTest() { + jedis = new Jedis(); + } + + @BeforeClass + public static void setUp() throws IOException { + redisServer = new RedisServer(6379); + redisServer.start(); + } + + @AfterClass + public static void destroy() { + redisServer.stop(); + } + + @After + public void flush() { + jedis.flushAll(); + } + + @Test + public void givenAString_thenSaveItAsRedisStrings() { + String key = "key"; + String value = "value"; + + jedis.set(key, value); + String value2 = jedis.get(key); + + Assert.assertEquals(value, value2); + } + + @Test + public void givenListElements_thenSaveThemInRedisList() { + String queue = "queue#tasks"; + + String taskOne = "firstTask"; + String taskTwo = "secondTask"; + String taskThree = "thirdTask"; + + jedis.lpush(queue, taskOne, taskTwo); + + String taskReturnedOne = jedis.rpop(queue); + + jedis.lpush(queue, taskThree); + Assert.assertEquals(taskOne, taskReturnedOne); + + String taskReturnedTwo = jedis.rpop(queue); + String taskReturnedThree = jedis.rpop(queue); + + Assert.assertEquals(taskTwo, taskReturnedTwo); + Assert.assertEquals(taskThree, taskReturnedThree); + + String taskReturnedFour = jedis.rpop(queue); + Assert.assertNull(taskReturnedFour); + } + + @Test + public void givenSetElements_thenSaveThemInRedisSet() { + String countries = "countries"; + + String countryOne = "Spain"; + String countryTwo = "Ireland"; + String countryThree = "Ireland"; + + jedis.sadd(countries, countryOne); + + Set countriesSet = jedis.smembers(countries); + Assert.assertEquals(1, countriesSet.size()); + + jedis.sadd(countries, countryTwo); + countriesSet = jedis.smembers(countries); + Assert.assertEquals(2, countriesSet.size()); + + jedis.sadd(countries, countryThree); + countriesSet = jedis.smembers(countries); + Assert.assertEquals(2, countriesSet.size()); + + boolean exists = jedis.sismember(countries, countryThree); + Assert.assertTrue(exists); + } + + @Test + public void givenObjectFields_thenSaveThemInRedisHash() { + String key = "user#1"; + + String field = "name"; + String value = "William"; + + String field2 = "job"; + String value2 = "politician"; + + jedis.hset(key, field, value); + jedis.hset(key, field2, value2); + + String value3 = jedis.hget(key, field); + Assert.assertEquals(value, value3); + + Map fields = jedis.hgetAll(key); + String value4 = fields.get(field2); + Assert.assertEquals(value2, value4); + } + + @Test + public void givenARanking_thenSaveItInRedisSortedSet() { + String key = "ranking"; + + Map scores = new HashMap<>(); + + scores.put("PlayerOne", 3000.0); + scores.put("PlayerTwo", 1500.0); + scores.put("PlayerThree", 8200.0); + + for (String player : scores.keySet()) { + jedis.zadd(key, scores.get(player), player); + } + + Set players = jedis.zrevrange(key, 0, 1); + Assert.assertEquals("PlayerThree", players.iterator().next()); + + long rank = jedis.zrevrank(key, "PlayerOne"); + Assert.assertEquals(1, rank); + } + + @Test + public void givenMultipleOperationsThatNeedToBeExecutedAtomically_thenWrapThemInATransaction() { + String friendsPrefix = "friends#"; + + String userOneId = "4352523"; + String userTwoId = "5552321"; + + Transaction t = jedis.multi(); + t.sadd(friendsPrefix + userOneId, userTwoId); + t.sadd(friendsPrefix + userTwoId, userOneId); + t.exec(); + + boolean exists = jedis.sismember(friendsPrefix + userOneId, userTwoId); + Assert.assertTrue(exists); + + exists = jedis.sismember(friendsPrefix + userTwoId, userOneId); + Assert.assertTrue(exists); + } + + @Test + public void givenMultipleIndependentOperations_whenNetworkOptimizationIsImportant_thenWrapThemInAPipeline() { + String userOneId = "4352523"; + String userTwoId = "4849888"; + + Pipeline p = jedis.pipelined(); + p.sadd("searched#" + userOneId, "paris"); + p.zadd("ranking", 126, userOneId); + p.zadd("ranking", 325, userTwoId); + Response pipeExists = p.sismember("searched#" + userOneId, "paris"); + Response> pipeRanking = p.zrange("ranking", 0, -1); + p.sync(); + + Assert.assertTrue(pipeExists.get()); + Assert.assertEquals(2, pipeRanking.get().size()); + } + + @Test + public void givenAPoolConfiguration_thenCreateAJedisPool() { + final JedisPoolConfig poolConfig = buildPoolConfig(); + + try (JedisPool jedisPool = new JedisPool(poolConfig, "localhost"); Jedis jedis = jedisPool.getResource()) { + + // do simple operation to verify that the Jedis resource is working + // properly + String key = "key"; + String value = "value"; + + jedis.set(key, value); + String value2 = jedis.get(key); + + Assert.assertEquals(value, value2); + + // flush Redis + jedis.flushAll(); + } + } + + private JedisPoolConfig buildPoolConfig() { + final JedisPoolConfig poolConfig = new JedisPoolConfig(); + poolConfig.setMaxTotal(128); + poolConfig.setMaxIdle(128); + poolConfig.setMinIdle(16); + poolConfig.setTestOnBorrow(true); + poolConfig.setTestOnReturn(true); + poolConfig.setTestWhileIdle(true); + poolConfig.setMinEvictableIdleTimeMillis(Duration.ofSeconds(60).toMillis()); + poolConfig.setTimeBetweenEvictionRunsMillis(Duration.ofSeconds(30).toMillis()); + poolConfig.setNumTestsPerEvictionRun(3); + poolConfig.setBlockWhenExhausted(true); + return poolConfig; + } +} diff --git a/rest-assured/.gitignore b/rest-assured/.gitignore new file mode 100644 index 0000000000..862f46031e --- /dev/null +++ b/rest-assured/.gitignore @@ -0,0 +1,16 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear + +.externalToolBuilders +.settings \ No newline at end of file diff --git a/spring-cloud-data-flow/data-flow-shell/src/main/resources/application.properties b/rest-assured/README.md similarity index 100% rename from spring-cloud-data-flow/data-flow-shell/src/main/resources/application.properties rename to rest-assured/README.md diff --git a/rest-assured/pom.xml b/rest-assured/pom.xml new file mode 100644 index 0000000000..47241b18bd --- /dev/null +++ b/rest-assured/pom.xml @@ -0,0 +1,257 @@ + + 4.0.0 + com.baeldung + rest-assured + 1.0 + rest-assured + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 8 + 8 + + + + + + + + javax.servlet + javax.servlet-api + 3.1-b06 + + + + + javax.servlet + servlet-api + 2.5 + + + + + org.eclipse.jetty + jetty-security + 9.2.0.M1 + + + + + org.eclipse.jetty + jetty-servlet + 9.2.0.M1 + + + + + org.eclipse.jetty + jetty-servlets + 9.2.0.M1 + + + + + org.eclipse.jetty + jetty-io + 9.2.0.M1 + + + + + org.eclipse.jetty + jetty-http + 9.2.0.M1 + + + + + + + org.eclipse.jetty + jetty-server + 9.2.0.M1 + + + + + org.eclipse.jetty + jetty-util + 9.2.0.M1 + + + + + + org.slf4j + slf4j-api + 1.7.21 + + + + + log4j + log4j + 1.2.17 + + + + org.slf4j + slf4j-log4j12 + 1.7.21 + + + + + + commons-logging + commons-logging + 1.2 + + + + org.apache.httpcomponents + httpcore + 4.4.5 + + + + + org.apache.commons + commons-lang3 + 3.4 + + + + + + com.github.fge + uri-template + 0.9 + + + + + com.googlecode.libphonenumber + libphonenumber + 7.4.5 + + + + javax.mail + mail + 1.4.7 + + + + joda-time + joda-time + 2.9.4 + + + + com.fasterxml.jackson.core + jackson-annotations + 2.8.0 + + + + com.fasterxml.jackson.core + jackson-databind + 2.8.0 + + + + com.fasterxml.jackson.core + jackson-core + 2.8.0 + + + + com.github.fge + msg-simple + 1.1 + + + + com.github.fge + jackson-coreutils + 1.8 + + + + + + com.google.guava + guava + 18.0 + + + com.github.fge + btf + 1.2 + + + + org.apache.httpcomponents + httpclient + 4.5.2 + + + + org.codehaus.groovy + groovy-all + 2.4.7 + + + + com.github.tomakehurst + wiremock + 2.1.7 + + + io.rest-assured + rest-assured + 3.0.0 + test + + + io.rest-assured + json-schema-validator + 3.0.0 + + + com.github.fge + json-schema-validator + 2.2.6 + + + com.github.fge + json-schema-core + 1.2.5 + + + junit + junit + 4.3 + test + + + + org.hamcrest + hamcrest-all + 1.3 + + + + commons-collections + commons-collections + 3.2.2 + + + + diff --git a/rest-assured/src/test/java/com/baeldung/restassured/RestAssured2Test.java b/rest-assured/src/test/java/com/baeldung/restassured/RestAssured2Test.java new file mode 100644 index 0000000000..067756823b --- /dev/null +++ b/rest-assured/src/test/java/com/baeldung/restassured/RestAssured2Test.java @@ -0,0 +1,55 @@ +package com.baeldung.restassured; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.hamcrest.Matchers.hasItems; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import static io.restassured.RestAssured.get; + +import com.github.tomakehurst.wiremock.WireMockServer; + +public class RestAssured2Test { + private WireMockServer wireMockServer = new WireMockServer(); + + private static final String EVENTS_PATH = "/odds"; + private static final String APPLICATION_JSON = "application/json"; + private static final String ODDS = getJson(); + + @Before + public void before() throws Exception { + System.out.println("Setting up!"); + wireMockServer.start(); + configureFor("localhost", 8080); + stubFor(get(urlEqualTo(EVENTS_PATH)).willReturn( + aResponse().withStatus(200) + .withHeader("Content-Type", APPLICATION_JSON) + .withBody(ODDS))); + } + + @Test + public void givenUrl_whenVerifiesOddPricesAccuratelyByStatus_thenCorrect() { + get("/odds").then().body("odds.findAll { it.status > 0 }.price", + hasItems(5.25f, 1.2f)); + } + + private static String getJson() { + + return Util.inputStreamToString(new RestAssured2Test().getClass() + .getResourceAsStream("/odds.json")); + + } + + @After + public void after() throws Exception { + System.out.println("Running: tearDown"); + wireMockServer.stop(); + } + +} diff --git a/rest-assured/src/test/java/com/baeldung/restassured/RestAssuredTest.java b/rest-assured/src/test/java/com/baeldung/restassured/RestAssuredTest.java new file mode 100644 index 0000000000..06f54aae24 --- /dev/null +++ b/rest-assured/src/test/java/com/baeldung/restassured/RestAssuredTest.java @@ -0,0 +1,106 @@ +package com.baeldung.restassured; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static io.restassured.RestAssured.get; +import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath; +import static io.restassured.module.jsv.JsonSchemaValidatorSettings.settings; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItems; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.github.fge.jsonschema.SchemaVersion; +import com.github.fge.jsonschema.cfg.ValidationConfiguration; +import com.github.fge.jsonschema.main.JsonSchemaFactory; +import com.github.tomakehurst.wiremock.WireMockServer; + +public class RestAssuredTest { + + private WireMockServer wireMockServer = new WireMockServer(); + private static final String EVENTS_PATH = "/events?id=390"; + private static final String APPLICATION_JSON = "application/json"; + private static final String GAME_ODDS = getEventJson(); + + @Before + public void before() throws Exception { + System.out.println("Setting up!"); + wireMockServer.start(); + configureFor("localhost", 8080); + stubFor(get(urlEqualTo(EVENTS_PATH)).willReturn( + aResponse().withStatus(200) + .withHeader("Content-Type", APPLICATION_JSON) + .withBody(GAME_ODDS))); + } + + @Test + public void givenUrl_whenCheckingFloatValuePasses_thenCorrect() { + get("/events?id=390").then().assertThat() + .body("odd.ck", equalTo(12.2f)); + } + + @Test + public void givenUrl_whenSuccessOnGetsResponseAndJsonHasRequiredKV_thenCorrect() { + + get("/events?id=390").then().statusCode(200).assertThat() + .body("id", equalTo("390")); + + } + + @Test + public void givenUrl_whenJsonResponseHasArrayWithGivenValuesUnderKey_thenCorrect() { + get("/events?id=390").then().assertThat() + .body("odds.price", hasItems("1.30", "5.25", "2.70", "1.20")); + } + + @Test + public void givenUrl_whenJsonResponseConformsToSchema_thenCorrect() { + + get("/events?id=390").then().assertThat() + .body(matchesJsonSchemaInClasspath("event_0.json")); + } + + @Test + public void givenUrl_whenValidatesResponseWithInstanceSettings_thenCorrect() { + JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory + .newBuilder() + .setValidationConfiguration( + ValidationConfiguration.newBuilder() + .setDefaultVersion(SchemaVersion.DRAFTV4) + .freeze()).freeze(); + + get("/events?id=390") + .then() + .assertThat() + .body(matchesJsonSchemaInClasspath("event_0.json").using( + jsonSchemaFactory)); + + } + + @Test + public void givenUrl_whenValidatesResponseWithStaticSettings_thenCorrect() { + + get("/events?id=390") + .then() + .assertThat() + .body(matchesJsonSchemaInClasspath("event_0.json").using( + settings().with().checkedValidation(false))); + } + + @After + public void after() throws Exception { + System.out.println("Running: tearDown"); + wireMockServer.stop(); + } + + private static String getEventJson() { + return Util.inputStreamToString(RestAssuredTest.class + .getResourceAsStream("/event_0.json")); + } + +} diff --git a/rest-assured/src/test/java/com/baeldung/restassured/RestAssuredXML2Test.java b/rest-assured/src/test/java/com/baeldung/restassured/RestAssuredXML2Test.java new file mode 100644 index 0000000000..597280c7c0 --- /dev/null +++ b/rest-assured/src/test/java/com/baeldung/restassured/RestAssuredXML2Test.java @@ -0,0 +1,54 @@ +package com.baeldung.restassured; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.hamcrest.Matchers.hasItems; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import static io.restassured.RestAssured.get; + +import com.github.tomakehurst.wiremock.WireMockServer; + +public class RestAssuredXML2Test { + private WireMockServer wireMockServer = new WireMockServer(); + + private static final String EVENTS_PATH = "/teachers"; + private static final String APPLICATION_XML = "application/xml"; + private static final String TEACHERS = getXml(); + + @Before + public void before() throws Exception { + System.out.println("Setting up!"); + wireMockServer.start(); + configureFor("localhost", 8080); + stubFor(get(urlEqualTo(EVENTS_PATH)).willReturn( + aResponse().withStatus(200) + .withHeader("Content-Type", APPLICATION_XML) + .withBody(TEACHERS))); + } + @Test + public void givenUrl_whenVerifiesScienceTeacherFromXml_thenCorrect() { + get("/teachers") + .then() + .body("teachers.teacher.find { it.@department == 'science' }.subject", + hasItems("math", "physics")); + } + private static String getXml() { + + return Util + .inputStreamToString(new RestAssuredXML2Test().getClass().getResourceAsStream("/teachers.xml")); + +} + @After +public void after() throws Exception { + System.out.println("Running: tearDown"); + wireMockServer.stop(); +} + +} diff --git a/rest-assured/src/test/java/com/baeldung/restassured/RestAssuredXMLTest.java b/rest-assured/src/test/java/com/baeldung/restassured/RestAssuredXMLTest.java new file mode 100644 index 0000000000..315dc76169 --- /dev/null +++ b/rest-assured/src/test/java/com/baeldung/restassured/RestAssuredXMLTest.java @@ -0,0 +1,99 @@ +package com.baeldung.restassured; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static io.restassured.RestAssured.post; +import static io.restassured.RestAssured.get; +import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath; +import static io.restassured.module.jsv.JsonSchemaValidatorSettings.settings; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.xml.HasXPath.hasXPath; + +import java.io.FileNotFoundException; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.github.fge.jsonschema.SchemaVersion; +import com.github.fge.jsonschema.cfg.ValidationConfiguration; +import com.github.fge.jsonschema.main.JsonSchemaFactory; +import com.github.tomakehurst.wiremock.WireMockServer; +public class RestAssuredXMLTest { + private WireMockServer wireMockServer = new WireMockServer(); + private static final String EVENTS_PATH = "/employees"; + private static final String APPLICATION_XML = "application/xml"; + private static final String EMPLOYEES = getXml(); + + @Before + public void before() throws Exception { + System.out.println("Setting up!"); + wireMockServer.start(); + configureFor("localhost", 8080); + stubFor(post(urlEqualTo(EVENTS_PATH)).willReturn( + aResponse().withStatus(200) + .withHeader("Content-Type", APPLICATION_XML) + .withBody(EMPLOYEES))); + } + @Test + public void givenUrl_whenXmlResponseValueTestsEqual_thenCorrect() { + post("/employees").then().assertThat() + .body("employees.employee.first-name", equalTo("Jane")); + } + + @Test + public void givenUrl_whenMultipleXmlValuesTestEqual_thenCorrect() { + post("/employees").then().assertThat() + .body("employees.employee.first-name", equalTo("Jane")) + .body("employees.employee.last-name", equalTo("Daisy")) + .body("employees.employee.sex", equalTo("f")); + } + + @Test + public void givenUrl_whenMultipleXmlValuesTestEqualInShortHand_thenCorrect() { + post("/employees") + .then() + .assertThat() + .body("employees.employee.first-name", equalTo("Jane"), + "employees.employee.last-name", equalTo("Daisy"), + "employees.employee.sex", equalTo("f")); + } + + @Test + public void givenUrl_whenValidatesXmlUsingXpath_thenCorrect() { + post("/employees") + .then() + .assertThat() + .body(hasXPath("/employees/employee/first-name", + containsString("Ja"))); + + } + + @Test + public void givenUrl_whenValidatesXmlUsingXpath2_thenCorrect() { + post("/employees") + .then() + .assertThat() + .body(hasXPath("/employees/employee/first-name[text()='Jane']")); + + } + + + private static String getXml() { + + return Util + .inputStreamToString(new RestAssuredXMLTest().getClass().getResourceAsStream("/employees.xml")); + +} + @After +public void after() throws Exception { + System.out.println("Running: tearDown"); + wireMockServer.stop(); +} +} diff --git a/rest-assured/src/test/java/com/baeldung/restassured/Util.java b/rest-assured/src/test/java/com/baeldung/restassured/Util.java new file mode 100644 index 0000000000..c75c52eb34 --- /dev/null +++ b/rest-assured/src/test/java/com/baeldung/restassured/Util.java @@ -0,0 +1,36 @@ +package com.baeldung.restassured; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class Util { + public static String inputStreamToString(InputStream is) { + BufferedReader br = null; + StringBuilder sb = new StringBuilder(); + + String line; + try { + + br = new BufferedReader(new InputStreamReader(is)); + while ((line = br.readLine()) != null) { + sb.append(line); + } + + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + return sb.toString(); + + } +} diff --git a/rest-assured/src/test/resources/employees.xml b/rest-assured/src/test/resources/employees.xml new file mode 100644 index 0000000000..388b422210 --- /dev/null +++ b/rest-assured/src/test/resources/employees.xml @@ -0,0 +1,7 @@ + + + Jane + Daisy + f + + \ No newline at end of file diff --git a/rest-assured/src/test/resources/event_0.json b/rest-assured/src/test/resources/event_0.json new file mode 100644 index 0000000000..a6e45239ec --- /dev/null +++ b/rest-assured/src/test/resources/event_0.json @@ -0,0 +1,43 @@ +{ + "id": "390", + "odd": { + "price": "1.20", + "status": 2, + "ck": 12.2, + "name": "2" + }, + "data": { + "countryId": 35, + "countryName": "Norway", + "leagueName": "Norway 3", + "status": 0, + "sportName": "Soccer", + "time": "2016-06-12T12:00:00Z" + }, + "odds": [{ + "price": "1.30", + "status": 0, + "ck": 12.2, + "name": "1" + }, + { + "price":"5.25", + "status": 1, + "ck": 13.1, + "name": "X" + }, + { + "price": "2.70", + "status": 0, + "ck": 12.2, + "name": "0" + }, + { + "price": "1.20", + "status": 2, + "ck": 13.1, + "name": "2" + } + + ] +} \ No newline at end of file diff --git a/rest-assured/src/test/resources/log4j.properties b/rest-assured/src/test/resources/log4j.properties new file mode 100644 index 0000000000..d3c6b9e783 --- /dev/null +++ b/rest-assured/src/test/resources/log4j.properties @@ -0,0 +1,16 @@ +## Logger configure +datestamp=yyyy-MM-dd HH:mm:ss +log4j.rootLogger=TRACE, file, console + +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.maxFileSize=1GB +log4j.appender.file.maxBackupIndex=5 +log4j.appender.file.File=log/rest-assured.log +log4j.appender.file.threshold=TRACE +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{${datestamp}} %5p: [%c] - %m%n + +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.Threshold=INFO +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{${datestamp}} %5p\: [%c] - %m%n \ No newline at end of file diff --git a/rest-assured/src/test/resources/odds.json b/rest-assured/src/test/resources/odds.json new file mode 100644 index 0000000000..8b3dc166c5 --- /dev/null +++ b/rest-assured/src/test/resources/odds.json @@ -0,0 +1,28 @@ +{ + "odds": [{ + "price": 1.30, + "status": 0, + "ck": 12.2, + "name": "1" + }, + { + "price": 5.25, + "status": 1, + "ck": 13.1, + "name": "X" + }, + { + "price": 2.70, + "status": 0, + "ck": 12.2, + "name": "0" + }, + { + "price": 1.20, + "status": 2, + "ck": 13.1, + "name": "2" + } + + ] +} \ No newline at end of file diff --git a/rest-assured/src/test/resources/teachers.xml b/rest-assured/src/test/resources/teachers.xml new file mode 100644 index 0000000000..9c073d5a38 --- /dev/null +++ b/rest-assured/src/test/resources/teachers.xml @@ -0,0 +1,10 @@ + + + math + physics + + + political education + english + + \ No newline at end of file diff --git a/rest-testing/.classpath b/rest-testing/.classpath deleted file mode 100644 index 8ebf6d9c31..0000000000 --- a/rest-testing/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rest-testing/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/rest-testing/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/rest-testing/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/rest-testing/.gitignore b/rest-testing/.gitignore index 83c05e60c8..601d2281e5 100644 --- a/rest-testing/.gitignore +++ b/rest-testing/.gitignore @@ -10,4 +10,8 @@ # Packaged files # *.jar *.war -*.ear \ No newline at end of file +*.ear + +.externalToolBuilders +.settings +.springBeans \ No newline at end of file diff --git a/rest-testing/.project b/rest-testing/.project deleted file mode 100644 index 1dc9ce93fe..0000000000 --- a/rest-testing/.project +++ /dev/null @@ -1,36 +0,0 @@ - - - rest-testing - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/rest-testing/.settings/.jsdtscope b/rest-testing/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/rest-testing/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/rest-testing/.settings/org.eclipse.jdt.core.prefs b/rest-testing/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/rest-testing/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/rest-testing/.settings/org.eclipse.jdt.ui.prefs b/rest-testing/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/rest-testing/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/rest-testing/.settings/org.eclipse.m2e.core.prefs b/rest-testing/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/rest-testing/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/rest-testing/.settings/org.eclipse.m2e.wtp.prefs b/rest-testing/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/rest-testing/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/rest-testing/.settings/org.eclipse.wst.common.component b/rest-testing/.settings/org.eclipse.wst.common.component deleted file mode 100644 index e98377cb0f..0000000000 --- a/rest-testing/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/rest-testing/.settings/org.eclipse.wst.common.project.facet.core.xml b/rest-testing/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f4ef8aa0a5..0000000000 --- a/rest-testing/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/rest-testing/.settings/org.eclipse.wst.jsdt.ui.superType.container b/rest-testing/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/rest-testing/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/rest-testing/.settings/org.eclipse.wst.jsdt.ui.superType.name b/rest-testing/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/rest-testing/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/rest-testing/.settings/org.eclipse.wst.validation.prefs b/rest-testing/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index cacf5451ae..0000000000 --- a/rest-testing/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,14 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.303.v201202090300 -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/rest-testing/.settings/org.eclipse.wst.ws.service.policy.prefs b/rest-testing/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/rest-testing/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/rest-testing/.springBeans b/rest-testing/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/rest-testing/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/rest-testing/README.md b/rest-testing/README.md index db7f0c8a86..54a2e98dda 100644 --- a/rest-testing/README.md +++ b/rest-testing/README.md @@ -2,6 +2,8 @@ ## REST Testing and Examples +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Test a REST API with Java](http://www.baeldung.com/2011/10/13/integration-testing-a-rest-api/) diff --git a/rest-testing/pom.xml b/rest-testing/pom.xml index b8fdc50a01..652f2ab601 100644 --- a/rest-testing/pom.xml +++ b/rest-testing/pom.xml @@ -1,176 +1,191 @@ - - 4.0.0 - org.baeldung - rest-testing - 0.1-SNAPSHOT + + 4.0.0 + com.baeldung + rest-testing + 0.1-SNAPSHOT - rest-testing + rest-testing - + - + - - com.google.guava - guava - ${guava.version} - + + com.google.guava + guava + ${guava.version} + - - commons-io - commons-io - 2.4 - + + commons-io + commons-io + 2.4 + - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + - + - - org.apache.httpcomponents - httpclient - ${httpclient.version} - - - org.apache.httpcomponents - httpcore - ${httpcore.version} - + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + org.apache.httpcomponents + httpcore + ${httpcore.version} + - + - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + - + - - org.slf4j - slf4j-api - ${org.slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - - org.slf4j - jcl-over-slf4j - ${org.slf4j.version} - - - - org.slf4j - log4j-over-slf4j - ${org.slf4j.version} - + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + runtime + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + - + - - junit - junit - ${junit.version} - test - + + junit + junit + ${junit.version} + test + - - org.hamcrest - hamcrest-core - ${org.hamcrest.version} - test - - - org.hamcrest - hamcrest-library - ${org.hamcrest.version} - test - + + org.hamcrest + hamcrest-core + ${org.hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + - - org.mockito - mockito-core - ${mockito.version} - test - + + org.mockito + mockito-core + ${mockito.version} + test + + + com.github.tomakehurst + wiremock + 1.58 + test + - + + info.cukes + cucumber-java + 1.2.4 + test + + + info.cukes + cucumber-junit + 1.2.4 + + - - rest-testing - - - src/main/resources - true - - + + rest-testing + + + src/main/resources + true + + - + - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + - + - + - - - 4.1.5.RELEASE + + + 2.7.2 - - 2.5.5 + + 1.7.13 + 1.1.3 - - 1.7.13 - 1.1.3 + + 5.1.3.Final - - 5.1.3.Final + + 19.0 + 3.4 - - 19.0 - 3.4 + + 1.3 + 4.12 + 1.10.19 - - 1.3 - 4.12 - 1.10.19 + 4.4.1 + 4.5 - 4.4.1 - 4.5 + 2.9.0 - 2.4.1 + + 3.5.1 + 2.6 + 2.19.1 + 2.7 + 1.4.18 - - 3.3 - 2.6 - 2.18.1 - 2.7 - 1.4.14 - - + \ No newline at end of file diff --git a/rest-testing/src/main/resources/Feature/cucumber.feature b/rest-testing/src/main/resources/Feature/cucumber.feature new file mode 100644 index 0000000000..99dd8249fe --- /dev/null +++ b/rest-testing/src/main/resources/Feature/cucumber.feature @@ -0,0 +1,10 @@ +Feature: Testing a REST API + Users should be able to submit GET and POST requests to a web service, represented by WireMock + + Scenario: Data Upload to a web service + When users upload data on a project + Then the server should handle it and return a success status + + Scenario: Data retrieval from a web service + When users want to get information on the Cucumber project + Then the requested data is returned \ No newline at end of file diff --git a/rest-testing/src/main/resources/cucumber.json b/rest-testing/src/main/resources/cucumber.json new file mode 100644 index 0000000000..38ebe066ac --- /dev/null +++ b/rest-testing/src/main/resources/cucumber.json @@ -0,0 +1,14 @@ +{ + "testing-framework": "cucumber", + "supported-language": + [ + "Ruby", + "Java", + "Javascript", + "PHP", + "Python", + "C++" + ], + + "website": "cucumber.io" +} \ No newline at end of file diff --git a/rest-testing/src/main/resources/wiremock_intro.json b/rest-testing/src/main/resources/wiremock_intro.json new file mode 100644 index 0000000000..ece2d35907 --- /dev/null +++ b/rest-testing/src/main/resources/wiremock_intro.json @@ -0,0 +1,5 @@ +{ + "testing-library": "WireMock", + "creator": "Tom Akehurst", + "website": "wiremock.org" +} \ No newline at end of file diff --git a/rest-testing/src/main/webapp/WEB-INF/api-servlet.xml b/rest-testing/src/main/webapp/WEB-INF/api-servlet.xml deleted file mode 100644 index 4c74be8912..0000000000 --- a/rest-testing/src/main/webapp/WEB-INF/api-servlet.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/rest-testing/src/main/webapp/WEB-INF/web.xml b/rest-testing/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 935beae648..0000000000 --- a/rest-testing/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - Spring MVC Application - - - - contextClass - - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - contextConfigLocation - org.baeldung.config - - - - org.springframework.web.context.ContextLoaderListener - - - - - api - org.springframework.web.servlet.DispatcherServlet - 1 - - - api - / - - - - - - - \ No newline at end of file diff --git a/rest-testing/src/test/java/com/baeldung/rest/cucumber/CucumberTest.java b/rest-testing/src/test/java/com/baeldung/rest/cucumber/CucumberTest.java new file mode 100644 index 0000000000..041de592e9 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/cucumber/CucumberTest.java @@ -0,0 +1,10 @@ +package com.baeldung.rest.cucumber; + +import org.junit.runner.RunWith; +import cucumber.api.CucumberOptions; +import cucumber.api.junit.Cucumber; + +@RunWith(Cucumber.class) +@CucumberOptions(features = "classpath:Feature") +public class CucumberTest { +} \ No newline at end of file diff --git a/rest-testing/src/test/java/com/baeldung/rest/cucumber/StepDefinition.java b/rest-testing/src/test/java/com/baeldung/rest/cucumber/StepDefinition.java new file mode 100644 index 0000000000..b461da8403 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/cucumber/StepDefinition.java @@ -0,0 +1,101 @@ +package com.baeldung.rest.cucumber; + +import com.github.tomakehurst.wiremock.WireMockServer; +import cucumber.api.java.en.Then; +import cucumber.api.java.en.When; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Scanner; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; +import static com.github.tomakehurst.wiremock.client.WireMock.containing; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +public class StepDefinition { + + private static final String CREATE_PATH = "/create"; + private static final String APPLICATION_JSON = "application/json"; + + private final InputStream jsonInputStream = this.getClass().getClassLoader().getResourceAsStream("cucumber.json"); + private final String jsonString = new Scanner(jsonInputStream, "UTF-8").useDelimiter("\\Z").next(); + + private final WireMockServer wireMockServer = new WireMockServer(); + private final CloseableHttpClient httpClient = HttpClients.createDefault(); + + @When("^users upload data on a project$") + public void usersUploadDataOnAProject() throws IOException { + wireMockServer.start(); + + configureFor("localhost", 8080); + stubFor(post(urlEqualTo(CREATE_PATH)) + .withHeader("content-type", equalTo(APPLICATION_JSON)) + .withRequestBody(containing("testing-framework")) + .willReturn(aResponse().withStatus(200))); + + HttpPost request = new HttpPost("http://localhost:8080/create"); + StringEntity entity = new StringEntity(jsonString); + request.addHeader("content-type", APPLICATION_JSON); + request.setEntity(entity); + HttpResponse response = httpClient.execute(request); + + assertEquals(200, response.getStatusLine().getStatusCode()); + verify(postRequestedFor(urlEqualTo(CREATE_PATH)) + .withHeader("content-type", equalTo(APPLICATION_JSON))); + + wireMockServer.stop(); + } + + @When("^users want to get information on the (.+) project$") + public void usersGetInformationOnAProject(String projectName) throws IOException { + wireMockServer.start(); + + configureFor("localhost", 8080); + stubFor(get(urlEqualTo("/projects/cucumber")).withHeader("accept", equalTo(APPLICATION_JSON)) + .willReturn(aResponse().withBody(jsonString))); + + HttpGet request = new HttpGet("http://localhost:8080/projects/" + projectName.toLowerCase()); + request.addHeader("accept", APPLICATION_JSON); + HttpResponse httpResponse = httpClient.execute(request); + String responseString = convertResponseToString(httpResponse); + + assertThat(responseString, containsString("\"testing-framework\": \"cucumber\"")); + assertThat(responseString, containsString("\"website\": \"cucumber.io\"")); + verify(getRequestedFor(urlEqualTo("/projects/cucumber")).withHeader("accept", equalTo(APPLICATION_JSON))); + + wireMockServer.stop(); + } + + @Then("^the server should handle it and return a success status$") + public void theServerShouldReturnASuccessStatus() { + } + + @Then("^the requested data is returned$") + public void theRequestedDataIsReturned() { + } + + private String convertResponseToString(HttpResponse response) throws IOException { + InputStream responseStream = response.getEntity().getContent(); + Scanner scanner = new Scanner(responseStream, "UTF-8"); + String responseString = scanner.useDelimiter("\\Z").next(); + scanner.close(); + return responseString; + } +} \ No newline at end of file diff --git a/rest-testing/src/test/java/com/baeldung/rest/wiremock/introduction/JUnitManaged.java b/rest-testing/src/test/java/com/baeldung/rest/wiremock/introduction/JUnitManaged.java new file mode 100644 index 0000000000..664c3fac78 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/wiremock/introduction/JUnitManaged.java @@ -0,0 +1,144 @@ +package com.baeldung.rest.wiremock.introduction; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Scanner; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.containing; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.matching; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.junit.Assert.assertEquals; + +public class JUnitManaged { + + private static final String BAELDUNG_WIREMOCK_PATH = "/baeldung/wiremock"; + private static final String APPLICATION_JSON = "application/json"; + + @Rule + public WireMockRule wireMockRule = new WireMockRule(); + + @Test + public void givenJUnitManagedServer_whenMatchingURL_thenCorrect() throws IOException { + stubFor(get(urlPathMatching("/baeldung/.*")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", APPLICATION_JSON) + .withBody("\"testing-library\": \"WireMock\""))); + + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock"); + HttpResponse httpResponse = httpClient.execute(request); + String stringResponse = convertHttpResponseToString(httpResponse); + + verify(getRequestedFor(urlEqualTo(BAELDUNG_WIREMOCK_PATH))); + assertEquals(200, httpResponse.getStatusLine().getStatusCode()); + assertEquals(APPLICATION_JSON, httpResponse.getFirstHeader("Content-Type").getValue()); + assertEquals("\"testing-library\": \"WireMock\"", stringResponse); + } + + @Test + public void givenJUnitManagedServer_whenMatchingHeaders_thenCorrect() throws IOException { + stubFor(get(urlPathEqualTo(BAELDUNG_WIREMOCK_PATH)) + .withHeader("Accept", matching("text/.*")) + .willReturn(aResponse() + .withStatus(503) + .withHeader("Content-Type", "text/html") + .withBody("!!! Service Unavailable !!!"))); + + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock"); + request.addHeader("Accept", "text/html"); + HttpResponse httpResponse = httpClient.execute(request); + String stringResponse = convertHttpResponseToString(httpResponse); + + verify(getRequestedFor(urlEqualTo(BAELDUNG_WIREMOCK_PATH))); + assertEquals(503, httpResponse.getStatusLine().getStatusCode()); + assertEquals("text/html", httpResponse.getFirstHeader("Content-Type").getValue()); + assertEquals("!!! Service Unavailable !!!", stringResponse); + } + + @Test + public void givenJUnitManagedServer_whenMatchingBody_thenCorrect() throws IOException { + stubFor(post(urlEqualTo(BAELDUNG_WIREMOCK_PATH)) + .withHeader("Content-Type", equalTo(APPLICATION_JSON)) + .withRequestBody(containing("\"testing-library\": \"WireMock\"")) + .withRequestBody(containing("\"creator\": \"Tom Akehurst\"")) + .withRequestBody(containing("\"website\": \"wiremock.org\"")) + .willReturn(aResponse().withStatus(200))); + + InputStream jsonInputStream = this.getClass().getClassLoader().getResourceAsStream("wiremock_intro.json"); + String jsonString = convertInputStreamToString(jsonInputStream); + StringEntity entity = new StringEntity(jsonString); + + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpPost request = new HttpPost("http://localhost:8080/baeldung/wiremock"); + request.addHeader("Content-Type", APPLICATION_JSON); + request.setEntity(entity); + HttpResponse response = httpClient.execute(request); + + verify(postRequestedFor(urlEqualTo(BAELDUNG_WIREMOCK_PATH)) + .withHeader("Content-Type", equalTo(APPLICATION_JSON))); + assertEquals(200, response.getStatusLine().getStatusCode()); + } + + @Test + public void givenJUnitManagedServer_whenNotUsingPriority_thenCorrect() throws IOException { + stubFor(get(urlPathMatching("/baeldung/.*")).willReturn(aResponse().withStatus(200))); + stubFor(get(urlPathEqualTo(BAELDUNG_WIREMOCK_PATH)).withHeader("Accept", matching("text/.*")).willReturn(aResponse().withStatus(503))); + + HttpResponse httpResponse = generateClientAndReceiveResponseForPriorityTests(); + + verify(getRequestedFor(urlEqualTo(BAELDUNG_WIREMOCK_PATH))); + assertEquals(503, httpResponse.getStatusLine().getStatusCode()); + } + + @Test + public void givenJUnitManagedServer_whenUsingPriority_thenCorrect() throws IOException { + stubFor(get(urlPathMatching("/baeldung/.*")).atPriority(1).willReturn(aResponse().withStatus(200))); + stubFor(get(urlPathEqualTo(BAELDUNG_WIREMOCK_PATH)).atPriority(2).withHeader("Accept", matching("text/.*")).willReturn(aResponse().withStatus(503))); + + HttpResponse httpResponse = generateClientAndReceiveResponseForPriorityTests(); + + verify(getRequestedFor(urlEqualTo(BAELDUNG_WIREMOCK_PATH))); + assertEquals(200, httpResponse.getStatusLine().getStatusCode()); + } + + private static String convertHttpResponseToString(HttpResponse httpResponse) throws IOException { + InputStream inputStream = httpResponse.getEntity().getContent(); + return convertInputStreamToString(inputStream); + } + + private static String convertInputStreamToString(InputStream inputStream) { + Scanner scanner = new Scanner(inputStream, "UTF-8"); + String string = scanner.useDelimiter("\\Z").next(); + scanner.close(); + return string; + } + + private HttpResponse generateClientAndReceiveResponseForPriorityTests() throws IOException { + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock"); + request.addHeader("Accept", "text/xml"); + return httpClient.execute(request); + } +} \ No newline at end of file diff --git a/rest-testing/src/test/java/com/baeldung/rest/wiremock/introduction/ProgrammaticallyManaged.java b/rest-testing/src/test/java/com/baeldung/rest/wiremock/introduction/ProgrammaticallyManaged.java new file mode 100644 index 0000000000..ad7caa52b5 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/wiremock/introduction/ProgrammaticallyManaged.java @@ -0,0 +1,54 @@ +package com.baeldung.rest.wiremock.introduction; + +import com.github.tomakehurst.wiremock.WireMockServer; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Scanner; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.configureFor; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.junit.Assert.assertEquals; + +public class ProgrammaticallyManaged { + + private static final String BAELDUNG_PATH = "/baeldung"; + + private WireMockServer wireMockServer = new WireMockServer(); + private CloseableHttpClient httpClient = HttpClients.createDefault(); + + @Test + public void givenProgrammaticallyManagedServer_whenUsingSimpleStubbing_thenCorrect() throws IOException { + wireMockServer.start(); + + configureFor("localhost", 8080); + stubFor(get(urlEqualTo(BAELDUNG_PATH)).willReturn(aResponse().withBody("Welcome to Baeldung!"))); + + HttpGet request = new HttpGet("http://localhost:8080/baeldung"); + HttpResponse httpResponse = httpClient.execute(request); + String stringResponse = convertResponseToString(httpResponse); + + verify(getRequestedFor(urlEqualTo(BAELDUNG_PATH))); + assertEquals("Welcome to Baeldung!", stringResponse); + + wireMockServer.stop(); + } + + private static String convertResponseToString(HttpResponse response) throws IOException { + InputStream responseStream = response.getEntity().getContent(); + Scanner scanner = new Scanner(responseStream, "UTF-8"); + String stringResponse = scanner.useDelimiter("\\Z").next(); + scanner.close(); + return stringResponse; + } +} \ No newline at end of file diff --git a/resteasy/README.md b/resteasy/README.md new file mode 100644 index 0000000000..722f1dfe93 --- /dev/null +++ b/resteasy/README.md @@ -0,0 +1,8 @@ +========= + +## A Guide to RESTEasy + + +### Relevant Articles: +- [A Guide to RESTEasy](http://www.baeldung.com/resteasy-tutorial) +- [RESTEasy Client API](http://www.baeldung.com/resteasy-client-tutorial) diff --git a/resteasy/pom.xml b/resteasy/pom.xml new file mode 100644 index 0000000000..ec9e87b0d1 --- /dev/null +++ b/resteasy/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + com.baeldung + resteasy-tutorial + 1.0 + war + + + 3.0.14.Final + + + + RestEasyTutorial + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + + + + org.jboss.resteasy + resteasy-servlet-initializer + ${resteasy.version} + + + + + org.jboss.resteasy + resteasy-client + ${resteasy.version} + + + + + + org.jboss.resteasy + resteasy-jaxb-provider + ${resteasy.version} + + + + org.jboss.resteasy + resteasy-jackson-provider + ${resteasy.version} + + + + + + junit + junit + 4.4 + + + + commons-io + commons-io + 2.4 + + + + + + \ No newline at end of file diff --git a/resteasy/src/main/java/com/baeldung/client/ServicesInterface.java b/resteasy/src/main/java/com/baeldung/client/ServicesInterface.java new file mode 100644 index 0000000000..19ad0c1ec3 --- /dev/null +++ b/resteasy/src/main/java/com/baeldung/client/ServicesInterface.java @@ -0,0 +1,36 @@ +package com.baeldung.client; + +import com.baeldung.model.Movie; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; + +@Path("/movies") +public interface ServicesInterface { + + @GET + @Path("/getinfo") + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + Movie movieByImdbId(@QueryParam("imdbId") String imdbId); + + @GET + @Path("/listmovies") + @Produces({ "application/json" }) + List listMovies(); + + @POST + @Path("/addmovie") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + Response addMovie(Movie movie); + + @PUT + @Path("/updatemovie") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + Response updateMovie(Movie movie); + + @DELETE + @Path("/deletemovie") + Response deleteMovie(@QueryParam("imdbId") String imdbId); + +} diff --git a/resteasy/src/main/java/com/baeldung/model/Movie.java b/resteasy/src/main/java/com/baeldung/model/Movie.java new file mode 100644 index 0000000000..408f2144fb --- /dev/null +++ b/resteasy/src/main/java/com/baeldung/model/Movie.java @@ -0,0 +1,66 @@ +package com.baeldung.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "movie", propOrder = { "imdbId", "title" }) +public class Movie { + + protected String imdbId; + protected String title; + + public Movie(String imdbId, String title) { + this.imdbId = imdbId; + this.title = title; + } + + public Movie() {} + + public String getImdbId() { + return imdbId; + } + + public void setImdbId(String imdbId) { + this.imdbId = imdbId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Movie movie = (Movie) o; + + if (imdbId != null ? !imdbId.equals(movie.imdbId) : movie.imdbId != null) + return false; + return title != null ? title.equals(movie.title) : movie.title == null; + + } + + @Override + public int hashCode() { + int result = imdbId != null ? imdbId.hashCode() : 0; + result = 31 * result + (title != null ? title.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Movie{" + + "imdbId='" + imdbId + '\'' + + ", title='" + title + '\'' + + '}'; + } +} diff --git a/resteasy/src/main/java/com/baeldung/server/MovieCrudService.java b/resteasy/src/main/java/com/baeldung/server/MovieCrudService.java new file mode 100644 index 0000000000..b7f3215f3f --- /dev/null +++ b/resteasy/src/main/java/com/baeldung/server/MovieCrudService.java @@ -0,0 +1,83 @@ +package com.baeldung.server; + +import com.baeldung.model.Movie; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Path("/movies") +public class MovieCrudService { + + private Map inventory = new HashMap(); + + @GET + @Path("/getinfo") + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public Movie movieByImdbId(@QueryParam("imdbId") String imdbId) { + + System.out.println("*** Calling getinfo for a given ImdbID***"); + + if (inventory.containsKey(imdbId)) { + return inventory.get(imdbId); + } else + return null; + } + + @POST + @Path("/addmovie") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public Response addMovie(Movie movie) { + + System.out.println("*** Calling addMovie ***"); + + if (null != inventory.get(movie.getImdbId())) { + return Response.status(Response.Status.NOT_MODIFIED).entity("Movie is Already in the database.").build(); + } + + inventory.put(movie.getImdbId(), movie); + return Response.status(Response.Status.CREATED).build(); + } + + @PUT + @Path("/updatemovie") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public Response updateMovie(Movie movie) { + + System.out.println("*** Calling updateMovie ***"); + + if (null == inventory.get(movie.getImdbId())) { + return Response.status(Response.Status.NOT_MODIFIED).entity("Movie is not in the database.\nUnable to Update").build(); + } + + inventory.put(movie.getImdbId(), movie); + return Response.status(Response.Status.OK).build(); + } + + @DELETE + @Path("/deletemovie") + public Response deleteMovie(@QueryParam("imdbId") String imdbId) { + + System.out.println("*** Calling deleteMovie ***"); + + if (null == inventory.get(imdbId)) { + return Response.status(Response.Status.NOT_FOUND).entity("Movie is not in the database.\nUnable to Delete").build(); + } + + inventory.remove(imdbId); + return Response.status(Response.Status.OK).build(); + } + + @GET + @Path("/listmovies") + @Produces({ "application/json" }) + public List listMovies() { + + return inventory.values().stream().collect(Collectors.toCollection(ArrayList::new)); + } + +} diff --git a/resteasy/src/main/java/com/baeldung/server/RestEasyServices.java b/resteasy/src/main/java/com/baeldung/server/RestEasyServices.java new file mode 100644 index 0000000000..7726e49f38 --- /dev/null +++ b/resteasy/src/main/java/com/baeldung/server/RestEasyServices.java @@ -0,0 +1,32 @@ +package com.baeldung.server; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +@ApplicationPath("/rest") +public class RestEasyServices extends Application { + + private Set singletons = new HashSet(); + + public RestEasyServices() { + singletons.add(new MovieCrudService()); + } + + @Override + public Set getSingletons() { + return singletons; + } + + @Override + public Set> getClasses() { + return super.getClasses(); + } + + @Override + public Map getProperties() { + return super.getProperties(); + } +} diff --git a/resteasy/src/main/webapp/WEB-INF/classes/logback.xml b/resteasy/src/main/webapp/WEB-INF/classes/logback.xml new file mode 100644 index 0000000000..d94e9f71ab --- /dev/null +++ b/resteasy/src/main/webapp/WEB-INF/classes/logback.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/resteasy/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/resteasy/src/main/webapp/WEB-INF/jboss-deployment-structure.xml new file mode 100644 index 0000000000..cb258374a1 --- /dev/null +++ b/resteasy/src/main/webapp/WEB-INF/jboss-deployment-structure.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/resteasy/src/main/webapp/WEB-INF/jboss-web.xml b/resteasy/src/main/webapp/WEB-INF/jboss-web.xml new file mode 100644 index 0000000000..694bb71332 --- /dev/null +++ b/resteasy/src/main/webapp/WEB-INF/jboss-web.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resteasy/src/main/webapp/WEB-INF/web.xml b/resteasy/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..d5f00293f4 --- /dev/null +++ b/resteasy/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,13 @@ + + + + RestEasy Example + + + resteasy.servlet.mapping.prefix + /rest + + + \ No newline at end of file diff --git a/resteasy/src/test/java/com/baeldung/server/RestEasyClientTest.java b/resteasy/src/test/java/com/baeldung/server/RestEasyClientTest.java new file mode 100644 index 0000000000..ef18b0f23f --- /dev/null +++ b/resteasy/src/test/java/com/baeldung/server/RestEasyClientTest.java @@ -0,0 +1,179 @@ +package com.baeldung.server; + +import com.baeldung.client.ServicesInterface; +import com.baeldung.model.Movie; +import org.apache.commons.io.IOUtils; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.ObjectMapper; +import org.jboss.resteasy.client.jaxrs.ResteasyClient; +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; +import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; +import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine; +import org.junit.Before; +import org.junit.Test; +import javax.naming.NamingException; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.List; +import java.util.Locale; + +public class RestEasyClientTest { + + public static final UriBuilder FULL_PATH = UriBuilder.fromPath("http://127.0.0.1:8080/RestEasyTutorial/rest"); + Movie transformerMovie = null; + Movie batmanMovie = null; + ObjectMapper jsonMapper = null; + + @Before + public void setup() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NamingException { + + jsonMapper = new ObjectMapper().configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); + jsonMapper.configure(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); + SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH); + jsonMapper.setDateFormat(sdf); + + try (InputStream inputStream = new RestEasyClientTest().getClass().getResourceAsStream("./movies/transformer.json")) { + String transformerMovieAsString = String.format(IOUtils.toString(inputStream, StandardCharsets.UTF_8)); + transformerMovie = jsonMapper.readValue(transformerMovieAsString, Movie.class); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Test is going to die ...", e); + } + + try (InputStream inputStream = new RestEasyClientTest().getClass().getResourceAsStream("./movies/batman.json")) { + String batmanMovieAsString = String.format(IOUtils.toString(inputStream, StandardCharsets.UTF_8)); + batmanMovie = jsonMapper.readValue(batmanMovieAsString, Movie.class); + + } catch (Exception e) { + throw new RuntimeException("Test is going to die ...", e); + } + } + + @Test + public void testListAllMovies() { + + ResteasyClient client = new ResteasyClientBuilder().build(); + ResteasyWebTarget target = client.target(FULL_PATH); + ServicesInterface proxy = target.proxy(ServicesInterface.class); + + Response moviesResponse = proxy.addMovie(transformerMovie); + moviesResponse.close(); + moviesResponse = proxy.addMovie(batmanMovie); + moviesResponse.close(); + + List movies = proxy.listMovies(); + System.out.println(movies); + } + + @Test + public void testMovieByImdbId() { + + String transformerImdbId = "tt0418279"; + + ResteasyClient client = new ResteasyClientBuilder().build(); + ResteasyWebTarget target = client.target(FULL_PATH); + ServicesInterface proxy = target.proxy(ServicesInterface.class); + + Response moviesResponse = proxy.addMovie(transformerMovie); + moviesResponse.close(); + + Movie movies = proxy.movieByImdbId(transformerImdbId); + System.out.println(movies); + } + + @Test + public void testAddMovie() { + + ResteasyClient client = new ResteasyClientBuilder().build(); + ResteasyWebTarget target = client.target(FULL_PATH); + ServicesInterface proxy = target.proxy(ServicesInterface.class); + + Response moviesResponse = proxy.addMovie(batmanMovie); + moviesResponse.close(); + moviesResponse = proxy.addMovie(transformerMovie); + + if (moviesResponse.getStatus() != Response.Status.CREATED.getStatusCode()) { + System.out.println("Failed : HTTP error code : " + moviesResponse.getStatus()); + } + + moviesResponse.close(); + System.out.println("Response Code: " + moviesResponse.getStatus()); + } + + @Test + public void testAddMovieMultiConnection() { + + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); + CloseableHttpClient httpClient = HttpClients.custom() + .setConnectionManager(cm) + .build(); + ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient); + ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build(); + ResteasyWebTarget target = client.target(FULL_PATH); + ServicesInterface proxy = target.proxy(ServicesInterface.class); + + Response batmanResponse = proxy.addMovie(batmanMovie); + Response transformerResponse = proxy.addMovie(transformerMovie); + + if (batmanResponse.getStatus() != Response.Status.CREATED.getStatusCode()) { + System.out.println("Batman Movie creation Failed : HTTP error code : " + batmanResponse.getStatus()); + } + if (batmanResponse.getStatus() != Response.Status.CREATED.getStatusCode()) { + System.out.println("Batman Movie creation Failed : HTTP error code : " + batmanResponse.getStatus()); + } + + batmanResponse.close(); + transformerResponse.close(); + cm.close(); + + + + } + + @Test + public void testDeleteMovie() { + + ResteasyClient client = new ResteasyClientBuilder().build(); + ResteasyWebTarget target = client.target(FULL_PATH); + ServicesInterface proxy = target.proxy(ServicesInterface.class); + + Response moviesResponse = proxy.addMovie(batmanMovie); + moviesResponse.close(); + moviesResponse = proxy.deleteMovie(batmanMovie.getImdbId()); + + if (moviesResponse.getStatus() != Response.Status.OK.getStatusCode()) { + System.out.println(moviesResponse.readEntity(String.class)); + throw new RuntimeException("Failed : HTTP error code : " + moviesResponse.getStatus()); + } + + moviesResponse.close(); + System.out.println("Response Code: " + moviesResponse.getStatus()); + } + + @Test + public void testUpdateMovie() { + + ResteasyClient client = new ResteasyClientBuilder().build(); + ResteasyWebTarget target = client.target(FULL_PATH); + ServicesInterface proxy = target.proxy(ServicesInterface.class); + + Response moviesResponse = proxy.addMovie(batmanMovie); + moviesResponse.close(); + batmanMovie.setTitle("Batman Begins"); + moviesResponse = proxy.updateMovie(batmanMovie); + + if (moviesResponse.getStatus() != Response.Status.OK.getStatusCode()) { + System.out.println("Failed : HTTP error code : " + moviesResponse.getStatus()); + } + + moviesResponse.close(); + System.out.println("Response Code: " + moviesResponse.getStatus()); + } + +} \ No newline at end of file diff --git a/resteasy/src/test/resources/com/baeldung/server/movies/batman.json b/resteasy/src/test/resources/com/baeldung/server/movies/batman.json new file mode 100644 index 0000000000..82aaaa8f40 --- /dev/null +++ b/resteasy/src/test/resources/com/baeldung/server/movies/batman.json @@ -0,0 +1,4 @@ +{ + "title": "Batman", + "imdbId": "tt0096895" +} \ No newline at end of file diff --git a/resteasy/src/test/resources/com/baeldung/server/movies/transformer.json b/resteasy/src/test/resources/com/baeldung/server/movies/transformer.json new file mode 100644 index 0000000000..634cefc73c --- /dev/null +++ b/resteasy/src/test/resources/com/baeldung/server/movies/transformer.json @@ -0,0 +1,4 @@ +{ + "title": "Transformers", + "imdbId": "tt0418279" +} \ No newline at end of file diff --git a/routing-in-play/.gitignore b/routing-in-play/.gitignore new file mode 100644 index 0000000000..eb372fc719 --- /dev/null +++ b/routing-in-play/.gitignore @@ -0,0 +1,8 @@ +logs +target +/.idea +/.idea_modules +/.classpath +/.project +/.settings +/RUNNING_PID diff --git a/routing-in-play/LICENSE b/routing-in-play/LICENSE new file mode 100644 index 0000000000..4baedcb95f --- /dev/null +++ b/routing-in-play/LICENSE @@ -0,0 +1,8 @@ +This software is licensed under the Apache 2 license, quoted below. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with +the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific +language governing permissions and limitations under the License. \ No newline at end of file diff --git a/routing-in-play/README b/routing-in-play/README new file mode 100644 index 0000000000..f21d092edf --- /dev/null +++ b/routing-in-play/README @@ -0,0 +1,49 @@ +This is your new Play application +================================= + +This file will be packaged with your application when using `activator dist`. + +There are several demonstration files available in this template. + +Controllers +=========== + +- HomeController.java: + + Shows how to handle simple HTTP requests. + +- AsyncController.java: + + Shows how to do asynchronous programming when handling a request. + +- CountController.java: + + Shows how to inject a component into a controller and use the component when + handling requests. + +Components +========== + +- Module.java: + + Shows how to use Guice to bind all the components needed by your application. + +- Counter.java: + + An example of a component that contains state, in this case a simple counter. + +- ApplicationTimer.java: + + An example of a component that starts when the application starts and stops + when the application stops. + +Filters +======= + +- Filters.java: + + Creates the list of HTTP filters used by your application. + +- ExampleFilter.java + + A simple filter that adds a header to every response. \ No newline at end of file diff --git a/routing-in-play/app/Filters.java b/routing-in-play/app/Filters.java new file mode 100644 index 0000000000..255de8ca93 --- /dev/null +++ b/routing-in-play/app/Filters.java @@ -0,0 +1,46 @@ +import javax.inject.*; +import play.*; +import play.mvc.EssentialFilter; +import play.http.HttpFilters; +import play.mvc.*; + +import filters.ExampleFilter; + +/** + * This class configures filters that run on every request. This + * class is queried by Play to get a list of filters. + * + * Play will automatically use filters from any class called + * Filters that is placed the root package. You can load filters + * from a different class by adding a `play.http.filters` setting to + * the application.conf configuration file. + */ +@Singleton +public class Filters implements HttpFilters { + + private final Environment env; + private final EssentialFilter exampleFilter; + + /** + * @param env Basic environment settings for the current application. + * @param exampleFilter A demonstration filter that adds a header to + */ + @Inject + public Filters(Environment env, ExampleFilter exampleFilter) { + this.env = env; + this.exampleFilter = exampleFilter; + } + + @Override + public EssentialFilter[] filters() { + // Use the example filter if we're running development mode. If + // we're running in production or test mode then don't use any + // filters at all. + if (env.mode().equals(Mode.DEV)) { + return new EssentialFilter[] { exampleFilter }; + } else { + return new EssentialFilter[] {}; + } + } + +} diff --git a/routing-in-play/app/Module.java b/routing-in-play/app/Module.java new file mode 100644 index 0000000000..6e7d1766ef --- /dev/null +++ b/routing-in-play/app/Module.java @@ -0,0 +1,31 @@ +import com.google.inject.AbstractModule; +import java.time.Clock; + +import services.ApplicationTimer; +import services.AtomicCounter; +import services.Counter; + +/** + * This class is a Guice module that tells Guice how to bind several + * different types. This Guice module is created when the Play + * application starts. + * + * Play will automatically use any class called `Module` that is in + * the root package. You can create modules in other locations by + * adding `play.modules.enabled` settings to the `application.conf` + * configuration file. + */ +public class Module extends AbstractModule { + + @Override + public void configure() { + // Use the system clock as the default implementation of Clock + bind(Clock.class).toInstance(Clock.systemDefaultZone()); + // Ask Guice to create an instance of ApplicationTimer when the + // application starts. + bind(ApplicationTimer.class).asEagerSingleton(); + // Set AtomicCounter as the implementation for Counter. + bind(Counter.class).to(AtomicCounter.class); + } + +} diff --git a/routing-in-play/app/controllers/HomeController.java b/routing-in-play/app/controllers/HomeController.java new file mode 100644 index 0000000000..6e340d594f --- /dev/null +++ b/routing-in-play/app/controllers/HomeController.java @@ -0,0 +1,33 @@ +package controllers; + +import play.mvc.*; + +import views.html.*; + +/** + * This controller contains an action to handle HTTP requests + * to the application's home page. + */ +public class HomeController extends Controller { + + /** + * An action that renders an HTML page with a welcome message. + * The configuration in the routes file means that + * this method will be called when the application receives a + * GET request with a path of /. + */ + public Result index(String author,int id) { + return ok("Routing in Play by:"+author+" ID:"+id); + } + public Result greet(String name,int age) { + return ok("Hello "+name+", you are "+age+" years old"); + } + public Result introduceMe(String data) { + String[] clientData=data.split(","); + return ok("Your name is "+clientData[0]+", you are "+clientData[1]+" years old"); + } + public Result squareMe(Long num) { + return ok(num+" Squared is "+(num*num)); + } + +} diff --git a/routing-in-play/app/filters/ExampleFilter.java b/routing-in-play/app/filters/ExampleFilter.java new file mode 100644 index 0000000000..67a6a36cc3 --- /dev/null +++ b/routing-in-play/app/filters/ExampleFilter.java @@ -0,0 +1,45 @@ +package filters; + +import akka.stream.Materializer; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Executor; +import java.util.function.Function; +import javax.inject.*; +import play.mvc.*; +import play.mvc.Http.RequestHeader; + + +/** + * This is a simple filter that adds a header to all requests. It's + * added to the application's list of filters by the + * {@link Filters} class. + */ +@Singleton +public class ExampleFilter extends Filter { + + private final Executor exec; + + /** + * @param mat This object is needed to handle streaming of requests + * and responses. + * @param exec This class is needed to execute code asynchronously. + * It is used below by the thenAsyncApply method. + */ + @Inject + public ExampleFilter(Materializer mat, Executor exec) { + super(mat); + this.exec = exec; + } + + @Override + public CompletionStage apply( + Function> next, + RequestHeader requestHeader) { + + return next.apply(requestHeader).thenApplyAsync( + result -> result.withHeader("X-ExampleFilter", "foo"), + exec + ); + } + +} diff --git a/routing-in-play/app/services/ApplicationTimer.java b/routing-in-play/app/services/ApplicationTimer.java new file mode 100644 index 0000000000..a951562b1d --- /dev/null +++ b/routing-in-play/app/services/ApplicationTimer.java @@ -0,0 +1,50 @@ +package services; + +import java.time.Clock; +import java.time.Instant; +import java.util.concurrent.CompletableFuture; +import javax.inject.*; +import play.Logger; +import play.inject.ApplicationLifecycle; + +/** + * This class demonstrates how to run code when the + * application starts and stops. It starts a timer when the + * application starts. When the application stops it prints out how + * long the application was running for. + * + * This class is registered for Guice dependency injection in the + * {@link Module} class. We want the class to start when the application + * starts, so it is registered as an "eager singleton". See the code + * in the {@link Module} class to see how this happens. + * + * This class needs to run code when the server stops. It uses the + * application's {@link ApplicationLifecycle} to register a stop hook. + */ +@Singleton +public class ApplicationTimer { + + private final Clock clock; + private final ApplicationLifecycle appLifecycle; + private final Instant start; + + @Inject + public ApplicationTimer(Clock clock, ApplicationLifecycle appLifecycle) { + this.clock = clock; + this.appLifecycle = appLifecycle; + // This code is called when the application starts. + start = clock.instant(); + Logger.info("ApplicationTimer demo: Starting application at " + start); + + // When the application starts, register a stop hook with the + // ApplicationLifecycle object. The code inside the stop hook will + // be run when the application stops. + appLifecycle.addStopHook(() -> { + Instant stop = clock.instant(); + Long runningTime = stop.getEpochSecond() - start.getEpochSecond(); + Logger.info("ApplicationTimer demo: Stopping application at " + clock.instant() + " after " + runningTime + "s."); + return CompletableFuture.completedFuture(null); + }); + } + +} diff --git a/routing-in-play/app/services/AtomicCounter.java b/routing-in-play/app/services/AtomicCounter.java new file mode 100644 index 0000000000..41f741cbf7 --- /dev/null +++ b/routing-in-play/app/services/AtomicCounter.java @@ -0,0 +1,26 @@ +package services; + +import java.util.concurrent.atomic.AtomicInteger; +import javax.inject.*; + +/** + * This class is a concrete implementation of the {@link Counter} trait. + * It is configured for Guice dependency injection in the {@link Module} + * class. + * + * This class has a {@link Singleton} annotation because we need to make + * sure we only use one counter per application. Without this + * annotation we would get a new instance every time a {@link Counter} is + * injected. + */ +@Singleton +public class AtomicCounter implements Counter { + + private final AtomicInteger atomicCounter = new AtomicInteger(); + + @Override + public int nextCount() { + return atomicCounter.getAndIncrement(); + } + +} diff --git a/routing-in-play/app/services/Counter.java b/routing-in-play/app/services/Counter.java new file mode 100644 index 0000000000..dadad8b09d --- /dev/null +++ b/routing-in-play/app/services/Counter.java @@ -0,0 +1,13 @@ +package services; + +/** + * This interface demonstrates how to create a component that is injected + * into a controller. The interface represents a counter that returns a + * incremented number each time it is called. + * + * The {@link Modules} class binds this interface to the + * {@link AtomicCounter} implementation. + */ +public interface Counter { + int nextCount(); +} diff --git a/routing-in-play/app/views/index.scala.html b/routing-in-play/app/views/index.scala.html new file mode 100644 index 0000000000..4539f5a10b --- /dev/null +++ b/routing-in-play/app/views/index.scala.html @@ -0,0 +1,20 @@ +@* + * This template takes a single argument, a String containing a + * message to display. + *@ +@(message: String) + +@* + * Call the `main` template with two arguments. The first + * argument is a `String` with the title of the page, the second + * argument is an `Html` object containing the body of the page. + *@ +@main("Welcome to Play") { + + @* + * Get an `Html` object by calling the built-in Play welcome + * template and passing a `String` message. + *@ + @play20.welcome(message, style = "Java") + +} diff --git a/routing-in-play/app/views/main.scala.html b/routing-in-play/app/views/main.scala.html new file mode 100644 index 0000000000..9414f4be6e --- /dev/null +++ b/routing-in-play/app/views/main.scala.html @@ -0,0 +1,23 @@ +@* + * This template is called from the `index` template. This template + * handles the rendering of the page header and body tags. It takes + * two arguments, a `String` for the title of the page and an `Html` + * object to insert into the body of the page. + *@ +@(title: String)(content: Html) + + + + + @* Here's where we render the page title `String`. *@ + @title + + + + + + @* And here's where we render the `Html` object containing + * the page content. *@ + @content + + diff --git a/routing-in-play/bin/activator b/routing-in-play/bin/activator new file mode 100644 index 0000000000..a8b11d482f --- /dev/null +++ b/routing-in-play/bin/activator @@ -0,0 +1,397 @@ +#!/usr/bin/env bash + +### ------------------------------- ### +### Helper methods for BASH scripts ### +### ------------------------------- ### + +realpath () { +( + TARGET_FILE="$1" + FIX_CYGPATH="$2" + + cd "$(dirname "$TARGET_FILE")" + TARGET_FILE=$(basename "$TARGET_FILE") + + COUNT=0 + while [ -L "$TARGET_FILE" -a $COUNT -lt 100 ] + do + TARGET_FILE=$(readlink "$TARGET_FILE") + cd "$(dirname "$TARGET_FILE")" + TARGET_FILE=$(basename "$TARGET_FILE") + COUNT=$(($COUNT + 1)) + done + + # make sure we grab the actual windows path, instead of cygwin's path. + if [[ "x$FIX_CYGPATH" != "x" ]]; then + echo "$(cygwinpath "$(pwd -P)/$TARGET_FILE")" + else + echo "$(pwd -P)/$TARGET_FILE" + fi +) +} + + +# Uses uname to detect if we're in the odd cygwin environment. +is_cygwin() { + local os=$(uname -s) + case "$os" in + CYGWIN*) return 0 ;; + *) return 1 ;; + esac +} + +# TODO - Use nicer bash-isms here. +CYGWIN_FLAG=$(if is_cygwin; then echo true; else echo false; fi) + + +# This can fix cygwin style /cygdrive paths so we get the +# windows style paths. +cygwinpath() { + local file="$1" + if [[ "$CYGWIN_FLAG" == "true" ]]; then + echo $(cygpath -w $file) + else + echo $file + fi +} + +# Make something URI friendly +make_url() { + url="$1" + local nospaces=${url// /%20} + if is_cygwin; then + echo "/${nospaces//\\//}" + else + echo "$nospaces" + fi +} + +declare -a residual_args +declare -a java_args +declare -a scalac_args +declare -a sbt_commands +declare java_cmd=java +declare java_version +declare -r real_script_path="$(realpath "$0")" +declare -r sbt_home="$(realpath "$(dirname "$(dirname "$real_script_path")")")" +declare -r sbt_bin_dir="$(dirname "$real_script_path")" +declare -r app_version="1.3.10" + +declare -r script_name=activator +declare -r java_opts=( "${ACTIVATOR_OPTS[@]}" "${SBT_OPTS[@]}" "${JAVA_OPTS[@]}" "${java_opts[@]}" ) +userhome="$HOME" +if is_cygwin; then + # cygwin sets home to something f-d up, set to real windows homedir + userhome="$USERPROFILE" +fi +declare -r activator_user_home_dir="${userhome}/.activator" +declare -r java_opts_config_home="${activator_user_home_dir}/activatorconfig.txt" +declare -r java_opts_config_version="${activator_user_home_dir}/${app_version}/activatorconfig.txt" + +echoerr () { + echo 1>&2 "$@" +} +vlog () { + [[ $verbose || $debug ]] && echoerr "$@" +} +dlog () { + [[ $debug ]] && echoerr "$@" +} + +jar_file () { + echo "$(cygwinpath "${sbt_home}/libexec/activator-launch-${app_version}.jar")" +} + +acquire_sbt_jar () { + sbt_jar="$(jar_file)" + + if [[ ! -f "$sbt_jar" ]]; then + echoerr "Could not find launcher jar: $sbt_jar" + exit 2 + fi +} + +execRunner () { + # print the arguments one to a line, quoting any containing spaces + [[ $verbose || $debug ]] && echo "# Executing command line:" && { + for arg; do + if printf "%s\n" "$arg" | grep -q ' '; then + printf "\"%s\"\n" "$arg" + else + printf "%s\n" "$arg" + fi + done + echo "" + } + + # THis used to be exec, but we loose the ability to re-hook stty then + # for cygwin... Maybe we should flag the feature here... + "$@" +} + +addJava () { + dlog "[addJava] arg = '$1'" + java_args=( "${java_args[@]}" "$1" ) +} +addSbt () { + dlog "[addSbt] arg = '$1'" + sbt_commands=( "${sbt_commands[@]}" "$1" ) +} +addResidual () { + dlog "[residual] arg = '$1'" + residual_args=( "${residual_args[@]}" "$1" ) +} +addDebugger () { + addJava "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$1" +} + +get_mem_opts () { + # if we detect any of these settings in ${JAVA_OPTS} we need to NOT output our settings. + # The reason is the Xms/Xmx, if they don't line up, cause errors. + if [[ "${JAVA_OPTS}" == *-Xmx* ]] || [[ "${JAVA_OPTS}" == *-Xms* ]] || [[ "${JAVA_OPTS}" == *-XX:MaxPermSize* ]] || [[ "${JAVA_OPTS}" == *-XX:MaxMetaspaceSize* ]] || [[ "${JAVA_OPTS}" == *-XX:ReservedCodeCacheSize* ]]; then + echo "" + else + # a ham-fisted attempt to move some memory settings in concert + # so they need not be messed around with individually. + local mem=${1:-1024} + local codecache=$(( $mem / 8 )) + (( $codecache > 128 )) || codecache=128 + (( $codecache < 512 )) || codecache=512 + local class_metadata_size=$(( $codecache * 2 )) + local class_metadata_opt=$([[ "$java_version" < "1.8" ]] && echo "MaxPermSize" || echo "MaxMetaspaceSize") + + echo "-Xms${mem}m -Xmx${mem}m -XX:ReservedCodeCacheSize=${codecache}m -XX:${class_metadata_opt}=${class_metadata_size}m" + fi +} + +require_arg () { + local type="$1" + local opt="$2" + local arg="$3" + if [[ -z "$arg" ]] || [[ "${arg:0:1}" == "-" ]]; then + echo "$opt requires <$type> argument" + exit 1 + fi +} + +is_function_defined() { + declare -f "$1" > /dev/null +} + +# If we're *not* running in a terminal, and we don't have any arguments, then we need to add the 'ui' parameter +detect_terminal_for_ui() { + [[ ! -t 0 ]] && [[ "${#residual_args}" == "0" ]] && { + addResidual "ui" + } + # SPECIAL TEST FOR MAC + [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]] && [[ "${#residual_args}" == "0" ]] && { + echo "Detected MAC OSX launched script...." + echo "Swapping to UI" + addResidual "ui" + } +} + +process_args () { + while [[ $# -gt 0 ]]; do + case "$1" in + -h|-help) usage; exit 1 ;; + -v|-verbose) verbose=1 && shift ;; + -d|-debug) debug=1 && shift ;; + + -ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;; + -mem) require_arg integer "$1" "$2" && sbt_mem="$2" && shift 2 ;; + -jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;; + -batch) exec &1 | awk -F '"' '/version/ {print $2}') + vlog "[process_args] java_version = '$java_version'" +} + +# Detect that we have java installed. +checkJava() { + local required_version="$1" + # Now check to see if it's a good enough version + if [[ "$java_version" == "" ]]; then + echo + echo No java installations was detected. + echo Please go to http://www.java.com/getjava/ and download + echo + exit 1 + elif [[ ! "$java_version" > "$required_version" ]]; then + echo + echo The java installation you have is not up to date + echo $script_name requires at least version $required_version+, you have + echo version $java_version + echo + echo Please go to http://www.java.com/getjava/ and download + echo a valid Java Runtime and install before running $script_name. + echo + exit 1 + fi +} + + +run() { + # no jar? download it. + [[ -f "$sbt_jar" ]] || acquire_sbt_jar "$sbt_version" || { + # still no jar? uh-oh. + echo "Download failed. Obtain the sbt-launch.jar manually and place it at $sbt_jar" + exit 1 + } + + # process the combined args, then reset "$@" to the residuals + process_args "$@" + detect_terminal_for_ui + set -- "${residual_args[@]}" + argumentCount=$# + + # TODO - java check should be configurable... + checkJava "1.6" + + #If we're in cygwin, we should use the windows config, and terminal hacks + if [[ "$CYGWIN_FLAG" == "true" ]]; then + stty -icanon min 1 -echo > /dev/null 2>&1 + addJava "-Djline.terminal=jline.UnixTerminal" + addJava "-Dsbt.cygwin=true" + fi + + # run sbt + execRunner "$java_cmd" \ + "-Dactivator.home=$(make_url "$sbt_home")" \ + ${SBT_OPTS:-$default_sbt_opts} \ + $(get_mem_opts $sbt_mem) \ + ${JAVA_OPTS} \ + ${java_args[@]} \ + -jar "$sbt_jar" \ + "${sbt_commands[@]}" \ + "${residual_args[@]}" + + exit_code=$? + + # Clean up the terminal from cygwin hacks. + if [[ "$CYGWIN_FLAG" == "true" ]]; then + stty icanon echo > /dev/null 2>&1 + fi + exit $exit_code +} + + +declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy" +declare -r sbt_opts_file=".sbtopts" +declare -r etc_sbt_opts_file="${sbt_home}/conf/sbtopts" +declare -r win_sbt_opts_file="${sbt_home}/conf/sbtconfig.txt" + +usage() { + cat < path to global settings/plugins directory (default: ~/.sbt) + -sbt-boot path to shared boot directory (default: ~/.sbt/boot in 0.11 series) + -ivy path to local Ivy repository (default: ~/.ivy2) + -mem set memory options (default: $sbt_mem, which is $(get_mem_opts $sbt_mem)) + -no-share use all local caches; no sharing + -no-global uses global caches, but does not use global ~/.sbt directory. + -jvm-debug Turn on JVM debugging, open at the given port. + -batch Disable interactive mode + + # sbt version (default: from project/build.properties if present, else latest release) + -sbt-version use the specified version of sbt + -sbt-jar use the specified jar as the sbt launcher + -sbt-rc use an RC version of sbt + -sbt-snapshot use a snapshot version of sbt + + # java version (default: java from PATH, currently $(java -version 2>&1 | grep version)) + -java-home alternate JAVA_HOME + + # jvm options and output control + JAVA_OPTS environment variable, if unset uses "$java_opts" + SBT_OPTS environment variable, if unset uses "$default_sbt_opts" + ACTIVATOR_OPTS Environment variable, if unset uses "" + .sbtopts if this file exists in the current directory, it is + prepended to the runner args + /etc/sbt/sbtopts if this file exists, it is prepended to the runner args + -Dkey=val pass -Dkey=val directly to the java runtime + -J-X pass option -X directly to the java runtime + (-J is stripped) + -S-X add -X to sbt's scalacOptions (-S is stripped) + +In the case of duplicated or conflicting options, the order above +shows precedence: JAVA_OPTS lowest, command line options highest. +EOM +} + + + +process_my_args () { + while [[ $# -gt 0 ]]; do + case "$1" in + -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;; + -no-share) addJava "$noshare_opts" && shift ;; + -no-global) addJava "-Dsbt.global.base=$(pwd)/project/.sbtboot" && shift ;; + -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; + -sbt-dir) require_arg path "$1" "$2" && addJava "-Dsbt.global.base=$2" && shift 2 ;; + -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; + -batch) exec ^&1') do ( + if %%~j==java set JAVAINSTALLED=1 + if %%~j==openjdk set JAVAINSTALLED=1 +) + +rem Detect the same thing about javac +if "%_JAVACCMD%"=="" ( + if not "%JAVA_HOME%"=="" ( + if exist "%JAVA_HOME%\bin\javac.exe" set "_JAVACCMD=%JAVA_HOME%\bin\javac.exe" + ) +) +if "%_JAVACCMD%"=="" set _JAVACCMD=javac +for /F %%j in ('"%_JAVACCMD%" -version 2^>^&1') do ( + if %%~j==javac set JAVACINSTALLED=1 +) + +rem BAT has no logical or, so we do it OLD SCHOOL! Oppan Redmond Style +set JAVAOK=true +if not defined JAVAINSTALLED set JAVAOK=false +if not defined JAVACINSTALLED set JAVAOK=false + +if "%JAVAOK%"=="false" ( + echo. + echo A Java JDK is not installed or can't be found. + if not "%JAVA_HOME%"=="" ( + echo JAVA_HOME = "%JAVA_HOME%" + ) + echo. + echo Please go to + echo http://www.oracle.com/technetwork/java/javase/downloads/index.html + echo and download a valid Java JDK and install before running Activator. + echo. + echo If you think this message is in error, please check + echo your environment variables to see if "java.exe" and "javac.exe" are + echo available via JAVA_HOME or PATH. + echo. + if defined DOUBLECLICKED pause + exit /B 1 +) + +rem Check what Java version is being used to determine what memory options to use +for /f "tokens=3" %%g in ('java -version 2^>^&1 ^| findstr /i "version"') do ( + set JAVA_VERSION=%%g +) + +rem Strips away the " characters +set JAVA_VERSION=%JAVA_VERSION:"=% + +rem TODO Check if there are existing mem settings in JAVA_OPTS/CFG_OPTS and use those instead of the below +for /f "delims=. tokens=1-3" %%v in ("%JAVA_VERSION%") do ( + set MAJOR=%%v + set MINOR=%%w + set BUILD=%%x + + set META_SIZE=-XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=256M + if "!MINOR!" LSS "8" ( + set META_SIZE=-XX:PermSize=64M -XX:MaxPermSize=256M + ) + + set MEM_OPTS=!META_SIZE! + ) + +rem We use the value of the JAVA_OPTS environment variable if defined, rather than the config. +set _JAVA_OPTS=%JAVA_OPTS% +if "%_JAVA_OPTS%"=="" set _JAVA_OPTS=%CFG_OPTS% + +set DEBUG_OPTS= + +rem Loop through the arguments, building remaining args in args variable +set args= +:argsloop +if not "%~1"=="" ( + rem Checks if the argument contains "-D" and if true, adds argument 1 with 2 and puts an equal sign between them. + rem This is done since batch considers "=" to be a delimiter so we need to circumvent this behavior with a small hack. + set arg1=%~1 + if "!arg1:~0,2!"=="-D" ( + set "args=%args% "%~1"="%~2"" + shift + shift + goto argsloop + ) + + if "%~1"=="-jvm-debug" ( + if not "%~2"=="" ( + rem This piece of magic somehow checks that an argument is a number + for /F "delims=0123456789" %%i in ("%~2") do ( + set var="%%i" + ) + if defined var ( + rem Not a number, assume no argument given and default to 9999 + set JPDA_PORT=9999 + ) else ( + rem Port was given, shift arguments + set JPDA_PORT=%~2 + shift + ) + ) else ( + set JPDA_PORT=9999 + ) + shift + + set DEBUG_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=!JPDA_PORT! + goto argsloop + ) + rem else + set "args=%args% "%~1"" + shift + goto argsloop +) + +:run + +if "!args!"=="" ( + if defined DOUBLECLICKED ( + set CMDS="ui" + ) else set CMDS=!args! +) else set CMDS=!args! + +rem We add a / in front, so we get file:///C: instead of file://C: +rem Java considers the later a UNC path. +rem We also attempt a solid effort at making it URI friendly. +rem We don't even bother with UNC paths. +set JAVA_FRIENDLY_HOME_1=/!ACTIVATOR_HOME:\=/! +set JAVA_FRIENDLY_HOME=/!JAVA_FRIENDLY_HOME_1: =%%20! + +rem Checks if the command contains spaces to know if it should be wrapped in quotes or not +set NON_SPACED_CMD=%_JAVACMD: =% +if "%_JAVACMD%"=="%NON_SPACED_CMD%" %_JAVACMD% %DEBUG_OPTS% %MEM_OPTS% %ACTIVATOR_OPTS% %SBT_OPTS% %_JAVA_OPTS% "-Dactivator.home=%JAVA_FRIENDLY_HOME%" -jar "%ACTIVATOR_HOME%\libexec\%ACTIVATOR_LAUNCH_JAR%" %CMDS% +if NOT "%_JAVACMD%"=="%NON_SPACED_CMD%" "%_JAVACMD%" %DEBUG_OPTS% %MEM_OPTS% %ACTIVATOR_OPTS% %SBT_OPTS% %_JAVA_OPTS% "-Dactivator.home=%JAVA_FRIENDLY_HOME%" -jar "%ACTIVATOR_HOME%\libexec\%ACTIVATOR_LAUNCH_JAR%" %CMDS% + +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end + +@endlocal + +exit /B %ERROR_CODE% diff --git a/routing-in-play/build.sbt b/routing-in-play/build.sbt new file mode 100644 index 0000000000..083d071676 --- /dev/null +++ b/routing-in-play/build.sbt @@ -0,0 +1,13 @@ +name := """webapp""" + +version := "1.0-SNAPSHOT" + +lazy val root = (project in file(".")).enablePlugins(PlayJava) + +scalaVersion := "2.11.7" + +libraryDependencies ++= Seq( + javaJdbc, + cache, + javaWs +) diff --git a/routing-in-play/conf/application.conf b/routing-in-play/conf/application.conf new file mode 100644 index 0000000000..489d3f9b3e --- /dev/null +++ b/routing-in-play/conf/application.conf @@ -0,0 +1,353 @@ +# This is the main configuration file for the application. +# https://www.playframework.com/documentation/latest/ConfigFile +# ~~~~~ +# Play uses HOCON as its configuration file format. HOCON has a number +# of advantages over other config formats, but there are two things that +# can be used when modifying settings. +# +# You can include other configuration files in this main application.conf file: +#include "extra-config.conf" +# +# You can declare variables and substitute for them: +#mykey = ${some.value} +# +# And if an environment variable exists when there is no other subsitution, then +# HOCON will fall back to substituting environment variable: +#mykey = ${JAVA_HOME} + +## Akka +# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration +# https://www.playframework.com/documentation/latest/JavaAkka#Configuration +# ~~~~~ +# Play uses Akka internally and exposes Akka Streams and actors in Websockets and +# other streaming HTTP responses. +akka { + # "akka.log-config-on-start" is extraordinarly useful because it log the complete + # configuration at INFO level, including defaults and overrides, so it s worth + # putting at the very top. + # + # Put the following in your conf/logback.xml file: + # + # + # + # And then uncomment this line to debug the configuration. + # + #log-config-on-start = true +} + +## Secret key +# http://www.playframework.com/documentation/latest/ApplicationSecret +# ~~~~~ +# The secret key is used to sign Play's session cookie. +# This must be changed for production, but we don't recommend you change it in this file. +play.crypto.secret = "changeme" + +## Modules +# https://www.playframework.com/documentation/latest/Modules +# ~~~~~ +# Control which modules are loaded when Play starts. Note that modules are +# the replacement for "GlobalSettings", which are deprecated in 2.5.x. +# Please see https://www.playframework.com/documentation/latest/GlobalSettings +# for more information. +# +# You can also extend Play functionality by using one of the publically available +# Play modules: https://playframework.com/documentation/latest/ModuleDirectory +play.modules { + # By default, Play will load any class called Module that is defined + # in the root package (the "app" directory), or you can define them + # explicitly below. + # If there are any built-in modules that you want to disable, you can list them here. + #enabled += my.application.Module + + # If there are any built-in modules that you want to disable, you can list them here. + #disabled += "" +} + +## IDE +# https://www.playframework.com/documentation/latest/IDE +# ~~~~~ +# Depending on your IDE, you can add a hyperlink for errors that will jump you +# directly to the code location in the IDE in dev mode. The following line makes +# use of the IntelliJ IDEA REST interface: +#play.editor="http://localhost:63342/api/file/?file=%s&line=%s" + +## Internationalisation +# https://www.playframework.com/documentation/latest/JavaI18N +# https://www.playframework.com/documentation/latest/ScalaI18N +# ~~~~~ +# Play comes with its own i18n settings, which allow the user's preferred language +# to map through to internal messages, or allow the language to be stored in a cookie. +play.i18n { + # The application languages + langs = [ "en" ] + + # Whether the language cookie should be secure or not + #langCookieSecure = true + + # Whether the HTTP only attribute of the cookie should be set to true + #langCookieHttpOnly = true +} + +## Play HTTP settings +# ~~~~~ +play.http { + ## Router + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # Define the Router object to use for this application. + # This router will be looked up first when the application is starting up, + # so make sure this is the entry point. + # Furthermore, it's assumed your route file is named properly. + # So for an application router like `my.application.Router`, + # you may need to define a router file `conf/my.application.routes`. + # Default to Routes in the root package (aka "apps" folder) (and conf/routes) + #router = my.application.Router + + ## Action Creator + # https://www.playframework.com/documentation/latest/JavaActionCreator + # ~~~~~ + #actionCreator = null + + ## ErrorHandler + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # If null, will attempt to load a class called ErrorHandler in the root package, + #errorHandler = null + + ## Filters + # https://www.playframework.com/documentation/latest/ScalaHttpFilters + # https://www.playframework.com/documentation/latest/JavaHttpFilters + # ~~~~~ + # Filters run code on every request. They can be used to perform + # common logic for all your actions, e.g. adding common headers. + # Defaults to "Filters" in the root package (aka "apps" folder) + # Alternatively you can explicitly register a class here. + #filters = my.application.Filters + + ## Session & Flash + # https://www.playframework.com/documentation/latest/JavaSessionFlash + # https://www.playframework.com/documentation/latest/ScalaSessionFlash + # ~~~~~ + session { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + + # Sets the max-age field of the cookie to 5 minutes. + # NOTE: this only sets when the browser will discard the cookie. Play will consider any + # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout, + # you need to put a timestamp in the session and check it at regular intervals to possibly expire it. + #maxAge = 300 + + # Sets the domain on the session cookie. + #domain = "example.com" + } + + flash { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + } +} + +## Netty Provider +# https://www.playframework.com/documentation/latest/SettingsNetty +# ~~~~~ +play.server.netty { + # Whether the Netty wire should be logged + #log.wire = true + + # If you run Play on Linux, you can use Netty's native socket transport + # for higher performance with less garbage. + #transport = "native" +} + +## WS (HTTP Client) +# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS +# ~~~~~ +# The HTTP client primarily used for REST APIs. The default client can be +# configured directly, but you can also create different client instances +# with customized settings. You must enable this by adding to build.sbt: +# +# libraryDependencies += ws // or javaWs if using java +# +play.ws { + # Sets HTTP requests not to follow 302 requests + #followRedirects = false + + # Sets the maximum number of open HTTP connections for the client. + #ahc.maxConnectionsTotal = 50 + + ## WS SSL + # https://www.playframework.com/documentation/latest/WsSSL + # ~~~~~ + ssl { + # Configuring HTTPS with Play WS does not require programming. You can + # set up both trustManager and keyManager for mutual authentication, and + # turn on JSSE debugging in development with a reload. + #debug.handshake = true + #trustManager = { + # stores = [ + # { type = "JKS", path = "exampletrust.jks" } + # ] + #} + } +} + +## Cache +# https://www.playframework.com/documentation/latest/JavaCache +# https://www.playframework.com/documentation/latest/ScalaCache +# ~~~~~ +# Play comes with an integrated cache API that can reduce the operational +# overhead of repeated requests. You must enable this by adding to build.sbt: +# +# libraryDependencies += cache +# +play.cache { + # If you want to bind several caches, you can bind the individually + #bindCaches = ["db-cache", "user-cache", "session-cache"] +} + +## Filters +# https://www.playframework.com/documentation/latest/Filters +# ~~~~~ +# There are a number of built-in filters that can be enabled and configured +# to give Play greater security. You must enable this by adding to build.sbt: +# +# libraryDependencies += filters +# +play.filters { + ## CORS filter configuration + # https://www.playframework.com/documentation/latest/CorsFilter + # ~~~~~ + # CORS is a protocol that allows web applications to make requests from the browser + # across different domains. + # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has + # dependencies on CORS settings. + cors { + # Filter paths by a whitelist of path prefixes + #pathPrefixes = ["/some/path", ...] + + # The allowed origins. If null, all origins are allowed. + #allowedOrigins = ["http://www.example.com"] + + # The allowed HTTP methods. If null, all methods are allowed + #allowedHttpMethods = ["GET", "POST"] + } + + ## CSRF Filter + # https://www.playframework.com/documentation/latest/ScalaCsrf#Applying-a-global-CSRF-filter + # https://www.playframework.com/documentation/latest/JavaCsrf#Applying-a-global-CSRF-filter + # ~~~~~ + # Play supports multiple methods for verifying that a request is not a CSRF request. + # The primary mechanism is a CSRF token. This token gets placed either in the query string + # or body of every form submitted, and also gets placed in the users session. + # Play then verifies that both tokens are present and match. + csrf { + # Sets the cookie to be sent only over HTTPS + #cookie.secure = true + + # Defaults to CSRFErrorHandler in the root package. + #errorHandler = MyCSRFErrorHandler + } + + ## Security headers filter configuration + # https://www.playframework.com/documentation/latest/SecurityHeaders + # ~~~~~ + # Defines security headers that prevent XSS attacks. + # If enabled, then all options are set to the below configuration by default: + headers { + # The X-Frame-Options header. If null, the header is not set. + #frameOptions = "DENY" + + # The X-XSS-Protection header. If null, the header is not set. + #xssProtection = "1; mode=block" + + # The X-Content-Type-Options header. If null, the header is not set. + #contentTypeOptions = "nosniff" + + # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set. + #permittedCrossDomainPolicies = "master-only" + + # The Content-Security-Policy header. If null, the header is not set. + #contentSecurityPolicy = "default-src 'self'" + } + + ## Allowed hosts filter configuration + # https://www.playframework.com/documentation/latest/AllowedHostsFilter + # ~~~~~ + # Play provides a filter that lets you configure which hosts can access your application. + # This is useful to prevent cache poisoning attacks. + hosts { + # Allow requests to example.com, its subdomains, and localhost:9000. + #allowed = [".example.com", "localhost:9000"] + } +} + +## Evolutions +# https://www.playframework.com/documentation/latest/Evolutions +# ~~~~~ +# Evolutions allows database scripts to be automatically run on startup in dev mode +# for database migrations. You must enable this by adding to build.sbt: +# +# libraryDependencies += evolutions +# +play.evolutions { + # You can disable evolutions for a specific datasource if necessary + #db.default.enabled = false +} + +## Database Connection Pool +# https://www.playframework.com/documentation/latest/SettingsJDBC +# ~~~~~ +# Play doesn't require a JDBC database to run, but you can easily enable one. +# +# libraryDependencies += jdbc +# +play.db { + # The combination of these two settings results in "db.default" as the + # default JDBC pool: + #config = "db" + #default = "default" + + # Play uses HikariCP as the default connection pool. You can override + # settings by changing the prototype: + prototype { + # Sets a fixed JDBC connection pool size of 50 + #hikaricp.minimumIdle = 50 + #hikaricp.maximumPoolSize = 50 + } +} + +## JDBC Datasource +# https://www.playframework.com/documentation/latest/JavaDatabase +# https://www.playframework.com/documentation/latest/ScalaDatabase +# ~~~~~ +# Once JDBC datasource is set up, you can work with several different +# database options: +# +# Slick (Scala preferred option): https://www.playframework.com/documentation/latest/PlaySlick +# JPA (Java preferred option): https://playframework.com/documentation/latest/JavaJPA +# EBean: https://playframework.com/documentation/latest/JavaEbean +# Anorm: https://www.playframework.com/documentation/latest/ScalaAnorm +# +db { + # You can declare as many datasources as you want. + # By convention, the default datasource is named `default` + + # https://www.playframework.com/documentation/latest/Developing-with-the-H2-Database + #default.driver = org.h2.Driver + #default.url = "jdbc:h2:mem:play" + #default.username = sa + #default.password = "" + + # You can turn on SQL logging for any datasource + # https://www.playframework.com/documentation/latest/Highlights25#Logging-SQL-statements + #default.logSql=true +} diff --git a/routing-in-play/conf/logback.xml b/routing-in-play/conf/logback.xml new file mode 100644 index 0000000000..86ec12c0af --- /dev/null +++ b/routing-in-play/conf/logback.xml @@ -0,0 +1,41 @@ + + + + + + + ${application.home:-.}/logs/application.log + + %date [%level] from %logger in %thread - %message%n%xException + + + + + + %coloredLevel %logger{15} - %message%n%xException{10} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/routing-in-play/conf/routes b/routing-in-play/conf/routes new file mode 100644 index 0000000000..f72d8a1a14 --- /dev/null +++ b/routing-in-play/conf/routes @@ -0,0 +1,7 @@ +GET / controllers.HomeController.index(author="Baeldung",id:Int?=1) +GET /:author controllers.HomeController.index(author,id:Int?=1) +GET /greet/:name/:age controllers.HomeController.greet(name,age:Integer) +GET /square/$num<[0-9]+> controllers.HomeController.squareMe(num:Long) +# Map static resources from the /public folder to the /assets URL path +GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) +GET /*data controllers.HomeController.introduceMe(data) diff --git a/routing-in-play/libexec/activator-launch-1.3.10.jar b/routing-in-play/libexec/activator-launch-1.3.10.jar new file mode 100644 index 0000000000..69050e7dec Binary files /dev/null and b/routing-in-play/libexec/activator-launch-1.3.10.jar differ diff --git a/routing-in-play/project/build.properties b/routing-in-play/project/build.properties new file mode 100644 index 0000000000..6d22e3f2d1 --- /dev/null +++ b/routing-in-play/project/build.properties @@ -0,0 +1,4 @@ +#Activator-generated Properties +#Fri Sep 30 14:25:10 EAT 2016 +template.uuid=26c759a5-daf0-4e02-bcfa-ac69725267c0 +sbt.version=0.13.11 diff --git a/routing-in-play/project/plugins.sbt b/routing-in-play/project/plugins.sbt new file mode 100644 index 0000000000..e8e7f602f7 --- /dev/null +++ b/routing-in-play/project/plugins.sbt @@ -0,0 +1,21 @@ +// The Play plugin +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.8") + +// Web plugins +addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.1.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-jshint" % "1.0.4") +addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.8") +addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.1") +addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0") +addSbtPlugin("org.irundaia.sbt" % "sbt-sassify" % "1.4.6") + +// Play enhancer - this automatically generates getters/setters for public fields +// and rewrites accessors of these fields to use the getters/setters. Remove this +// plugin if you prefer not to have this feature, or disable on a per project +// basis using disablePlugins(PlayEnhancer) in your build.sbt +addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.1.0") + +// Play Ebean support, to enable, uncomment this line, and enable in your build.sbt using +// enablePlugins(PlayEbean). +// addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "3.0.2") diff --git a/routing-in-play/public/images/favicon.png b/routing-in-play/public/images/favicon.png new file mode 100644 index 0000000000..c7d92d2ae4 Binary files /dev/null and b/routing-in-play/public/images/favicon.png differ diff --git a/routing-in-play/public/javascripts/hello.js b/routing-in-play/public/javascripts/hello.js new file mode 100644 index 0000000000..02ee13c7ca --- /dev/null +++ b/routing-in-play/public/javascripts/hello.js @@ -0,0 +1,3 @@ +if (window.console) { + console.log("Welcome to your Play application's JavaScript!"); +} diff --git a/spring-cloud-data-flow/log-sink/src/main/resources/application.properties b/routing-in-play/public/stylesheets/main.css similarity index 100% rename from spring-cloud-data-flow/log-sink/src/main/resources/application.properties rename to routing-in-play/public/stylesheets/main.css diff --git a/routing-in-play/test/ApplicationTest.java b/routing-in-play/test/ApplicationTest.java new file mode 100644 index 0000000000..3d7c4875aa --- /dev/null +++ b/routing-in-play/test/ApplicationTest.java @@ -0,0 +1,45 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.*; + +import play.mvc.*; +import play.test.*; +import play.data.DynamicForm; +import play.data.validation.ValidationError; +import play.data.validation.Constraints.RequiredValidator; +import play.i18n.Lang; +import play.libs.F; +import play.libs.F.*; +import play.twirl.api.Content; + +import static play.test.Helpers.*; +import static org.junit.Assert.*; + + +/** + * + * Simple (JUnit) tests that can call all parts of a play app. + * If you are interested in mocking a whole application, see the wiki for more details. + * + */ +public class ApplicationTest { + + @Test + public void simpleCheck() { + int a = 1 + 1; + assertEquals(2, a); + } + + @Test + public void renderTemplate() { + Content html = views.html.index.render("Your new application is ready."); + assertEquals("text/html", html.contentType()); + assertTrue(html.body().contains("Your new application is ready.")); + } + + +} diff --git a/routing-in-play/test/IntegrationTest.java b/routing-in-play/test/IntegrationTest.java new file mode 100644 index 0000000000..c53c71e124 --- /dev/null +++ b/routing-in-play/test/IntegrationTest.java @@ -0,0 +1,25 @@ +import org.junit.*; + +import play.mvc.*; +import play.test.*; + +import static play.test.Helpers.*; +import static org.junit.Assert.*; + +import static org.fluentlenium.core.filter.FilterConstructor.*; + +public class IntegrationTest { + + /** + * add your integration test here + * in this example we just check if the welcome page is being shown + */ + @Test + public void test() { + running(testServer(3333, fakeApplication(inMemoryDatabase())), HTMLUNIT, browser -> { + browser.goTo("http://localhost:3333"); + assertTrue(browser.pageSource().contains("Your new application is ready.")); + }); + } + +} diff --git a/sandbox/.classpath b/sandbox/.classpath deleted file mode 100644 index 8ebf6d9c31..0000000000 --- a/sandbox/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sandbox/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/sandbox/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/sandbox/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/sandbox/.project b/sandbox/.project deleted file mode 100644 index f039cd270e..0000000000 --- a/sandbox/.project +++ /dev/null @@ -1,36 +0,0 @@ - - - sandbox - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/sandbox/.settings/.jsdtscope b/sandbox/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/sandbox/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/sandbox/.settings/org.eclipse.jdt.core.prefs b/sandbox/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/sandbox/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/sandbox/.settings/org.eclipse.jdt.ui.prefs b/sandbox/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/sandbox/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/sandbox/.settings/org.eclipse.m2e.core.prefs b/sandbox/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/sandbox/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/sandbox/.settings/org.eclipse.m2e.wtp.prefs b/sandbox/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/sandbox/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/sandbox/.settings/org.eclipse.wst.common.component b/sandbox/.settings/org.eclipse.wst.common.component deleted file mode 100644 index e98377cb0f..0000000000 --- a/sandbox/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/sandbox/.settings/org.eclipse.wst.common.project.facet.core.xml b/sandbox/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f4ef8aa0a5..0000000000 --- a/sandbox/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/sandbox/.settings/org.eclipse.wst.jsdt.ui.superType.container b/sandbox/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/sandbox/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/sandbox/.settings/org.eclipse.wst.jsdt.ui.superType.name b/sandbox/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/sandbox/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/sandbox/.settings/org.eclipse.wst.validation.prefs b/sandbox/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index cacf5451ae..0000000000 --- a/sandbox/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,14 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.303.v201202090300 -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/sandbox/.settings/org.eclipse.wst.ws.service.policy.prefs b/sandbox/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/sandbox/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/sandbox/.springBeans b/sandbox/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/sandbox/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/sandbox/README.md b/sandbox/README.md deleted file mode 100644 index 772681ad57..0000000000 --- a/sandbox/README.md +++ /dev/null @@ -1,9 +0,0 @@ -========= - -## Core Java Cookbooks and Examples - -### Relevant Articles: -- [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list) -- [Java - Reading a Large File Efficiently](http://www.baeldung.com/java-read-lines-large-file) -- [Java InputStream to String](http://www.baeldung.com/convert-input-stream-to-string) - diff --git a/sandbox/pom.xml b/sandbox/pom.xml deleted file mode 100644 index 95b2df2cb3..0000000000 --- a/sandbox/pom.xml +++ /dev/null @@ -1,176 +0,0 @@ - - 4.0.0 - org.baeldung - sandbox - 0.1-SNAPSHOT - - sandbox - - - - - - - com.google.guava - guava - ${guava.version} - - - - org.apache.commons - commons-collections4 - 4.0 - - - - commons-io - commons-io - 2.4 - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - - - - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - - - - org.slf4j - slf4j-api - ${org.slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - - org.slf4j - jcl-over-slf4j - ${org.slf4j.version} - - - - org.slf4j - log4j-over-slf4j - ${org.slf4j.version} - - - - - - junit - junit - ${junit.version} - test - - - - org.hamcrest - hamcrest-core - ${org.hamcrest.version} - test - - - org.hamcrest - hamcrest-library - ${org.hamcrest.version} - test - - - - org.mockito - mockito-core - ${mockito.version} - test - - - - - - core-java - - - src/main/resources - true - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - - - - - - - 4.0.3.RELEASE - 3.2.5.RELEASE - - - 4.3.10.Final - 5.1.35 - - - 2.5.5 - - - 1.7.13 - 1.1.3 - - - 5.1.3.Final - - - 16.0.1 - 3.4 - - - 1.3 - 4.12 - 1.10.19 - - 4.4.1 - 4.5 - - 2.4.1 - - - 3.3 - 2.6 - 2.18.1 - 2.7 - 1.4.14 - - - - \ No newline at end of file diff --git a/sandbox/src/main/resources/logback.xml b/sandbox/src/main/resources/logback.xml deleted file mode 100644 index 62d0ea5037..0000000000 --- a/sandbox/src/main/resources/logback.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - web - %date [%thread] %-5level %logger{36} - %message%n - - - - - - - - - - - \ No newline at end of file diff --git a/sandbox/src/main/webapp/WEB-INF/api-servlet.xml b/sandbox/src/main/webapp/WEB-INF/api-servlet.xml deleted file mode 100644 index a675fc6d95..0000000000 --- a/sandbox/src/main/webapp/WEB-INF/api-servlet.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/sandbox/src/main/webapp/WEB-INF/web.xml b/sandbox/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 935beae648..0000000000 --- a/sandbox/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - Spring MVC Application - - - - contextClass - - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - contextConfigLocation - org.baeldung.config - - - - org.springframework.web.context.ContextLoaderListener - - - - - api - org.springframework.web.servlet.DispatcherServlet - 1 - - - api - / - - - - - - - \ No newline at end of file diff --git a/sandbox/src/test/java/org/baeldung/codility/CodilityTest1.java b/sandbox/src/test/java/org/baeldung/codility/CodilityTest1.java deleted file mode 100644 index 8bd957c51a..0000000000 --- a/sandbox/src/test/java/org/baeldung/codility/CodilityTest1.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.baeldung.codility; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Random; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class CodilityTest1 { - - @Before - public final void before() { - // - } - - // tests - - @Test - public final void whenSolutionIsCalculated1_thenCorrect() { - final int[] A = new int[] { 1, 4, 3, 3, 1, 2 }; - final int solution = solution(A); - Assert.assertEquals(4, solution); - } - - @Test - public final void whenSolutionIsCalculated2_thenCorrect() { - final int[] A = new int[] { 6, 4, 4, 6 }; - final int solution = solution(A); - Assert.assertEquals(-1, solution); - } - - @Test - public final void whenSolutionIsCalculated3_thenCorrect() { - final int[] A = new int[100000]; - final Random random = new Random(); - for (final int index : A) { - A[index] = random.nextInt(); - } - - final long start = System.currentTimeMillis(); - final int solution = solution(A); - final long end = System.currentTimeMillis(); - System.out.println("Time: " + (end - start)); - System.out.println(solution); - } - - // - - final int solution(final int elements[]) { - final Map collector = new LinkedHashMap(); - Integer currentValue = null; - for (final int element : elements) { - currentValue = collector.get(element); - if (currentValue == null) { - collector.put(element, 1); - } else if (currentValue >= 1) { - collector.put(element, ++currentValue); - } - } - - for (final Map.Entry entry : collector.entrySet()) { - if (entry.getValue() == 1) { - return entry.getKey(); - } - } - - return -1; - } - -} diff --git a/sandbox/src/test/java/org/baeldung/codility/CodilityTest2.java b/sandbox/src/test/java/org/baeldung/codility/CodilityTest2.java deleted file mode 100644 index d92e9001f9..0000000000 --- a/sandbox/src/test/java/org/baeldung/codility/CodilityTest2.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.baeldung.codility; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.junit.Assert; -import org.junit.Test; - -public class CodilityTest2 { - - // tests - - @Test - public final void whenSolutionIsCalculated1_thenCorrect() { - final int solution = solution(955); - Assert.assertEquals(4, solution); - } - - @Test - public final void whenSolutionIsCalculated2_thenCorrect() { - final int solution = solution(102); - Assert.assertEquals(-1, solution); - } - - @Test - public final void whenSolutionIsCalculated3_thenCorrect() { - final int solution = solution(2); - Assert.assertEquals(-1, solution); - } - - @Test - public final void whenSolutionIsCalculated4_thenCorrect() { - final int solution = solution2("codilitycodilityco"); - Assert.assertEquals(8, solution); - } - - // - - public final int solution(final int decimal) { - final String binaryString = Integer.toBinaryString(decimal); - int lastPeriod = -1; - for (int period = 1; period < (binaryString.length() / 2 + 1); period++) { - final Matcher m = Pattern.compile("(\\S{" + period + ",})(?=.*?\\1)").matcher(binaryString); - final boolean found = m.find(); - if (found && m.groupCount() > 0) { - lastPeriod = period; - } - if (!found) { - break; - } - } - - return lastPeriod; - } - - public final int solution2(final String binaryString) { - int lastPeriod = -1; - for (int period = 1; period < (binaryString.length() / 2 + 1); period++) { - final Matcher m = Pattern.compile("(\\S{" + period + ",})(?=.*?\\1)").matcher(binaryString); - final boolean found = m.find(); - if (found && m.groupCount() > 0) { - lastPeriod = period; - } - if (!found) { - break; - } - } - - return lastPeriod; - } - -} diff --git a/sandbox/src/test/java/org/baeldung/codility/CodilityTest3.java b/sandbox/src/test/java/org/baeldung/codility/CodilityTest3.java deleted file mode 100644 index a7067be7b0..0000000000 --- a/sandbox/src/test/java/org/baeldung/codility/CodilityTest3.java +++ /dev/null @@ -1,207 +0,0 @@ -package org.baeldung.codility; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - -public class CodilityTest3 { - - // tests - - @Test - public final void whenSolutionIsCalculated1_thenCorrect() { - final int[] moves = new int[] { 1, 3, 2, 5, 4, 4, 6, 3, 2 }; - final int solution = solution(moves); - Assert.assertEquals(7, solution); - } - - // - - public int solution(final int[] moves) { - final World world = new World(); - int nextMove = 0; - for (final int move : moves) { - switch (nextMove) { - case 0: - if (world.moveNorth(move)) { - nextMove = 1; - break; - } else { - return world.movesCount; - } - case 1: - if (world.moveEast(move)) { - nextMove = 2; - break; - } else { - return world.movesCount; - } - case 2: - if (world.moveSouth(move)) { - nextMove = 3; - break; - } else { - return world.movesCount; - } - case 3: - if (world.moveWest(move)) { - nextMove = 0; - break; - } else { - return world.movesCount; - } - default: - throw new IllegalStateException(); - } - } - - return world.movesCount; - } - -} - -class World { - int movesCount = 1; - int currentX = 0; - int currentY = 0; - Map minXAtY; - Map maxXAtY; - Map minYAtX; - Map maxYAtX; - - public World() { - minXAtY = new HashMap<>(); - maxXAtY = new HashMap<>(); - minYAtX = new HashMap<>(); - maxYAtX = new HashMap<>(); - } - - final boolean moveNorth(final int steps) { - if (isMoveNorthValid(steps)) { - storeMoveNorth(steps); - movesCount++; - return true; - } - return false; - } - - final boolean moveEast(final int steps) { - if (isMoveEastValid(steps)) { - storeMoveEast(steps); - movesCount++; - return true; - } - return false; - } - - final boolean moveSouth(final int steps) { - if (isMoveSouthValid(steps)) { - storeMoveSouth(steps); - movesCount++; - return true; - } - return false; - } - - final boolean moveWest(final int steps) { - if (isMoveWestValid(steps)) { - storeMoveWest(steps); - movesCount++; - return true; - } - return false; - } - - // - - private boolean isMoveNorthValid(final int steps) { - int currentPosition = currentY; - for (int i = 1; i <= steps; i++) { - currentPosition += 1; - if (minXAtY.get(currentPosition) != null && minXAtY.get(currentPosition) > currentX) { - return false; - } - if (maxXAtY.get(currentPosition) != null && maxXAtY.get(currentPosition) < currentX) { - return false; - } - } - return true; - } - - private boolean isMoveEastValid(final int steps) { // - int currentPosition = currentX; - for (int i = 1; i <= steps; i++) { - currentPosition += 1; - if (minYAtX.get(currentPosition) != null && minYAtX.get(currentPosition) < currentY) { - return false; - } - if (maxYAtX.get(currentPosition) != null && maxYAtX.get(currentPosition) > currentY) { - return false; - } - } - return true; - } - - private boolean isMoveSouthValid(final int steps) { - int currentPosition = currentY; - for (int i = 1; i <= steps; i++) { - currentPosition -= 1; - if (minXAtY.get(currentPosition) != null && minXAtY.get(currentPosition) < currentX) { - return false; - } - if (maxXAtY.get(currentPosition) != null && maxXAtY.get(currentPosition) > currentX) { - return false; - } - } - return true; - } - - private boolean isMoveWestValid(final int steps) { - int currentPosition = currentX; - for (int i = 1; i <= steps; i++) { - currentPosition -= 1; - if (minYAtX.get(currentPosition) != null && minYAtX.get(currentPosition) > currentY) { - return false; - } - if (maxYAtX.get(currentPosition) != null && maxYAtX.get(currentPosition) < currentY) { - return false; - } - } - return true; - } - - private void storeMoveNorth(final int steps) { - currentY = currentY + steps; - final Integer currentMaxYAtThisLevel = maxYAtX.get(currentX); - if (currentMaxYAtThisLevel == null || currentMaxYAtThisLevel == null && currentMaxYAtThisLevel < currentY) { - maxYAtX.put(currentX, currentY); - } - } - - private void storeMoveEast(final int steps) { - currentX = currentX + steps; - final Integer currentMaxXAtThisLevel = maxXAtY.get(currentY); - if (currentMaxXAtThisLevel == null || currentMaxXAtThisLevel == null && currentMaxXAtThisLevel < currentX) { - maxXAtY.put(currentY, currentX); - } - } - - private void storeMoveSouth(final int steps) { - currentY = currentY - steps; - final Integer currentMinYAtThisLevel = minYAtX.get(currentX); - if (currentMinYAtThisLevel == null || currentMinYAtThisLevel == null && currentMinYAtThisLevel > currentY) { - minYAtX.put(currentX, currentY); - } - } - - private void storeMoveWest(final int steps) { - currentX = currentX - steps; - final Integer currentMinXAtThisLevel = minXAtY.get(currentY); - if (currentMinXAtThisLevel == null || currentMinXAtThisLevel == null && currentMinXAtThisLevel > currentX) { - minXAtY.put(currentY, currentX); - } - } - -} diff --git a/selenium-junit-testng/pom.xml b/selenium-junit-testng/pom.xml new file mode 100644 index 0000000000..bf5a082fba --- /dev/null +++ b/selenium-junit-testng/pom.xml @@ -0,0 +1,48 @@ + + 4.0.0 + com.baeldung + selenium-junit-testng + 0.0.1-SNAPSHOT + + src + + + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + + Test*.java + + + + + + + + org.seleniumhq.selenium + selenium-java + 2.53.1 + + + junit + junit + 4.8.1 + + + org.testng + testng + 6.9.10 + + + \ No newline at end of file diff --git a/selenium-junit-testng/src/main/java/com/baeldung/selenium/SeleniumExample.java b/selenium-junit-testng/src/main/java/com/baeldung/selenium/SeleniumExample.java new file mode 100644 index 0000000000..d8b248df81 --- /dev/null +++ b/selenium-junit-testng/src/main/java/com/baeldung/selenium/SeleniumExample.java @@ -0,0 +1,24 @@ +package main.java.com.baeldung.selenium; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.firefox.FirefoxDriver; + +public class SeleniumExample { + + private WebDriver webDriver; + private String url = "http://www.baeldung.com/"; + + public SeleniumExample() { + webDriver = new FirefoxDriver(); + webDriver.get(url); + } + + public void closeWindow() { + webDriver.close(); + } + + public String getTitle() { + return webDriver.getTitle(); + } + +} diff --git a/selenium-junit-testng/src/test/java/com/baeldung/selenium/junit/TestSeleniumWithJUnit.java b/selenium-junit-testng/src/test/java/com/baeldung/selenium/junit/TestSeleniumWithJUnit.java new file mode 100644 index 0000000000..f183a613e7 --- /dev/null +++ b/selenium-junit-testng/src/test/java/com/baeldung/selenium/junit/TestSeleniumWithJUnit.java @@ -0,0 +1,32 @@ +package test.java.com.baeldung.selenium.junit; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import main.java.com.baeldung.selenium.SeleniumExample; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class TestSeleniumWithJUnit { + + private SeleniumExample seleniumExample; + private String expectedTitle = "Baeldung | Java, Spring and Web Development tutorials"; + + @Before + public void setUp() { + seleniumExample = new SeleniumExample(); + } + + @After + public void tearDown() { + seleniumExample.closeWindow(); + } + + @Test + public void whenPageIsLoaded_thenTitleIsAsPerExpectation() { + String actualTitle = seleniumExample.getTitle(); + assertNotNull(actualTitle); + assertEquals(actualTitle, expectedTitle); + } +} diff --git a/selenium-junit-testng/src/test/java/com/baeldung/selenium/testng/TestSeleniumWithTestNG.java b/selenium-junit-testng/src/test/java/com/baeldung/selenium/testng/TestSeleniumWithTestNG.java new file mode 100644 index 0000000000..3c94f3d440 --- /dev/null +++ b/selenium-junit-testng/src/test/java/com/baeldung/selenium/testng/TestSeleniumWithTestNG.java @@ -0,0 +1,32 @@ +package test.java.com.baeldung.selenium.testng; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import main.java.com.baeldung.selenium.SeleniumExample; + +import org.testng.annotations.AfterSuite; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.Test; + +public class TestSeleniumWithTestNG { + + private SeleniumExample seleniumExample; + private String expectedTitle = "Baeldung | Java, Spring and Web Development tutorials"; + + @BeforeSuite + public void setUp() { + seleniumExample = new SeleniumExample(); + } + + @AfterSuite + public void tearDown() { + seleniumExample.closeWindow(); + } + + @Test + public void whenPageIsLoaded_thenTitleIsAsPerExpectation() { + String actualTitle = seleniumExample.getTitle(); + assertNotNull(actualTitle); + assertEquals(actualTitle, expectedTitle); + } +} diff --git a/sockets/pom.xml b/sockets/pom.xml new file mode 100644 index 0000000000..24e8e436f3 --- /dev/null +++ b/sockets/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + com.baeldung + sockets + 1.0 + sockets + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 8 + 8 + + + + + + + junit + junit + 4.3 + test + + + + diff --git a/sockets/src/main/java/com/baeldung/socket/EchoClient.java b/sockets/src/main/java/com/baeldung/socket/EchoClient.java new file mode 100644 index 0000000000..e8ec97c80a --- /dev/null +++ b/sockets/src/main/java/com/baeldung/socket/EchoClient.java @@ -0,0 +1,43 @@ +package com.baeldung.socket; + +import java.io.*; +import java.net.*; + +public class EchoClient { + private Socket clientSocket; + private PrintWriter out; + private BufferedReader in; + + public void startConnection(String ip, int port) { + try { + clientSocket = new Socket(ip, port); + out = new PrintWriter(clientSocket.getOutputStream(), true); + in = new BufferedReader(new InputStreamReader( + clientSocket.getInputStream())); + } catch (IOException e) { + System.out.print(e); + } + + } + + public String sendMessage(String msg) { + try { + out.println(msg); + String resp = in.readLine(); + return resp; + } catch (Exception e) { + return null; + } + } + + public void stopConnection() { + try { + in.close(); + out.close(); + clientSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + } +} diff --git a/sockets/src/main/java/com/baeldung/socket/EchoMultiServer.java b/sockets/src/main/java/com/baeldung/socket/EchoMultiServer.java new file mode 100644 index 0000000000..2ece1ceebe --- /dev/null +++ b/sockets/src/main/java/com/baeldung/socket/EchoMultiServer.java @@ -0,0 +1,71 @@ +package com.baeldung.socket; + +import java.net.*; +import java.io.*; + +public class EchoMultiServer { + private ServerSocket serverSocket; + + public void start(int port) { + try { + serverSocket = new ServerSocket(port); + while (true) + new EchoClientHandler(serverSocket.accept()).run(); + + } catch (IOException e) { + e.printStackTrace(); + } finally { + stop(); + } + + } + + public void stop() { + try { + + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + private static class EchoClientHandler extends Thread { + private Socket clientSocket; + private PrintWriter out; + private BufferedReader in; + + public EchoClientHandler(Socket socket) { + this.clientSocket = socket; + } + + public void run() { + try { + out = new PrintWriter(clientSocket.getOutputStream(), true); + in = new BufferedReader(new InputStreamReader( + clientSocket.getInputStream())); + String inputLine; + while ((inputLine = in.readLine()) != null) { + if (".".equals(inputLine)) { + out.println("bye"); + break; + } + out.println(inputLine); + } + + in.close(); + out.close(); + clientSocket.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) { + EchoMultiServer server = new EchoMultiServer(); + server.start(5555); + } + +} diff --git a/sockets/src/main/java/com/baeldung/socket/EchoServer.java b/sockets/src/main/java/com/baeldung/socket/EchoServer.java new file mode 100644 index 0000000000..3607afa7f5 --- /dev/null +++ b/sockets/src/main/java/com/baeldung/socket/EchoServer.java @@ -0,0 +1,50 @@ +package com.baeldung.socket; + +import java.net.*; +import java.io.*; + +public class EchoServer { + private ServerSocket serverSocket; + private Socket clientSocket; + private PrintWriter out; + private BufferedReader in; + + public void start(int port) { + try { + serverSocket = new ServerSocket(port); + clientSocket = serverSocket.accept(); + out = new PrintWriter(clientSocket.getOutputStream(), true); + in = new BufferedReader(new InputStreamReader( + clientSocket.getInputStream())); + String inputLine; + while ((inputLine = in.readLine()) != null) { + if (".".equals(inputLine)) { + out.println("good bye"); + break; + } + out.println(inputLine); + } + } catch (IOException e) { + e.printStackTrace(); + } + + } + + public void stop() { + try { + in.close(); + out.close(); + clientSocket.close(); + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + public static void main(String[] args) { + EchoServer server = new EchoServer(); + server.start(4444); + } + +} diff --git a/sockets/src/main/java/com/baeldung/socket/GreetClient.java b/sockets/src/main/java/com/baeldung/socket/GreetClient.java new file mode 100644 index 0000000000..7252827c87 --- /dev/null +++ b/sockets/src/main/java/com/baeldung/socket/GreetClient.java @@ -0,0 +1,46 @@ +package com.baeldung.socket; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.Socket; + +public class GreetClient { + private Socket clientSocket; + private PrintWriter out; + private BufferedReader in; + + public void startConnection(String ip, int port) { + try { + clientSocket = new Socket(ip, port); + out = new PrintWriter(clientSocket.getOutputStream(), true); + in = new BufferedReader(new InputStreamReader( + clientSocket.getInputStream())); + } catch (IOException e) { + + } + + } + + public String sendMessage(String msg) { + try { + out.println(msg); + String resp = in.readLine(); + return resp; + } catch (Exception e) { + return null; + } + } + + public void stopConnection() { + try { + in.close(); + out.close(); + clientSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/sockets/src/main/java/com/baeldung/socket/GreetServer.java b/sockets/src/main/java/com/baeldung/socket/GreetServer.java new file mode 100644 index 0000000000..8bf675c7b9 --- /dev/null +++ b/sockets/src/main/java/com/baeldung/socket/GreetServer.java @@ -0,0 +1,47 @@ +package com.baeldung.socket; + +import java.net.*; +import java.io.*; + +public class GreetServer { + private ServerSocket serverSocket; + private Socket clientSocket; + private PrintWriter out; + private BufferedReader in; + + + public void start(int port) { + try { + serverSocket = new ServerSocket(port); + clientSocket = serverSocket.accept(); + out = new PrintWriter(clientSocket.getOutputStream(), true); + in = new BufferedReader(new InputStreamReader( + clientSocket.getInputStream())); + String greeting = in.readLine(); + if ("hello server".equals(greeting)) + out.println("hello client"); + else + out.println("unrecognised greeting"); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + public void stop() { + try { + in.close(); + out.close(); + clientSocket.close(); + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + public static void main(String[] args) { + GreetServer server=new GreetServer(); + server.start(6666); + } + +} diff --git a/sockets/src/test/java/com/baeldung/socket/EchoMultiTest.java b/sockets/src/test/java/com/baeldung/socket/EchoMultiTest.java new file mode 100644 index 0000000000..19a59c211c --- /dev/null +++ b/sockets/src/test/java/com/baeldung/socket/EchoMultiTest.java @@ -0,0 +1,57 @@ +package com.baeldung.socket; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.Executors; + +import static org.junit.Assert.assertEquals; + +public class EchoMultiTest { + + { + Executors.newSingleThreadExecutor().submit(() -> new EchoMultiServer().start(5555)); + } + + + @Test + public void givenClient1_whenServerResponds_thenCorrect() { + EchoClient client = new EchoClient(); + client.startConnection("127.0.0.1", 5555); + String msg1 = client.sendMessage("hello"); + String msg2 = client.sendMessage("world"); + String terminate = client.sendMessage("."); + assertEquals(msg1, "hello"); + assertEquals(msg2, "world"); + assertEquals(terminate, "bye"); + client.stopConnection(); + } + + @Test + public void givenClient2_whenServerResponds_thenCorrect() { + EchoClient client = new EchoClient(); + client.startConnection("127.0.0.1", 5555); + String msg1 = client.sendMessage("hello"); + String msg2 = client.sendMessage("world"); + String terminate = client.sendMessage("."); + assertEquals(msg1, "hello"); + assertEquals(msg2, "world"); + assertEquals(terminate, "bye"); + client.stopConnection(); + } + + @Test + public void givenClient3_whenServerResponds_thenCorrect() { + EchoClient client = new EchoClient(); + client.startConnection("127.0.0.1", 5555); + String msg1 = client.sendMessage("hello"); + String msg2 = client.sendMessage("world"); + String terminate = client.sendMessage("."); + assertEquals(msg1, "hello"); + assertEquals(msg2, "world"); + assertEquals(terminate, "bye"); + client.stopConnection(); + } + +} diff --git a/sockets/src/test/java/com/baeldung/socket/EchoTest.java b/sockets/src/test/java/com/baeldung/socket/EchoTest.java new file mode 100644 index 0000000000..0f0c02e4d8 --- /dev/null +++ b/sockets/src/test/java/com/baeldung/socket/EchoTest.java @@ -0,0 +1,41 @@ +package com.baeldung.socket; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.Executors; + +import static org.junit.Assert.assertEquals; + +public class EchoTest { + { + Executors.newSingleThreadExecutor().submit(() -> new EchoServer().start(4444)); + } + + EchoClient client = new EchoClient(); + + @Before + public void init() { + client.startConnection("127.0.0.1", 4444); + } + + @Test + public void givenClient_whenServerEchosMessage_thenCorrect() { + + String resp1 = client.sendMessage("hello"); + String resp2 = client.sendMessage("world"); + String resp3 = client.sendMessage("!"); + String resp4 = client.sendMessage("."); + assertEquals("hello", resp1); + assertEquals("world", resp2); + assertEquals("!", resp3); + assertEquals("good bye", resp4); + } + + @After + public void tearDown() { + client.stopConnection(); + } + +} diff --git a/sockets/src/test/java/com/baeldung/socket/GreetServerTest.java b/sockets/src/test/java/com/baeldung/socket/GreetServerTest.java new file mode 100644 index 0000000000..fedc32fb39 --- /dev/null +++ b/sockets/src/test/java/com/baeldung/socket/GreetServerTest.java @@ -0,0 +1,36 @@ +package com.baeldung.socket; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.Executors; + +import static org.junit.Assert.assertEquals; + +public class GreetServerTest { + + GreetClient client; + + { + Executors.newSingleThreadExecutor().submit(() -> new GreetServer().start(6666)); + } + + @Before + public void init() { + client = new GreetClient(); + client.startConnection("127.0.0.1", 6666); + + } + + @Test + public void givenGreetingClient_whenServerRespondsWhenStarted_thenCorrect() { + String response = client.sendMessage("hello server"); + assertEquals("hello client", response); + } + + @After + public void finish() { + client.stopConnection(); + } +} diff --git a/spring-akka/pom.xml b/spring-akka/pom.xml new file mode 100644 index 0000000000..6299448ec8 --- /dev/null +++ b/spring-akka/pom.xml @@ -0,0 +1,80 @@ + + 4.0.0 + com.baeldung + spring-akka + 0.1-SNAPSHOT + + spring-akka + + + + + org.springframework + spring-context + + + + com.typesafe.akka + akka-actor_2.11 + ${akka.version} + + + + org.springframework + spring-test + test + + + + junit + junit + ${junit.version} + test + + + + + + + + + + org.springframework + spring-framework-bom + ${spring.version} + pom + import + + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + + + + + 4.3.2.RELEASE + 2.4.8 + 4.12 + + 3.5.1 + + + \ No newline at end of file diff --git a/spring-akka/src/main/java/org/baeldung/akka/AppConfiguration.java b/spring-akka/src/main/java/org/baeldung/akka/AppConfiguration.java new file mode 100644 index 0000000000..9211ae0fdb --- /dev/null +++ b/spring-akka/src/main/java/org/baeldung/akka/AppConfiguration.java @@ -0,0 +1,26 @@ +package org.baeldung.akka; + +import akka.actor.ActorSystem; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import static org.baeldung.akka.SpringExtension.SPRING_EXTENSION_PROVIDER; + +@Configuration +@ComponentScan +public class AppConfiguration { + + @Autowired + private ApplicationContext applicationContext; + + @Bean + public ActorSystem actorSystem() { + ActorSystem system = ActorSystem.create("akka-spring-demo"); + SPRING_EXTENSION_PROVIDER.get(system).initialize(applicationContext); + return system; + } + +} diff --git a/spring-akka/src/main/java/org/baeldung/akka/GreetingActor.java b/spring-akka/src/main/java/org/baeldung/akka/GreetingActor.java new file mode 100644 index 0000000000..6366c277a4 --- /dev/null +++ b/spring-akka/src/main/java/org/baeldung/akka/GreetingActor.java @@ -0,0 +1,42 @@ +package org.baeldung.akka; + +import akka.actor.UntypedActor; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class GreetingActor extends UntypedActor { + + private GreetingService greetingService; + + public GreetingActor(GreetingService greetingService) { + this.greetingService = greetingService; + } + + @Override + public void onReceive(Object message) throws Throwable { + if (message instanceof Greet) { + String name = ((Greet) message).getName(); + getSender().tell(greetingService.greet(name), getSelf()); + } else { + unhandled(message); + } + } + + public static class Greet { + + private String name; + + public Greet(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + } + +} diff --git a/spring-akka/src/main/java/org/baeldung/akka/GreetingService.java b/spring-akka/src/main/java/org/baeldung/akka/GreetingService.java new file mode 100644 index 0000000000..801921887d --- /dev/null +++ b/spring-akka/src/main/java/org/baeldung/akka/GreetingService.java @@ -0,0 +1,12 @@ +package org.baeldung.akka; + +import org.springframework.stereotype.Component; + +@Component +public class GreetingService { + + public String greet(String name) { + return "Hello, " + name; + } + +} diff --git a/spring-akka/src/main/java/org/baeldung/akka/SpringActorProducer.java b/spring-akka/src/main/java/org/baeldung/akka/SpringActorProducer.java new file mode 100644 index 0000000000..20813ab60a --- /dev/null +++ b/spring-akka/src/main/java/org/baeldung/akka/SpringActorProducer.java @@ -0,0 +1,28 @@ +package org.baeldung.akka; + +import akka.actor.Actor; +import akka.actor.IndirectActorProducer; +import org.springframework.context.ApplicationContext; + +public class SpringActorProducer implements IndirectActorProducer { + + private ApplicationContext applicationContext; + + private String beanActorName; + + public SpringActorProducer(ApplicationContext applicationContext, String beanActorName) { + this.applicationContext = applicationContext; + this.beanActorName = beanActorName; + } + + @Override + public Actor produce() { + return (Actor) applicationContext.getBean(beanActorName); + } + + @Override + public Class actorClass() { + return (Class) applicationContext.getType(beanActorName); + } + +} diff --git a/spring-akka/src/main/java/org/baeldung/akka/SpringExtension.java b/spring-akka/src/main/java/org/baeldung/akka/SpringExtension.java new file mode 100644 index 0000000000..624e289812 --- /dev/null +++ b/spring-akka/src/main/java/org/baeldung/akka/SpringExtension.java @@ -0,0 +1,33 @@ +package org.baeldung.akka; + +import akka.actor.AbstractExtensionId; +import akka.actor.ExtendedActorSystem; +import akka.actor.Extension; +import akka.actor.Props; +import org.springframework.context.ApplicationContext; + +public class SpringExtension extends AbstractExtensionId { + + public static final SpringExtension SPRING_EXTENSION_PROVIDER = new SpringExtension(); + + @Override + public SpringExt createExtension(ExtendedActorSystem system) { + return new SpringExt(); + } + + public static class SpringExt implements Extension { + + private volatile ApplicationContext applicationContext; + + public void initialize(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + public Props props(String actorBeanName) { + return Props.create(SpringActorProducer.class, applicationContext, actorBeanName); + } + + } + + +} diff --git a/spring-akka/src/test/java/org/baeldung/akka/SpringAkkaTest.java b/spring-akka/src/test/java/org/baeldung/akka/SpringAkkaTest.java new file mode 100644 index 0000000000..6162b02307 --- /dev/null +++ b/spring-akka/src/test/java/org/baeldung/akka/SpringAkkaTest.java @@ -0,0 +1,48 @@ +package org.baeldung.akka; + +import java.util.concurrent.TimeUnit; + +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.util.Timeout; +import org.baeldung.akka.GreetingActor.Greet; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; +import scala.concurrent.Await; +import scala.concurrent.Future; +import scala.concurrent.duration.FiniteDuration; + +import static akka.pattern.Patterns.ask; +import static org.baeldung.akka.SpringExtension.SPRING_EXTENSION_PROVIDER; + +@ContextConfiguration(classes = AppConfiguration.class) +public class SpringAkkaTest extends AbstractJUnit4SpringContextTests { + + @Autowired + private ActorSystem system; + + @Test + public void whenCallingGreetingActor_thenActorGreetsTheCaller() throws Exception { + ActorRef greeter = system.actorOf( + SPRING_EXTENSION_PROVIDER.get(system) + .props("greetingActor"), "greeter"); + + FiniteDuration duration = FiniteDuration.create(1, TimeUnit.SECONDS); + Timeout timeout = Timeout.durationToTimeout(duration); + + Future result = ask(greeter, new Greet("John"), timeout); + + Assert.assertEquals("Hello, John", Await.result(result, duration)); + } + + @After + public void tearDown() { + system.shutdown(); + system.awaitTermination(); + } + +} diff --git a/spring-all/.classpath b/spring-all/.classpath deleted file mode 100644 index 6b533711d3..0000000000 --- a/spring-all/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-all/.project b/spring-all/.project deleted file mode 100644 index ce1efa8880..0000000000 --- a/spring-all/.project +++ /dev/null @@ -1,43 +0,0 @@ - - - spring-all - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-all/.settings/.jsdtscope b/spring-all/.settings/.jsdtscope deleted file mode 100644 index b46b9207a8..0000000000 --- a/spring-all/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-all/.settings/org.eclipse.jdt.core.prefs b/spring-all/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/spring-all/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-all/.settings/org.eclipse.jdt.ui.prefs b/spring-all/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-all/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-all/.settings/org.eclipse.m2e.core.prefs b/spring-all/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-all/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-all/.settings/org.eclipse.m2e.wtp.prefs b/spring-all/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-all/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-all/.settings/org.eclipse.wst.common.component b/spring-all/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 847c6ff698..0000000000 --- a/spring-all/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-all/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-all/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 991897a4ac..0000000000 --- a/spring-all/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/spring-all/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-all/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-all/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-all/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-all/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-all/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-all/.settings/org.eclipse.wst.validation.prefs b/spring-all/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-all/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-all/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-all/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-all/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-all/.springBeans b/spring-all/.springBeans deleted file mode 100644 index 7623a7e888..0000000000 --- a/spring-all/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/spring-all/README.md b/spring-all/README.md index 4a3bd25077..0bbb600860 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -4,6 +4,11 @@ This project is used to replicate Spring Exceptions only. +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant articles: -- [Properties with Spring](http://www.baeldung.com/2012/02/06/properties-with-spring) - checkout the `org.baeldung.properties` package for all scenarios of properties injection and usage \ No newline at end of file +- [Properties with Spring](http://www.baeldung.com/2012/02/06/properties-with-spring) - checkout the `org.baeldung.properties` package for all scenarios of properties injection and usage +- [Spring Profiles](http://www.baeldung.com/spring-profiles) +- [A Spring Custom Annotation for a Better DAO](http://www.baeldung.com/spring-annotation-bean-pre-processor) +- [What's New in Spring 4.3?](http://www.baeldung.com/whats-new-in-spring-4-3/) diff --git a/spring-all/pom.xml b/spring-all/pom.xml index 6ce8ad7196..c70d9d75fc 100644 --- a/spring-all/pom.xml +++ b/spring-all/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-all 0.1-SNAPSHOT @@ -10,10 +10,14 @@ org.springframework.boot spring-boot-starter-parent - 1.2.6.RELEASE + 1.3.6.RELEASE + + com.fasterxml.jackson.core + jackson-databind + @@ -41,11 +45,6 @@ spring-aspects - - org.springframework - spring-orm - - @@ -131,6 +130,13 @@ test + + org.assertj + assertj-core + 3.5.1 + test + + org.hamcrest hamcrest-core @@ -147,8 +153,38 @@ mockito-core test + + + org.easymock + easymock + 3.4 + test + + + + + + + + org.springframework + spring-framework-bom + ${org.springframework.version} + pom + import + + + + org.springframework + spring-core + ${org.springframework.version} + + + + + + spring-all @@ -217,14 +253,14 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.3.1.RELEASE + 4.0.4.RELEASE 3.20.0-GA 1.2 4.3.11.Final - 5.1.37 + 5.1.38 1.7.13 @@ -245,14 +281,14 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-all/src/main/java/org/baeldung/async/AsyncComponent.java b/spring-all/src/main/java/org/baeldung/async/AsyncComponent.java index 2946ab0aa1..8503f75c8f 100644 --- a/spring-all/src/main/java/org/baeldung/async/AsyncComponent.java +++ b/spring-all/src/main/java/org/baeldung/async/AsyncComponent.java @@ -1,11 +1,11 @@ package org.baeldung.async; -import java.util.concurrent.Future; - import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Component; +import java.util.concurrent.Future; + @Component public class AsyncComponent { @@ -19,7 +19,7 @@ public class AsyncComponent { System.out.println("Execute method asynchronously " + Thread.currentThread().getName()); try { Thread.sleep(5000); - return new AsyncResult("hello world !!!!"); + return new AsyncResult<>("hello world !!!!"); } catch (final InterruptedException e) { } diff --git a/spring-all/src/main/java/org/baeldung/caching/config/CachingConfig.java b/spring-all/src/main/java/org/baeldung/caching/config/CachingConfig.java index 4153ec9636..c995bca68d 100644 --- a/spring-all/src/main/java/org/baeldung/caching/config/CachingConfig.java +++ b/spring-all/src/main/java/org/baeldung/caching/config/CachingConfig.java @@ -2,23 +2,19 @@ package org.baeldung.caching.config; import java.util.Arrays; -import org.baeldung.caching.example.CustomerDataService; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.concurrent.ConcurrentMapCache; import org.springframework.cache.support.SimpleCacheManager; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @EnableCaching +@ComponentScan("org.baeldung.caching.example") public class CachingConfig { - @Bean - public CustomerDataService customerDataService() { - return new CustomerDataService(); - } - @Bean public CacheManager cacheManager() { final SimpleCacheManager cacheManager = new SimpleCacheManager(); diff --git a/spring-all/src/main/java/org/baeldung/caching/example/AbstractService.java b/spring-all/src/main/java/org/baeldung/caching/example/AbstractService.java new file mode 100644 index 0000000000..38b5a5a3ec --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/caching/example/AbstractService.java @@ -0,0 +1,76 @@ +package org.baeldung.caching.example; + +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; + +public abstract class AbstractService { + + // this method configuration is equivalent to xml configuration + @Cacheable(value = "addresses", key = "#customer.name") + public String getAddress(final Customer customer) { + return customer.getAddress(); + } + + /** + * The method returns the customer's address, + only it doesn't find it the cache- addresses and directory. + * + * @param customer the customer + * @return the address + */ + @Cacheable({ "addresses", "directory" }) + public String getAddress1(final Customer customer) { + return customer.getAddress(); + } + + /** + * The method returns the customer's address, + but refreshes all the entries in the cache to load new ones. + * + * @param customer the customer + * @return the address + */ + @CacheEvict(value = "addresses", allEntries = true) + public String getAddress2(final Customer customer) { + return customer.getAddress(); + } + + /** + * The method returns the customer's address, + but not before selectively evicting the cache as per specified paramters. + * + * @param customer the customer + * @return the address + */ + @Caching(evict = { @CacheEvict("addresses"), @CacheEvict(value = "directory", key = "#customer.name") }) + public String getAddress3(final Customer customer) { + return customer.getAddress(); + } + + /** + * The method uses the class level cache to look up for entries. + * + * @param customer the customer + * @return the address + */ + @Cacheable + // parameter not required as we have declared it using @CacheConfig + public String getAddress4(final Customer customer) { + return customer.getAddress(); + } + + /** + * The method selectively caches the results that meet the predefined criteria. + * + * @param customer the customer + * @return the address + */ + @CachePut(value = "addresses", condition = "#customer.name=='Tom'") + // @CachePut(value = "addresses", unless = "#result.length>64") + public String getAddress5(final Customer customer) { + return customer.getAddress(); + } + +} diff --git a/spring-all/src/main/java/org/baeldung/caching/example/CustomerDataService.java b/spring-all/src/main/java/org/baeldung/caching/example/CustomerDataService.java index fe4de5d282..1c595057a8 100644 --- a/spring-all/src/main/java/org/baeldung/caching/example/CustomerDataService.java +++ b/spring-all/src/main/java/org/baeldung/caching/example/CustomerDataService.java @@ -1,7 +1,5 @@ package org.baeldung.caching.example; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; @@ -13,9 +11,6 @@ import org.springframework.stereotype.Component; @CacheConfig(cacheNames = { "addresses" }) public class CustomerDataService { - @Autowired - CacheManager cacheManager; - // this method configuration is equivalent to xml configuration @Cacheable(value = "addresses", key = "#customer.name") public String getAddress(final Customer customer) { diff --git a/spring-all/src/main/java/org/baeldung/caching/example/CustomerServiceWithParent.java b/spring-all/src/main/java/org/baeldung/caching/example/CustomerServiceWithParent.java new file mode 100644 index 0000000000..a5ded7daf9 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/caching/example/CustomerServiceWithParent.java @@ -0,0 +1,10 @@ +package org.baeldung.caching.example; + +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.stereotype.Component; + +@Component +@CacheConfig(cacheNames = { "addresses" }) +public class CustomerServiceWithParent extends AbstractService { + // +} diff --git a/spring-all/src/main/java/org/baeldung/controller/config/StudentControllerConfig.java b/spring-all/src/main/java/org/baeldung/controller/config/StudentControllerConfig.java new file mode 100644 index 0000000000..443635fb70 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/controller/config/StudentControllerConfig.java @@ -0,0 +1,31 @@ +package org.baeldung.controller.config; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +public class StudentControllerConfig implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext sc) throws ServletException { + AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); + root.register(WebConfig.class); + + root.setServletContext(sc); + + // Manages the lifecycle of the root application context + sc.addListener(new ContextLoaderListener(root)); + + DispatcherServlet dv = new DispatcherServlet(new GenericWebApplicationContext()); + + ServletRegistration.Dynamic appServlet = sc.addServlet("test-mvc", dv); + appServlet.setLoadOnStartup(1); + appServlet.addMapping("/test/*"); + } +} diff --git a/spring-all/src/main/java/org/baeldung/controller/config/WebConfig.java b/spring-all/src/main/java/org/baeldung/controller/config/WebConfig.java new file mode 100644 index 0000000000..f55af69c88 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/controller/config/WebConfig.java @@ -0,0 +1,28 @@ +package org.baeldung.controller.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +@Configuration +@EnableWebMvc +@ComponentScan(basePackages= {"org.baeldung.controller.controller","org.baeldung.controller.config" }) +public class WebConfig extends WebMvcConfigurerAdapter { + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + @Bean + public ViewResolver viewResolver() { + InternalResourceViewResolver bean = new InternalResourceViewResolver(); + bean.setPrefix("/WEB-INF/"); + bean.setSuffix(".jsp"); + return bean; + } +} \ No newline at end of file diff --git a/spring-all/src/main/java/org/baeldung/controller/controller/RestAnnotatedController.java b/spring-all/src/main/java/org/baeldung/controller/controller/RestAnnotatedController.java new file mode 100644 index 0000000000..48981fd012 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/controller/controller/RestAnnotatedController.java @@ -0,0 +1,19 @@ +package org.baeldung.controller.controller; + +import org.baeldung.controller.student.Student; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class RestAnnotatedController { + + @GetMapping(value = "/annotated/student/{studentId}") + public Student getData(@PathVariable Integer studentId) { + Student student = new Student(); + student.setName("Peter"); + student.setId(studentId); + + return student; + } +} diff --git a/spring-all/src/main/java/org/baeldung/controller/controller/RestController.java b/spring-all/src/main/java/org/baeldung/controller/controller/RestController.java new file mode 100644 index 0000000000..95903bcc40 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/controller/controller/RestController.java @@ -0,0 +1,21 @@ +package org.baeldung.controller.controller; + +import org.baeldung.controller.student.Student; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class RestController{ + + @GetMapping(value="/student/{studentId}") + public @ResponseBody Student getTestData(@PathVariable Integer studentId) { + Student student = new Student(); + student.setName("Peter"); + student.setId(studentId); + + return student; + + } +} diff --git a/spring-all/src/main/java/org/baeldung/controller/controller/TestController.java b/spring-all/src/main/java/org/baeldung/controller/controller/TestController.java new file mode 100644 index 0000000000..12ae4e0ab1 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/controller/controller/TestController.java @@ -0,0 +1,24 @@ + +/** + * @author Prashant Dutta + */ +package org.baeldung.controller.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +@Controller +@RequestMapping(value = "/test") +public class TestController { + + @GetMapping + public ModelAndView getTestData() { + ModelAndView mv = new ModelAndView(); + mv.setViewName("welcome"); + mv.getModel().put("data", "Welcome home man"); + + return mv; + } +} \ No newline at end of file diff --git a/spring-all/src/main/java/org/baeldung/controller/student/Student.java b/spring-all/src/main/java/org/baeldung/controller/student/Student.java new file mode 100644 index 0000000000..ee706d7028 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/controller/student/Student.java @@ -0,0 +1,33 @@ +package org.baeldung.controller.student; + +public class Student { + private String name; + + private int id; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public int hashCode(){ + return this.id; + } + + @Override + public boolean equals(Object obj){ + return this.name.equals(((Student)obj).getName()); + } +} \ No newline at end of file diff --git a/spring-all/src/main/java/org/baeldung/profiles/DatasourceConfig.java b/spring-all/src/main/java/org/baeldung/profiles/DatasourceConfig.java index 80cb060c7e..8fde925fd8 100644 --- a/spring-all/src/main/java/org/baeldung/profiles/DatasourceConfig.java +++ b/spring-all/src/main/java/org/baeldung/profiles/DatasourceConfig.java @@ -1,5 +1,5 @@ package org.baeldung.profiles; public interface DatasourceConfig { - public void setup(); + void setup(); } diff --git a/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithPlaceHolderConfigurer.java b/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithPlaceHolderConfigurer.java new file mode 100644 index 0000000000..f96184a8a3 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithPlaceHolderConfigurer.java @@ -0,0 +1,22 @@ +package org.baeldung.properties.spring; + +import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class PropertiesWithPlaceHolderConfigurer { + + public PropertiesWithPlaceHolderConfigurer() { + super(); + } + + + @Bean + public PropertyPlaceholderConfigurer propertyConfigurer() { + final PropertyPlaceholderConfigurer props = new PropertyPlaceholderConfigurer(); + props.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_FALLBACK); + return props; + } + +} \ No newline at end of file diff --git a/spring-all/src/main/java/org/baeldung/scopes/HelloMessageGenerator.java b/spring-all/src/main/java/org/baeldung/scopes/HelloMessageGenerator.java new file mode 100644 index 0000000000..ae1c6157db --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/scopes/HelloMessageGenerator.java @@ -0,0 +1,15 @@ +package org.baeldung.scopes; + +public class HelloMessageGenerator { + + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(final String message) { + this.message = message; + } + +} diff --git a/spring-all/src/main/java/org/baeldung/scopes/Person.java b/spring-all/src/main/java/org/baeldung/scopes/Person.java new file mode 100644 index 0000000000..e6139c31dd --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/scopes/Person.java @@ -0,0 +1,27 @@ +package org.baeldung.scopes; + +public class Person { + private String name; + private int age; + + public Person() { + } + + public Person(final String name, final int age) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public String toString() { + return "Person [name=" + name + "]"; + } + +} diff --git a/spring-all/src/main/java/org/baeldung/scopes/ScopesController.java b/spring-all/src/main/java/org/baeldung/scopes/ScopesController.java new file mode 100644 index 0000000000..bf733b75f9 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/scopes/ScopesController.java @@ -0,0 +1,31 @@ +package org.baeldung.scopes; + +import javax.annotation.Resource; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class ScopesController { + public static final Logger LOG = Logger.getLogger(ScopesController.class); + + @Resource(name = "requestMessage") + HelloMessageGenerator requestMessage; + + @Resource(name = "sessionMessage") + HelloMessageGenerator sessionMessage; + + @RequestMapping("/scopes") + public String getScopes(final Model model) { + LOG.info("Request Message:" + requestMessage.getMessage()); + LOG.info("Session Message" + sessionMessage.getMessage()); + requestMessage.setMessage("Good morning!"); + sessionMessage.setMessage("Good afternoon!"); + model.addAttribute("requestMessage", requestMessage.getMessage()); + model.addAttribute("sessionMessage", sessionMessage.getMessage()); + return "scopesExample"; + } + +} diff --git a/spring-all/src/main/java/org/baeldung/spring/config/ScopesConfig.java b/spring-all/src/main/java/org/baeldung/spring/config/ScopesConfig.java new file mode 100644 index 0000000000..5a9b266388 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring/config/ScopesConfig.java @@ -0,0 +1,57 @@ +package org.baeldung.spring.config; + +import org.baeldung.scopes.HelloMessageGenerator; +import org.baeldung.scopes.Person; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.view.JstlView; +import org.springframework.web.servlet.view.UrlBasedViewResolver; + +@Configuration +@ComponentScan("org.baeldung.scopes") +@EnableWebMvc +public class ScopesConfig { + @Bean + public UrlBasedViewResolver setupViewResolver() { + final UrlBasedViewResolver resolver = new UrlBasedViewResolver(); + resolver.setPrefix("/WEB-INF/view/"); + resolver.setSuffix(".jsp"); + resolver.setViewClass(JstlView.class); + return resolver; + } + + @Bean + @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) + public HelloMessageGenerator requestMessage() { + return new HelloMessageGenerator(); + } + + @Bean + @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) + public HelloMessageGenerator sessionMessage() { + return new HelloMessageGenerator(); + } + + @Bean + @Scope(value = WebApplicationContext.SCOPE_GLOBAL_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) + public HelloMessageGenerator globalSessionMessage() { + return new HelloMessageGenerator(); + } + + @Bean + @Scope("prototype") + public Person personPrototype() { + return new Person(); + } + + @Bean + @Scope("singleton") + public Person personSingleton() { + return new Person(); + } +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/attributeannotations/AttributeAnnotationsTestController.java b/spring-all/src/main/java/org/baeldung/spring43/attributeannotations/AttributeAnnotationsTestController.java new file mode 100644 index 0000000000..df1d173bd2 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/attributeannotations/AttributeAnnotationsTestController.java @@ -0,0 +1,14 @@ +package org.baeldung.spring43.attributeannotations; + +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/test") +public class AttributeAnnotationsTestController { + + @GetMapping + public String get(@SessionAttribute String login, @RequestAttribute String query) { + return String.format("login = %s, query = %s", login, query); + } + +} \ No newline at end of file diff --git a/spring-all/src/main/java/org/baeldung/spring43/attributeannotations/ParamInterceptor.java b/spring-all/src/main/java/org/baeldung/spring43/attributeannotations/ParamInterceptor.java new file mode 100644 index 0000000000..9cf6020a93 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/attributeannotations/ParamInterceptor.java @@ -0,0 +1,17 @@ +package org.baeldung.spring43.attributeannotations; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +public class ParamInterceptor extends HandlerInterceptorAdapter { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + request.getSession().setAttribute("login", "john"); + request.setAttribute("query", "invoices"); + return super.preHandle(request, response, handler); + } + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/cache/Foo.java b/spring-all/src/main/java/org/baeldung/spring43/cache/Foo.java new file mode 100644 index 0000000000..4abd3cc813 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/cache/Foo.java @@ -0,0 +1,29 @@ +package org.baeldung.spring43.cache; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Foo { + + private static final Logger log = LoggerFactory.getLogger(Foo.class); + + private static final AtomicInteger instanceCount = new AtomicInteger(0); + + + private final int instanceNum; + + public Foo() { + instanceNum = instanceCount.incrementAndGet(); + } + + public static int getInstanceCount() { + return instanceCount.get(); + } + + public void printInstanceNumber() { + log.info("Foo instance number: {}", instanceNum); + } + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/cache/FooService.java b/spring-all/src/main/java/org/baeldung/spring43/cache/FooService.java new file mode 100644 index 0000000000..ad4c8b395f --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/cache/FooService.java @@ -0,0 +1,14 @@ +package org.baeldung.spring43.cache; + +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +public class FooService { + + @Cacheable(cacheNames = "foos", sync = true) + public Foo getFoo(String id) { + return new Foo(); + } + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/composedmapping/Appointment.java b/spring-all/src/main/java/org/baeldung/spring43/composedmapping/Appointment.java new file mode 100644 index 0000000000..af06249768 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/composedmapping/Appointment.java @@ -0,0 +1,5 @@ +package org.baeldung.spring43.composedmapping; + +public class Appointment { + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/composedmapping/AppointmentService.java b/spring-all/src/main/java/org/baeldung/spring43/composedmapping/AppointmentService.java new file mode 100644 index 0000000000..c4c5e82f65 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/composedmapping/AppointmentService.java @@ -0,0 +1,9 @@ +package org.baeldung.spring43.composedmapping; + +import java.util.Map; + +public interface AppointmentService { + + Map getAppointmentsForToday(); + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/composedmapping/AppointmentsController.java b/spring-all/src/main/java/org/baeldung/spring43/composedmapping/AppointmentsController.java new file mode 100644 index 0000000000..9f3c8729d8 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/composedmapping/AppointmentsController.java @@ -0,0 +1,26 @@ +package org.baeldung.spring43.composedmapping; + +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/appointments") +public class AppointmentsController { + + private final AppointmentService appointmentService; + + @Autowired + public AppointmentsController(AppointmentService appointmentService) { + this.appointmentService = appointmentService; + } + + @GetMapping + public Map get() { + return appointmentService.getAppointmentsForToday(); + } + +} \ No newline at end of file diff --git a/spring-all/src/main/java/org/baeldung/spring43/ctor/FooRepository.java b/spring-all/src/main/java/org/baeldung/spring43/ctor/FooRepository.java new file mode 100644 index 0000000000..96dbeb8642 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/ctor/FooRepository.java @@ -0,0 +1,5 @@ +package org.baeldung.spring43.ctor; + +public class FooRepository { + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/ctor/FooService.java b/spring-all/src/main/java/org/baeldung/spring43/ctor/FooService.java new file mode 100644 index 0000000000..bf92d1bd32 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/ctor/FooService.java @@ -0,0 +1,15 @@ +package org.baeldung.spring43.ctor; + +public class FooService { + + private final FooRepository repository; + + public FooService(FooRepository repository) { + this.repository = repository; + } + + public FooRepository getRepository() { + return repository; + } + +} \ No newline at end of file diff --git a/spring-all/src/main/java/org/baeldung/spring43/defaultmethods/DateHolder.java b/spring-all/src/main/java/org/baeldung/spring43/defaultmethods/DateHolder.java new file mode 100644 index 0000000000..9ae62cf484 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/defaultmethods/DateHolder.java @@ -0,0 +1,18 @@ +package org.baeldung.spring43.defaultmethods; + +import java.time.LocalDate; + +public class DateHolder implements IDateHolder { + + private LocalDate localDate; + + @Override + public LocalDate getLocalDate() { + return localDate; + } + + @Override + public void setLocalDate(LocalDate localDate) { + this.localDate = localDate; + } +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/defaultmethods/IDateHolder.java b/spring-all/src/main/java/org/baeldung/spring43/defaultmethods/IDateHolder.java new file mode 100644 index 0000000000..e37d27f9fc --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/defaultmethods/IDateHolder.java @@ -0,0 +1,16 @@ +package org.baeldung.spring43.defaultmethods; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +public interface IDateHolder { + + LocalDate getLocalDate(); + + void setLocalDate(LocalDate localDate); + + default void setStringDate(String stringDate) { + setLocalDate(LocalDate.parse(stringDate, DateTimeFormatter.ofPattern("dd.MM.yyyy"))); + } + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/depresolution/FooRepository.java b/spring-all/src/main/java/org/baeldung/spring43/depresolution/FooRepository.java new file mode 100644 index 0000000000..313f6fc8c5 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/depresolution/FooRepository.java @@ -0,0 +1,8 @@ +package org.baeldung.spring43.depresolution; + +import org.springframework.stereotype.Repository; + +@Repository +public class FooRepository { + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/depresolution/FooService.java b/spring-all/src/main/java/org/baeldung/spring43/depresolution/FooService.java new file mode 100644 index 0000000000..b76fa84749 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/depresolution/FooService.java @@ -0,0 +1,18 @@ +package org.baeldung.spring43.depresolution; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.stereotype.Service; + +@Service +public class FooService { + + private final FooRepository repository; + + public FooService(ObjectProvider repositoryProvider) { + this.repository = repositoryProvider.getIfUnique(); + } + + public FooRepository getRepository() { + return repository; + } +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/AppPreferences.java b/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/AppPreferences.java new file mode 100644 index 0000000000..45b90c4609 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/AppPreferences.java @@ -0,0 +1,10 @@ +package org.baeldung.spring43.scopeannotations; + +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.ApplicationScope; + +@Component +@ApplicationScope +public class AppPreferences extends InstanceCountingService { + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/InstanceCountingService.java b/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/InstanceCountingService.java new file mode 100644 index 0000000000..4fb90566d8 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/InstanceCountingService.java @@ -0,0 +1,15 @@ +package org.baeldung.spring43.scopeannotations; + +import java.util.concurrent.atomic.AtomicInteger; + +public class InstanceCountingService { + + private static final AtomicInteger instanceCount = new AtomicInteger(0); + + private final int instanceNumber = instanceCount.incrementAndGet(); + + public int getInstanceNumber() { + return instanceNumber; + } + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/LoginAction.java b/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/LoginAction.java new file mode 100644 index 0000000000..60017b4b94 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/LoginAction.java @@ -0,0 +1,10 @@ +package org.baeldung.spring43.scopeannotations; + +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; + +@Component +@RequestScope +public class LoginAction extends InstanceCountingService { + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/ScopeTestController.java b/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/ScopeTestController.java new file mode 100644 index 0000000000..8f4390dfc0 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/ScopeTestController.java @@ -0,0 +1,36 @@ +package org.baeldung.spring43.scopeannotations; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/appointments") +public class ScopeTestController { + + @Autowired + private LoginAction loginAction; + + @Autowired + private UserPreferences userPreferences; + + @Autowired + private AppPreferences appPreferences; + + @GetMapping("/request") + public String getRequestNumber() { + return Integer.toString(loginAction.getInstanceNumber()); + } + + @GetMapping("/session") + public String getSessionNumber() { + return Integer.toString(userPreferences.getInstanceNumber()); + } + + @GetMapping("/application") + public String getApplicationNumber() { + return Integer.toString(appPreferences.getInstanceNumber()); + } + +} diff --git a/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/UserPreferences.java b/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/UserPreferences.java new file mode 100644 index 0000000000..ce49c4b1fe --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/spring43/scopeannotations/UserPreferences.java @@ -0,0 +1,10 @@ +package org.baeldung.spring43.scopeannotations; + +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.SessionScope; + +@Component +@SessionScope +public class UserPreferences extends InstanceCountingService { + +} diff --git a/spring-all/src/main/java/org/baeldung/startup/AllStrategiesExampleBean.java b/spring-all/src/main/java/org/baeldung/startup/AllStrategiesExampleBean.java new file mode 100644 index 0000000000..d4334437f7 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/startup/AllStrategiesExampleBean.java @@ -0,0 +1,33 @@ +package org.baeldung.startup; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +@Component +@Scope(value = "prototype") +public class AllStrategiesExampleBean implements InitializingBean { + + private static final Logger LOG = Logger.getLogger(AllStrategiesExampleBean.class); + + public AllStrategiesExampleBean() { + LOG.info("Constructor"); + } + + @Override + public void afterPropertiesSet() throws Exception { + LOG.info("InitializingBean"); + } + + @PostConstruct + public void postConstruct() { + LOG.info("PostConstruct"); + } + + public void init() { + LOG.info("init-method"); + } +} diff --git a/spring-all/src/main/java/org/baeldung/startup/EventListenerExampleBean.java b/spring-all/src/main/java/org/baeldung/startup/EventListenerExampleBean.java new file mode 100644 index 0000000000..e9cd1a159d --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/startup/EventListenerExampleBean.java @@ -0,0 +1,19 @@ +package org.baeldung.startup; + +import org.apache.log4j.Logger; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +@Component +public class EventListenerExampleBean { + private static final Logger LOG = Logger.getLogger(EventListenerExampleBean.class); + + public static int counter; + + @EventListener + public void onApplicationEvent(ContextRefreshedEvent event) { + LOG.info("Increment counter"); + counter++; + } +} diff --git a/spring-all/src/main/java/org/baeldung/startup/InitMethodExampleBean.java b/spring-all/src/main/java/org/baeldung/startup/InitMethodExampleBean.java new file mode 100644 index 0000000000..cea6b026d6 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/startup/InitMethodExampleBean.java @@ -0,0 +1,23 @@ +package org.baeldung.startup; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.util.Arrays; + +@Component +@Scope(value = "prototype") +public class InitMethodExampleBean { + + private static final Logger LOG = Logger.getLogger(InitMethodExampleBean.class); + + @Autowired + private Environment environment; + + public void init() { + LOG.info(Arrays.asList(environment.getDefaultProfiles())); + } +} diff --git a/spring-all/src/main/java/org/baeldung/startup/InitializingBeanExampleBean.java b/spring-all/src/main/java/org/baeldung/startup/InitializingBeanExampleBean.java new file mode 100644 index 0000000000..33b14864f3 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/startup/InitializingBeanExampleBean.java @@ -0,0 +1,25 @@ +package org.baeldung.startup; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.util.Arrays; + +@Component +@Scope(value = "prototype") +public class InitializingBeanExampleBean implements InitializingBean { + + private static final Logger LOG = Logger.getLogger(InitializingBeanExampleBean.class); + + @Autowired + private Environment environment; + + @Override + public void afterPropertiesSet() throws Exception { + LOG.info(Arrays.asList(environment.getDefaultProfiles())); + } +} diff --git a/spring-all/src/main/java/org/baeldung/startup/InvalidInitExampleBean.java b/spring-all/src/main/java/org/baeldung/startup/InvalidInitExampleBean.java new file mode 100644 index 0000000000..0b9c6f0c7d --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/startup/InvalidInitExampleBean.java @@ -0,0 +1,18 @@ +package org.baeldung.startup; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +@Component +@Scope("prototype") +public class InvalidInitExampleBean { + + @Autowired + private Environment environment; + + public InvalidInitExampleBean() { + environment.getActiveProfiles(); + } +} diff --git a/spring-all/src/main/java/org/baeldung/startup/LogicInConstructorExampleBean.java b/spring-all/src/main/java/org/baeldung/startup/LogicInConstructorExampleBean.java new file mode 100644 index 0000000000..2a7b3e26c7 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/startup/LogicInConstructorExampleBean.java @@ -0,0 +1,25 @@ +package org.baeldung.startup; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.util.Arrays; + +@Component +@Scope(value = "prototype") +public class LogicInConstructorExampleBean { + + private static final Logger LOG = Logger.getLogger(LogicInConstructorExampleBean.class); + + private final Environment environment; + + @Autowired + public LogicInConstructorExampleBean(Environment environment) { + this.environment = environment; + + LOG.info(Arrays.asList(environment.getDefaultProfiles())); + } +} diff --git a/spring-all/src/main/java/org/baeldung/startup/PostConstructExampleBean.java b/spring-all/src/main/java/org/baeldung/startup/PostConstructExampleBean.java new file mode 100644 index 0000000000..4cabaad4df --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/startup/PostConstructExampleBean.java @@ -0,0 +1,25 @@ +package org.baeldung.startup; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.Arrays; + +@Component +@Scope(value = "prototype") +public class PostConstructExampleBean { + + private static final Logger LOG = Logger.getLogger(PostConstructExampleBean.class); + + @Autowired + private Environment environment; + + @PostConstruct + public void init() { + LOG.info(Arrays.asList(environment.getDefaultProfiles())); + } +} diff --git a/spring-all/src/main/java/org/baeldung/startup/SpringStartupConfig.java b/spring-all/src/main/java/org/baeldung/startup/SpringStartupConfig.java new file mode 100644 index 0000000000..12854e1be5 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/startup/SpringStartupConfig.java @@ -0,0 +1,9 @@ +package org.baeldung.startup; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("org.baeldung.startup") +public class SpringStartupConfig { +} \ No newline at end of file diff --git a/spring-all/src/main/java/org/baeldung/startup/StartupApplicationListenerExample.java b/spring-all/src/main/java/org/baeldung/startup/StartupApplicationListenerExample.java new file mode 100644 index 0000000000..32a63f0c1a --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/startup/StartupApplicationListenerExample.java @@ -0,0 +1,20 @@ +package org.baeldung.startup; + +import org.apache.log4j.Logger; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.stereotype.Component; + +@Component +public class StartupApplicationListenerExample implements ApplicationListener { + + private static final Logger LOG = Logger.getLogger(StartupApplicationListenerExample.class); + + public static int counter; + + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + LOG.info("Increment counter"); + counter++; + } +} diff --git a/spring-all/src/main/resources/defaultmethods-context.xml b/spring-all/src/main/resources/defaultmethods-context.xml new file mode 100644 index 0000000000..2b55037405 --- /dev/null +++ b/spring-all/src/main/resources/defaultmethods-context.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/spring-all/src/main/resources/implicit-ctor-context.xml b/spring-all/src/main/resources/implicit-ctor-context.xml new file mode 100644 index 0000000000..c978ca17bd --- /dev/null +++ b/spring-all/src/main/resources/implicit-ctor-context.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/spring-all/src/main/resources/scopes.xml b/spring-all/src/main/resources/scopes.xml new file mode 100644 index 0000000000..faecd727fa --- /dev/null +++ b/spring-all/src/main/resources/scopes.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/spring-all/src/main/resources/springAsync-config.xml b/spring-all/src/main/resources/springAsync-config.xml index 8ed5f1319d..34e8b33f45 100644 --- a/spring-all/src/main/resources/springAsync-config.xml +++ b/spring-all/src/main/resources/springAsync-config.xml @@ -9,6 +9,6 @@ - + \ No newline at end of file diff --git a/spring-all/src/main/resources/startupConfig.xml b/spring-all/src/main/resources/startupConfig.xml new file mode 100644 index 0000000000..8226665a90 --- /dev/null +++ b/spring-all/src/main/resources/startupConfig.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/spring-all/src/main/resources/test-mvc.xml b/spring-all/src/main/resources/test-mvc.xml new file mode 100644 index 0000000000..15f950ed4f --- /dev/null +++ b/spring-all/src/main/resources/test-mvc.xml @@ -0,0 +1,24 @@ + + + + + + + + /WEB-INF/ + + + .jsp + + + \ No newline at end of file diff --git a/spring-all/src/main/webapp/WEB-INF/view/scopesExample.jsp b/spring-all/src/main/webapp/WEB-INF/view/scopesExample.jsp new file mode 100644 index 0000000000..7974cf0220 --- /dev/null +++ b/spring-all/src/main/webapp/WEB-INF/view/scopesExample.jsp @@ -0,0 +1,10 @@ + + + + +

    Bean Scopes Examples

    +
    + Request Message: ${requestMessage }
    + Session Message: ${sessionMessage } + + \ No newline at end of file diff --git a/spring-all/src/main/webapp/WEB-INF/web.xml b/spring-all/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..4e0e7a231c --- /dev/null +++ b/spring-all/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,27 @@ + + + + test-mvc + + org.springframework.web.servlet.DispatcherServlet + + 1 + + contextConfigLocation + /WEB-INF/test-mvc.xml + + + + + test-mvc + /test/* + + + + /WEB-INF/index.jsp + + diff --git a/spring-all/src/main/webapp/WEB-INF/welcome.jsp b/spring-all/src/main/webapp/WEB-INF/welcome.jsp new file mode 100644 index 0000000000..61ee4bc7d6 --- /dev/null +++ b/spring-all/src/main/webapp/WEB-INF/welcome.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> + + + + +Insert title here + + +Data returned is ${data} + + \ No newline at end of file diff --git a/spring-all/src/test/java/org/baeldung/caching/test/SpringCachingBehaviorTest.java b/spring-all/src/test/java/org/baeldung/caching/test/SpringCachingBehaviorTest.java deleted file mode 100644 index a4a3733dd8..0000000000 --- a/spring-all/src/test/java/org/baeldung/caching/test/SpringCachingBehaviorTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.baeldung.caching.test; - -import org.baeldung.caching.config.CachingConfig; -import org.baeldung.caching.example.Customer; -import org.baeldung.caching.example.CustomerDataService; -import org.junit.Test; -import org.springframework.stereotype.Component; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; - -@Component -public class SpringCachingBehaviorTest { - - @Test - public void testCaching() { - @SuppressWarnings("resource") - final - // final ApplicationContext context = new ClassPathXmlApplicationContext("config.xml"); - AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - context.register(CachingConfig.class); - context.refresh(); - final CustomerDataService service = context.getBean(CustomerDataService.class); - - final Customer cust = new Customer("Tom", "67-2, Downing Street, NY"); - service.getAddress(cust); - service.getAddress(cust); - - // fail("Unable to instantiate the CustomerDataService"); - } - -} diff --git a/spring-all/src/test/java/org/baeldung/caching/test/SpringCachingIntegrationTest.java b/spring-all/src/test/java/org/baeldung/caching/test/SpringCachingIntegrationTest.java new file mode 100644 index 0000000000..8c4ebaa7ec --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/caching/test/SpringCachingIntegrationTest.java @@ -0,0 +1,71 @@ +package org.baeldung.caching.test; + +import org.baeldung.caching.config.CachingConfig; +import org.baeldung.caching.example.Customer; +import org.baeldung.caching.example.CustomerDataService; +import org.baeldung.caching.example.CustomerServiceWithParent; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { CachingConfig.class }, loader = AnnotationConfigContextLoader.class) +public class SpringCachingIntegrationTest { + + @Autowired + private CustomerDataService service; + + @Autowired + private CustomerServiceWithParent serviceWithParent; + + // + + @Test + public void whenGettingAddress_thenCorrect() { + final Customer cust = new Customer("Tom", "67-2, Downing Street, NY"); + service.getAddress(cust); + service.getAddress(cust); + + service.getAddress1(cust); + service.getAddress1(cust); + + service.getAddress2(cust); + service.getAddress2(cust); + + service.getAddress3(cust); + service.getAddress3(cust); + + service.getAddress4(cust); + service.getAddress4(cust); + + service.getAddress5(cust); + service.getAddress5(cust); + } + + @Test + public void givenUsingServiceWithParent_whenGettingAddress_thenCorrect() { + final Customer cust = new Customer("Tom", "67-2, Downing Street, NY"); + + serviceWithParent.getAddress(cust); + serviceWithParent.getAddress(cust); + + serviceWithParent.getAddress1(cust); + serviceWithParent.getAddress1(cust); + + serviceWithParent.getAddress2(cust); + serviceWithParent.getAddress2(cust); + + serviceWithParent.getAddress3(cust); + serviceWithParent.getAddress3(cust); + + // serviceWithParent.getAddress4(cust); + // serviceWithParent.getAddress4(cust); + + serviceWithParent.getAddress5(cust); + serviceWithParent.getAddress5(cust); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/controller/ControllerAnnotationTest.java b/spring-all/src/test/java/org/baeldung/controller/ControllerAnnotationTest.java new file mode 100644 index 0000000000..44f1767405 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/controller/ControllerAnnotationTest.java @@ -0,0 +1,86 @@ +package org.baeldung.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.baeldung.controller.config.WebConfig; +import org.baeldung.controller.student.Student; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.AnnotationConfigWebContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.ModelAndView; + + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes={WebConfig.class}, loader=AnnotationConfigWebContextLoader.class ) +public class ControllerAnnotationTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + private Student selectedStudent; + + @Before + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + + selectedStudent = new Student(); + selectedStudent.setId(1); + selectedStudent.setName("Peter"); + } + + @Test + public void testTestController() throws Exception { + + ModelAndView mv = this.mockMvc.perform(MockMvcRequestBuilders.get("/test/")) + .andReturn() + .getModelAndView(); + + // validate modal data + Assert.assertSame(mv.getModelMap().get("data").toString(), "Welcome home man"); + + // validate view name + Assert.assertSame(mv.getViewName(), "welcome"); + } + + @Test + public void testRestController() throws Exception { + + String responseBody = this.mockMvc.perform(MockMvcRequestBuilders.get("/student/{studentId}", 1)) + .andReturn().getResponse() + .getContentAsString(); + + ObjectMapper reader = new ObjectMapper(); + + Student studentDetails = reader.readValue(responseBody, Student.class); + + Assert.assertEquals(selectedStudent, studentDetails); + + } + + @Test + public void testRestAnnotatedController() throws Exception { + + String responseBody = this.mockMvc.perform(MockMvcRequestBuilders.get("/annotated/student/{studentId}", 1)) + .andReturn().getResponse() + .getContentAsString(); + + ObjectMapper reader = new ObjectMapper(); + + Student studentDetails = reader.readValue(responseBody, Student.class); + + Assert.assertEquals(selectedStudent, studentDetails); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/controller/ControllerTest.java b/spring-all/src/test/java/org/baeldung/controller/ControllerTest.java new file mode 100644 index 0000000000..f5e41cd5a2 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/controller/ControllerTest.java @@ -0,0 +1,83 @@ +package org.baeldung.controller; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.ModelAndView; + +import org.baeldung.controller.student.Student; +import com.fasterxml.jackson.databind.ObjectMapper; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration({"classpath:test-mvc.xml"}) +public class ControllerTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + private Student selectedStudent; + + @Before + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + + selectedStudent = new Student(); + selectedStudent.setId(1); + selectedStudent.setName("Peter"); + } + + @Test + public void testTestController() throws Exception { + + ModelAndView mv = this.mockMvc.perform(MockMvcRequestBuilders.get("/test/")) + .andReturn() + .getModelAndView(); + + // validate modal data + Assert.assertSame(mv.getModelMap().get("data").toString(), "Welcome home man"); + + // validate view name + Assert.assertSame(mv.getViewName(), "welcome"); + } + + @Test + public void testRestController() throws Exception { + + String responseBody = this.mockMvc.perform(MockMvcRequestBuilders.get("/student/{studentId}", 1)) + .andReturn().getResponse() + .getContentAsString(); + + ObjectMapper reader = new ObjectMapper(); + + Student studentDetails = reader.readValue(responseBody, Student.class); + + Assert.assertEquals(selectedStudent, studentDetails); + + } + + @Test + public void testRestAnnotatedController() throws Exception { + + String responseBody = this.mockMvc.perform(MockMvcRequestBuilders.get("/annotated/student/{studentId}", 1)) + .andReturn().getResponse() + .getContentAsString(); + + ObjectMapper reader = new ObjectMapper(); + + Student studentDetails = reader.readValue(responseBody, Student.class); + + Assert.assertEquals(selectedStudent, studentDetails); + } +} diff --git a/spring-all/src/test/java/org/baeldung/scopes/ScopesTest.java b/spring-all/src/test/java/org/baeldung/scopes/ScopesTest.java new file mode 100644 index 0000000000..b1dd248c26 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/scopes/ScopesTest.java @@ -0,0 +1,43 @@ +package org.baeldung.scopes; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class ScopesTest { + + private static final String NAME = "John Smith"; + private static final String NAME_OTHER = "Anna Jones"; + + @Test + public void testScopeSingleton() { + final ApplicationContext applicationContext = new ClassPathXmlApplicationContext("scopes.xml"); + + final Person personSingletonA = (Person) applicationContext.getBean("personSingleton"); + final Person personSingletonB = (Person) applicationContext.getBean("personSingleton"); + + personSingletonA.setName(NAME); + Assert.assertEquals(NAME, personSingletonB.getName()); + + ((AbstractApplicationContext) applicationContext).close(); + } + + @Test + public void testScopePrototype() { + final ApplicationContext applicationContext = new ClassPathXmlApplicationContext("scopes.xml"); + + final Person personPrototypeA = (Person) applicationContext.getBean("personPrototype"); + final Person personPrototypeB = (Person) applicationContext.getBean("personPrototype"); + + personPrototypeA.setName(NAME); + personPrototypeB.setName(NAME_OTHER); + + Assert.assertEquals(NAME, personPrototypeA.getName()); + Assert.assertEquals(NAME_OTHER, personPrototypeB.getName()); + + ((AbstractApplicationContext) applicationContext).close(); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/attributeannotations/AttributeAnnotationConfiguration.java b/spring-all/src/test/java/org/baeldung/spring43/attributeannotations/AttributeAnnotationConfiguration.java new file mode 100644 index 0000000000..97ae651473 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/attributeannotations/AttributeAnnotationConfiguration.java @@ -0,0 +1,30 @@ +package org.baeldung.spring43.attributeannotations; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +@Configuration +@ComponentScan +@EnableWebMvc +public class AttributeAnnotationConfiguration extends WebMvcConfigurerAdapter { + + @Bean + public ViewResolver viewResolver() { + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/WEB-INF/jsp/view/"); + viewResolver.setSuffix(".jsp"); + return viewResolver; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new ParamInterceptor()); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/attributeannotations/AttributeAnnotationTest.java b/spring-all/src/test/java/org/baeldung/spring43/attributeannotations/AttributeAnnotationTest.java new file mode 100644 index 0000000000..aa3acb113f --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/attributeannotations/AttributeAnnotationTest.java @@ -0,0 +1,45 @@ +package org.baeldung.spring43.attributeannotations; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@ContextConfiguration(classes = AttributeAnnotationConfiguration.class) +@WebAppConfiguration +public class AttributeAnnotationTest extends AbstractJUnit4SpringContextTests { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(wac) + .build(); + } + + @Test + public void whenInterceptorAddsRequestAndSessionParams_thenParamsInjectedWithAttributesAnnotations() throws Exception { + String result = this.mockMvc.perform(get("/test") + .accept(MediaType.ALL)) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + Assert.assertEquals("login = john, query = invoices", result); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/cache/CacheRefinementsConfiguration.java b/spring-all/src/test/java/org/baeldung/spring43/cache/CacheRefinementsConfiguration.java new file mode 100644 index 0000000000..e4610e5a83 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/cache/CacheRefinementsConfiguration.java @@ -0,0 +1,25 @@ +package org.baeldung.spring43.cache; + +import java.util.Collections; + +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.concurrent.ConcurrentMapCache; +import org.springframework.cache.support.SimpleCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan +@EnableCaching +public class CacheRefinementsConfiguration { + + @Bean + public CacheManager cacheManager() { + SimpleCacheManager manager = new SimpleCacheManager(); + manager.setCaches(Collections.singletonList(new ConcurrentMapCache("foos"))); + return manager; + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/cache/CacheRefinementsTest.java b/spring-all/src/test/java/org/baeldung/spring43/cache/CacheRefinementsTest.java new file mode 100644 index 0000000000..bfd6e5047c --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/cache/CacheRefinementsTest.java @@ -0,0 +1,31 @@ +package org.baeldung.spring43.cache; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; + +import static org.junit.Assert.assertEquals; + +@ContextConfiguration(classes = CacheRefinementsConfiguration.class) +public class CacheRefinementsTest extends AbstractJUnit4SpringContextTests { + + private ExecutorService executorService = Executors.newFixedThreadPool(10); + + @Autowired + private FooService service; + + @Test + public void whenMultipleThreadsExecuteCacheableMethodWithSyncTrue_thenMethodIsExecutedOnlyOnce() throws InterruptedException { + for (int i = 0; i < 10; i++) { + executorService.execute(() -> service.getFoo("test").printInstanceNumber()); + } + executorService.awaitTermination(1, TimeUnit.SECONDS); + assertEquals(Foo.getInstanceCount(), 1); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/composedmapping/ComposedMappingConfiguration.java b/spring-all/src/test/java/org/baeldung/spring43/composedmapping/ComposedMappingConfiguration.java new file mode 100644 index 0000000000..46bf3d8847 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/composedmapping/ComposedMappingConfiguration.java @@ -0,0 +1,36 @@ +package org.baeldung.spring43.composedmapping; + +import java.util.Collections; + +import org.easymock.EasyMock; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +import static org.easymock.EasyMock.*; + +@Configuration +@ComponentScan +@EnableWebMvc +public class ComposedMappingConfiguration { + + @Bean + public ViewResolver viewResolver() { + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/WEB-INF/jsp/view/"); + viewResolver.setSuffix(".jsp"); + return viewResolver; + } + + @Bean + public AppointmentService appointmentBook() { + AppointmentService book = EasyMock.mock(AppointmentService.class); + EasyMock.expect(book.getAppointmentsForToday()).andReturn(Collections.emptyMap()); + replay(book); + return book; + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/composedmapping/ComposedMappingTest.java b/spring-all/src/test/java/org/baeldung/spring43/composedmapping/ComposedMappingTest.java new file mode 100644 index 0000000000..04fabbc834 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/composedmapping/ComposedMappingTest.java @@ -0,0 +1,44 @@ +package org.baeldung.spring43.composedmapping; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.easymock.EasyMock.verify; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@ContextConfiguration(classes = ComposedMappingConfiguration.class) +@WebAppConfiguration +public class ComposedMappingTest extends AbstractJUnit4SpringContextTests { + + @Autowired + private AppointmentService appointmentService; + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(wac) + .build(); + } + + @Test + public void whenRequestingMethodWithGetMapping_thenReceiving200Answer() throws Exception { + this.mockMvc.perform(get("/appointments") + .accept(MediaType.ALL)) + .andExpect(status().isOk()); + verify(appointmentService); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/ctor/ConfigurationConstructorInjectionTest.java b/spring-all/src/test/java/org/baeldung/spring43/ctor/ConfigurationConstructorInjectionTest.java new file mode 100644 index 0000000000..82caae15fe --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/ctor/ConfigurationConstructorInjectionTest.java @@ -0,0 +1,21 @@ +package org.baeldung.spring43.ctor; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; + +import static org.junit.Assert.assertNotNull; + +@ContextConfiguration(classes = {FooRepositoryConfiguration.class, FooServiceConfiguration.class}) +public class ConfigurationConstructorInjectionTest extends AbstractJUnit4SpringContextTests { + + @Autowired + public FooService fooService; + + @Test + public void whenSingleCtorInConfiguration_thenContextLoadsNormally() { + assertNotNull(fooService.getRepository()); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/ctor/FooRepositoryConfiguration.java b/spring-all/src/test/java/org/baeldung/spring43/ctor/FooRepositoryConfiguration.java new file mode 100644 index 0000000000..a05a36529f --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/ctor/FooRepositoryConfiguration.java @@ -0,0 +1,14 @@ +package org.baeldung.spring43.ctor; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FooRepositoryConfiguration { + + @Bean + public FooRepository fooRepository() { + return new FooRepository(); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/ctor/FooServiceConfiguration.java b/spring-all/src/test/java/org/baeldung/spring43/ctor/FooServiceConfiguration.java new file mode 100644 index 0000000000..41f1719320 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/ctor/FooServiceConfiguration.java @@ -0,0 +1,19 @@ +package org.baeldung.spring43.ctor; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FooServiceConfiguration { + + private final FooRepository repository; + + public FooServiceConfiguration(FooRepository repository) { + this.repository = repository; + } + + @Bean + public FooService fooService() { + return new FooService(this.repository); + } +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/ctor/ImplicitConstructorTest.java b/spring-all/src/test/java/org/baeldung/spring43/ctor/ImplicitConstructorTest.java new file mode 100644 index 0000000000..be0cf77a62 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/ctor/ImplicitConstructorTest.java @@ -0,0 +1,21 @@ +package org.baeldung.spring43.ctor; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; + +import static org.junit.Assert.assertNotNull; + +@ContextConfiguration("classpath:implicit-ctor-context.xml") +public class ImplicitConstructorTest extends AbstractJUnit4SpringContextTests { + + @Autowired + private FooService fooService; + + @Test + public void whenBeanWithoutAutowiredCtor_thenInjectIntoSingleCtor() { + assertNotNull(fooService.getRepository()); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/DefaultMethodsInjectionTest.java b/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/DefaultMethodsInjectionTest.java new file mode 100644 index 0000000000..e29d89a679 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/DefaultMethodsInjectionTest.java @@ -0,0 +1,23 @@ +package org.baeldung.spring43.defaultmethods; + +import java.time.LocalDate; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; + +import static org.junit.Assert.assertEquals; + +@ContextConfiguration("classpath:defaultmethods-context.xml") +public class DefaultMethodsInjectionTest extends AbstractJUnit4SpringContextTests { + + @Autowired + private IDateHolder dateHolder; + + @Test + public void whenInjectingToDefaultInterfaceMethod_thenInjectionShouldHappen() { + assertEquals(LocalDate.of(1982, 10, 15), dateHolder.getLocalDate()); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/ITransactionalTest.java b/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/ITransactionalTest.java new file mode 100644 index 0000000000..c7b95bced4 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/ITransactionalTest.java @@ -0,0 +1,22 @@ +package org.baeldung.spring43.defaultmethods; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.test.context.transaction.AfterTransaction; +import org.springframework.test.context.transaction.BeforeTransaction; + +public interface ITransactionalTest { + + Logger log = LoggerFactory.getLogger(ITransactionalTest.class); + + @BeforeTransaction + default void beforeTransaction() { + log.info("Opening transaction"); + } + + @AfterTransaction + default void afterTransaction() { + log.info("Closing transaction"); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/TransactionalTest.java b/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/TransactionalTest.java new file mode 100644 index 0000000000..89c96ba1d4 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/TransactionalTest.java @@ -0,0 +1,14 @@ +package org.baeldung.spring43.defaultmethods; + +import org.junit.Test; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; + +@ContextConfiguration(classes = TransactionalTestConfiguration.class) +public class TransactionalTest extends AbstractTransactionalJUnit4SpringContextTests implements ITransactionalTest { + + @Test + public void whenDefaultMethodAnnotatedWithBeforeTransaction_thenDefaultMethodIsExecuted() { + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/TransactionalTestConfiguration.java b/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/TransactionalTestConfiguration.java new file mode 100644 index 0000000000..946b19d00d --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/defaultmethods/TransactionalTestConfiguration.java @@ -0,0 +1,30 @@ +package org.baeldung.spring43.defaultmethods; + + +import javax.sql.DataSource; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.SimpleDriverDataSource; +import org.springframework.transaction.PlatformTransactionManager; + +@Configuration +public class TransactionalTestConfiguration { + + @Bean + public DataSource getDataSource() { + SimpleDriverDataSource simpleDriverDataSource = new SimpleDriverDataSource(); + simpleDriverDataSource.setDriverClass(org.hsqldb.jdbcDriver.class); + simpleDriverDataSource.setUrl("jdbc:hsqldb:mem:app-db"); + simpleDriverDataSource.setUsername("sa"); + simpleDriverDataSource.setPassword(""); + return simpleDriverDataSource; + } + + @Bean + public PlatformTransactionManager transactionManager() { + return new DataSourceTransactionManager(getDataSource()); + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/depresolution/ObjectProviderConfiguration.java b/spring-all/src/test/java/org/baeldung/spring43/depresolution/ObjectProviderConfiguration.java new file mode 100644 index 0000000000..530c4d9f4a --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/depresolution/ObjectProviderConfiguration.java @@ -0,0 +1,9 @@ +package org.baeldung.spring43.depresolution; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan +public class ObjectProviderConfiguration { +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/depresolution/ObjectProviderTest.java b/spring-all/src/test/java/org/baeldung/spring43/depresolution/ObjectProviderTest.java new file mode 100644 index 0000000000..eeeb005f81 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/depresolution/ObjectProviderTest.java @@ -0,0 +1,23 @@ +package org.baeldung.spring43.depresolution; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; + +import static org.junit.Assert.assertNotNull; + +@ContextConfiguration(classes = ObjectProviderConfiguration.class) +public class ObjectProviderTest extends AbstractJUnit4SpringContextTests { + + @Autowired + private FooService fooService; + + @Test + public void whenArgumentIsObjectProvider_thenObjectProviderInjected() { + + assertNotNull(fooService.getRepository()); + + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/scopeannotations/ScopeAnnotationsConfiguration.java b/spring-all/src/test/java/org/baeldung/spring43/scopeannotations/ScopeAnnotationsConfiguration.java new file mode 100644 index 0000000000..24c1ec2f34 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/scopeannotations/ScopeAnnotationsConfiguration.java @@ -0,0 +1,23 @@ +package org.baeldung.spring43.scopeannotations; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +@Configuration +@ComponentScan +@EnableWebMvc +public class ScopeAnnotationsConfiguration { + + @Bean + public ViewResolver viewResolver() { + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/WEB-INF/jsp/view/"); + viewResolver.setSuffix(".jsp"); + return viewResolver; + } + +} diff --git a/spring-all/src/test/java/org/baeldung/spring43/scopeannotations/ScopeAnnotationsTest.java b/spring-all/src/test/java/org/baeldung/spring43/scopeannotations/ScopeAnnotationsTest.java new file mode 100644 index 0000000000..b696760f68 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/spring43/scopeannotations/ScopeAnnotationsTest.java @@ -0,0 +1,110 @@ +package org.baeldung.spring43.scopeannotations; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@ContextConfiguration(classes = ScopeAnnotationsConfiguration.class) +@WebAppConfiguration +public class ScopeAnnotationsTest extends AbstractJUnit4SpringContextTests { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(wac) + .build(); + } + + @Test + public void whenDifferentRequests_thenDifferentInstancesOfRequestScopedBeans() throws Exception { + MockHttpSession session = new MockHttpSession(); + + String requestScopedServiceInstanceNumber1 = this.mockMvc.perform(get("/appointments/request") + .session(session) + .accept(MediaType.ALL)).andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + String requestScopedServiceInstanceNumber2 = this.mockMvc.perform(get("/appointments/request") + .session(session) + .accept(MediaType.ALL)).andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertNotEquals(requestScopedServiceInstanceNumber1, requestScopedServiceInstanceNumber2); + } + + @Test + public void whenDifferentSessions_thenDifferentInstancesOfSessionScopedBeans() throws Exception { + + MockHttpSession session1 = new MockHttpSession(); + MockHttpSession session2 = new MockHttpSession(); + + String sessionScopedServiceInstanceNumber1 = this.mockMvc.perform(get("/appointments/session") + .session(session1) + .accept(MediaType.ALL)).andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + String sessionScopedServiceInstanceNumber2 = this.mockMvc.perform(get("/appointments/session") + .session(session1) + .accept(MediaType.ALL)).andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + String sessionScopedServiceInstanceNumber3 = this.mockMvc.perform(get("/appointments/session") + .session(session2) + .accept(MediaType.ALL)).andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertEquals(sessionScopedServiceInstanceNumber1, sessionScopedServiceInstanceNumber2); + + assertNotEquals(sessionScopedServiceInstanceNumber1, sessionScopedServiceInstanceNumber3); + + } + + @Test + public void whenDifferentSessionsAndRequests_thenAlwaysSingleApplicationScopedBean() throws Exception { + + MockHttpSession session1 = new MockHttpSession(); + MockHttpSession session2 = new MockHttpSession(); + + String applicationScopedServiceInstanceNumber1 = this.mockMvc.perform(get("/appointments/application") + .session(session1) + .accept(MediaType.ALL)).andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + String applicationScopedServiceInstanceNumber2 = this.mockMvc.perform(get("/appointments/application") + .session(session2) + .accept(MediaType.ALL)).andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + assertEquals(applicationScopedServiceInstanceNumber1, applicationScopedServiceInstanceNumber2); + + } + +} diff --git a/spring-all/src/test/java/org/baeldung/startup/SpringStartupTest.java b/spring-all/src/test/java/org/baeldung/startup/SpringStartupTest.java new file mode 100644 index 0000000000..523a27c2c4 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/startup/SpringStartupTest.java @@ -0,0 +1,44 @@ +package org.baeldung.startup; + +import org.assertj.core.api.Assertions; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { SpringStartupConfig.class }, loader = AnnotationConfigContextLoader.class) +public class SpringStartupTest { + + @Autowired + private ApplicationContext ctx; + + @Test(expected = BeanCreationException.class) + public void whenInstantiating_shouldThrowBCE() throws Exception { + ctx.getBean(InvalidInitExampleBean.class); + } + + @Test + public void whenPostConstruct_shouldLogEnv() throws Exception { + ctx.getBean(PostConstructExampleBean.class); + } + + @Test + public void whenConstructorInjection_shouldLogEnv() throws Exception { + ctx.getBean(LogicInConstructorExampleBean.class); + } + + @Test + public void whenInitializingBean_shouldLogEnv() throws Exception { + ctx.getBean(InitializingBeanExampleBean.class); + } + + @Test + public void whenApplicationListener_shouldRunOnce() throws Exception { + Assertions.assertThat(StartupApplicationListenerExample.counter).isEqualTo(1); + } +} \ No newline at end of file diff --git a/spring-all/src/test/java/org/baeldung/startup/SpringStartupXMLConfigTest.java b/spring-all/src/test/java/org/baeldung/startup/SpringStartupXMLConfigTest.java new file mode 100644 index 0000000000..19a35bb92b --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/startup/SpringStartupXMLConfigTest.java @@ -0,0 +1,26 @@ +package org.baeldung.startup; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:startupConfig.xml") +public class SpringStartupXMLConfigTest { + + @Autowired + private ApplicationContext ctx; + + @Test + public void whenPostConstruct_shouldLogEnv() throws Exception { + ctx.getBean(InitMethodExampleBean.class); + } + + @Test + public void whenAllStrategies_shouldLogOrder() throws Exception { + ctx.getBean(AllStrategiesExampleBean.class); + } +} diff --git a/spring-apache-camel/README.md b/spring-apache-camel/README.md new file mode 100644 index 0000000000..4015760f7d --- /dev/null +++ b/spring-apache-camel/README.md @@ -0,0 +1,33 @@ + +

    Configure and Use Apache Camel with Spring

    + +This article will demonstrate how to configure and use Apache Camel with Spring Framework. + +

    Relevant Articles

    + + + +

    Framework Versions:

    + +
      +
    • Spring 4.2.4
    • +
    • Apache Camel 2.16.1
    • +
    + +

    Build and Run Application

    + +To build this application execute following maven command in ApacheCamelFileProcessor directory. + +mvn clean install + +To run this application you can either run our main class App from your IDE or you can execute following maven command: + +mvn exec:java -Dexec.mainClass="App" + +

    Relevant Articles on Baeldung

    + diff --git a/spring-apache-camel/pom.xml b/spring-apache-camel/pom.xml new file mode 100644 index 0000000000..fbea9b779d --- /dev/null +++ b/spring-apache-camel/pom.xml @@ -0,0 +1,67 @@ + + 4.0.0 + org.apache.camel + spring-apache-camel + jar + 1.0-SNAPSHOT + spring-apache-camel + http://maven.apache.org + + + 2.16.1 + 4.2.4.RELEASE + 1.7 + 4.1 + + + + + + junit + junit + ${junit.version} + test + + + + org.apache.camel + camel-core + ${env.camel.version} + + + + org.apache.camel + camel-spring + ${env.camel.version} + + + + org.apache.camel + camel-stream + ${env.camel.version} + + + + org.springframework + spring-context + ${env.spring.version} + + + + + + + + maven-compiler-plugin + + true + true + ${java.version} + ${java.version} + ${java.version} + + + + + diff --git a/spring-apache-camel/src/main/java/com/baeldung/camel/main/App.java b/spring-apache-camel/src/main/java/com/baeldung/camel/main/App.java new file mode 100644 index 0000000000..ac0605a215 --- /dev/null +++ b/spring-apache-camel/src/main/java/com/baeldung/camel/main/App.java @@ -0,0 +1,12 @@ +package com.baeldung.camel.main; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class App { + public static void main(final String[] args) throws Exception { + ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("camel-context.xml"); + // Keep main thread alive for some time to let application finish processing the input files. + Thread.sleep(5000); + applicationContext.close(); + } +} \ No newline at end of file diff --git a/spring-apache-camel/src/main/java/com/baeldung/camel/processor/FileProcessor.java b/spring-apache-camel/src/main/java/com/baeldung/camel/processor/FileProcessor.java new file mode 100644 index 0000000000..971dd206cd --- /dev/null +++ b/spring-apache-camel/src/main/java/com/baeldung/camel/processor/FileProcessor.java @@ -0,0 +1,14 @@ +package com.baeldung.camel.processor; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; + +public class FileProcessor implements Processor { + + public void process(Exchange exchange) throws Exception { + String originalFileContent = exchange.getIn().getBody(String.class); + String upperCaseFileContent = originalFileContent.toUpperCase(); + exchange.getIn().setBody(upperCaseFileContent); + } + +} diff --git a/spring-apache-camel/src/main/resources/camel-context.xml b/spring-apache-camel/src/main/resources/camel-context.xml new file mode 100644 index 0000000000..0c10e0ecef --- /dev/null +++ b/spring-apache-camel/src/main/resources/camel-context.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + ${body.toLowerCase()} + + + + + + + + .......... File content conversion completed .......... + + + + + + + + + \ No newline at end of file diff --git a/spring-apache-camel/src/test/data/sampleInputFile/file.txt b/spring-apache-camel/src/test/data/sampleInputFile/file.txt new file mode 100644 index 0000000000..e057427864 --- /dev/null +++ b/spring-apache-camel/src/test/data/sampleInputFile/file.txt @@ -0,0 +1 @@ +This is data that will be processed by a Camel route! \ No newline at end of file diff --git a/spring-apache-camel/src/test/java/org/apache/camel/main/AppTest.java b/spring-apache-camel/src/test/java/org/apache/camel/main/AppTest.java new file mode 100644 index 0000000000..87b20369f3 --- /dev/null +++ b/spring-apache-camel/src/test/java/org/apache/camel/main/AppTest.java @@ -0,0 +1,117 @@ +package org.apache.camel.main; + +import com.baeldung.camel.main.App; +import junit.framework.TestCase; +import org.apache.camel.util.FileUtil; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class AppTest extends TestCase { + + private static final String FILE_NAME = "file.txt"; + private static final String SAMPLE_INPUT_DIR = "src/test/data/sampleInputFile/"; + private static final String TEST_INPUT_DIR = "src/test/data/input/"; + private static final String UPPERCASE_OUTPUT_DIR = "src/test/data/outputUpperCase/"; + private static final String LOWERCASE_OUTPUT_DIR = "src/test/data/outputLowerCase/"; + + @Before + public void setUp() throws Exception { + // Prepare input file for test + copySampleFileToInputDirectory(); + } + + @After + public void tearDown() throws Exception { + System.out.println("Deleting the test input and output files..."); + deleteFile(TEST_INPUT_DIR); + deleteFile(LOWERCASE_OUTPUT_DIR); + deleteFile(UPPERCASE_OUTPUT_DIR); + } + + @Test + public final void testMain() throws Exception { + App.main(null); + + String inputFileContent = readFileContent(SAMPLE_INPUT_DIR + FILE_NAME); + String outputUpperCase = readFileContent(UPPERCASE_OUTPUT_DIR + FILE_NAME); + String outputLowerCase = readFileContent(LOWERCASE_OUTPUT_DIR + FILE_NAME); + + System.out.println("Input File content = [" + inputFileContent + "]"); + System.out.println("UpperCaseOutput file content = [" + outputUpperCase + "]"); + System.out.println("LowerCaseOtput file content = [" + outputLowerCase + "]"); + + assertEquals(inputFileContent.toUpperCase(), outputUpperCase); + assertEquals(inputFileContent.toLowerCase(), outputLowerCase); + } + + private String readFileContent(String path) throws IOException { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded); + } + + private void deleteFile(String path) { + try { + FileUtil.removeDir(new File(path)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Copy sample input file to input directory. + */ + private void copySampleFileToInputDirectory() { + File sourceFile = new File(SAMPLE_INPUT_DIR + FILE_NAME); + File destFile = new File(TEST_INPUT_DIR + FILE_NAME); + + if (!sourceFile.exists()) { + System.out.println("Sample input file not found at location = [" + SAMPLE_INPUT_DIR + FILE_NAME + "]. Please provide this file."); + } + + if (!destFile.exists()) { + try { + System.out.println("Creating input file = [" + TEST_INPUT_DIR + FILE_NAME + "]"); + + File destDir = new File(TEST_INPUT_DIR); + if (!destDir.exists()) { + destDir.mkdir(); + } + destFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + FileChannel source = null; + FileChannel destination = null; + + try { + source = new FileInputStream(sourceFile).getChannel(); + destination = new FileOutputStream(destFile).getChannel(); + if (destination != null && source != null) { + destination.transferFrom(source, 0, source.size()); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + source.close(); + } catch (Exception e) { + e.printStackTrace(); + } + try { + destination.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/spring-autowire/pom.xml b/spring-autowire/pom.xml new file mode 100644 index 0000000000..e28efdae61 --- /dev/null +++ b/spring-autowire/pom.xml @@ -0,0 +1,63 @@ + + 4.0.0 + + com.baeldung + spring-autowire + 0.0.1-SNAPSHOT + jar + + spring-autowire + http://maven.apache.org + + + UTF-8 + 4.2.5.RELEASE + 3.5.1 + 2.19.1 + + + + + junit + junit + 4.11 + + + org.springframework + spring-core + ${org.springframework.version} + + + org.springframework + spring-context + ${org.springframework.version} + + + org.springframework + spring-test + ${org.springframework.version} + test + + + + + spring-autowire + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + diff --git a/spring-autowire/src/main/java/com/baeldung/autowire/sample/App.java b/spring-autowire/src/main/java/com/baeldung/autowire/sample/App.java new file mode 100644 index 0000000000..725a9b8406 --- /dev/null +++ b/spring-autowire/src/main/java/com/baeldung/autowire/sample/App.java @@ -0,0 +1,11 @@ +package com.baeldung.autowire.sample; + +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public class App { + public static void main(String[] args) { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); + FooService fooService = ctx.getBean(FooService.class); + fooService.doStuff(); + } +} diff --git a/spring-autowire/src/main/java/com/baeldung/autowire/sample/AppConfig.java b/spring-autowire/src/main/java/com/baeldung/autowire/sample/AppConfig.java new file mode 100644 index 0000000000..f948e2bf8e --- /dev/null +++ b/spring-autowire/src/main/java/com/baeldung/autowire/sample/AppConfig.java @@ -0,0 +1,10 @@ +package com.baeldung.autowire.sample; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("com.baeldung.autowire.sample") +public class AppConfig { + +} diff --git a/spring-autowire/src/main/java/com/baeldung/autowire/sample/Bar.java b/spring-autowire/src/main/java/com/baeldung/autowire/sample/Bar.java new file mode 100644 index 0000000000..7aa820adef --- /dev/null +++ b/spring-autowire/src/main/java/com/baeldung/autowire/sample/Bar.java @@ -0,0 +1,5 @@ +package com.baeldung.autowire.sample; + +public class Bar { + +} diff --git a/spring-autowire/src/main/java/com/baeldung/autowire/sample/BarFormatter.java b/spring-autowire/src/main/java/com/baeldung/autowire/sample/BarFormatter.java new file mode 100644 index 0000000000..fb704453fc --- /dev/null +++ b/spring-autowire/src/main/java/com/baeldung/autowire/sample/BarFormatter.java @@ -0,0 +1,13 @@ +package com.baeldung.autowire.sample; + +import org.springframework.stereotype.Component; + +@FormatterType("Bar") +@Component +public class BarFormatter implements Formatter { + + public String format() { + return "bar"; + } + +} diff --git a/spring-autowire/src/main/java/com/baeldung/autowire/sample/Foo.java b/spring-autowire/src/main/java/com/baeldung/autowire/sample/Foo.java new file mode 100644 index 0000000000..b587ab38b8 --- /dev/null +++ b/spring-autowire/src/main/java/com/baeldung/autowire/sample/Foo.java @@ -0,0 +1,5 @@ +package com.baeldung.autowire.sample; + +public class Foo { + +} diff --git a/spring-autowire/src/main/java/com/baeldung/autowire/sample/FooDAO.java b/spring-autowire/src/main/java/com/baeldung/autowire/sample/FooDAO.java new file mode 100644 index 0000000000..aec26202ab --- /dev/null +++ b/spring-autowire/src/main/java/com/baeldung/autowire/sample/FooDAO.java @@ -0,0 +1,5 @@ +package com.baeldung.autowire.sample; + +public class FooDAO { + +} diff --git a/spring-autowire/src/main/java/com/baeldung/autowire/sample/FooFormatter.java b/spring-autowire/src/main/java/com/baeldung/autowire/sample/FooFormatter.java new file mode 100644 index 0000000000..73966e9e43 --- /dev/null +++ b/spring-autowire/src/main/java/com/baeldung/autowire/sample/FooFormatter.java @@ -0,0 +1,13 @@ +package com.baeldung.autowire.sample; + +import org.springframework.stereotype.Component; + +@FormatterType("Foo") +@Component +public class FooFormatter implements Formatter { + + public String format() { + return "foo"; + } + +} diff --git a/spring-autowire/src/main/java/com/baeldung/autowire/sample/FooService.java b/spring-autowire/src/main/java/com/baeldung/autowire/sample/FooService.java new file mode 100644 index 0000000000..eccea4351a --- /dev/null +++ b/spring-autowire/src/main/java/com/baeldung/autowire/sample/FooService.java @@ -0,0 +1,17 @@ +package com.baeldung.autowire.sample; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class FooService { + + @Autowired + @FormatterType("Foo") + private Formatter formatter; + + public String doStuff(){ + return formatter.format(); + } + +} diff --git a/spring-autowire/src/main/java/com/baeldung/autowire/sample/Formatter.java b/spring-autowire/src/main/java/com/baeldung/autowire/sample/Formatter.java new file mode 100644 index 0000000000..83716d6e92 --- /dev/null +++ b/spring-autowire/src/main/java/com/baeldung/autowire/sample/Formatter.java @@ -0,0 +1,7 @@ +package com.baeldung.autowire.sample; + +public interface Formatter { + + String format(); + +} diff --git a/spring-autowire/src/main/java/com/baeldung/autowire/sample/FormatterType.java b/spring-autowire/src/main/java/com/baeldung/autowire/sample/FormatterType.java new file mode 100644 index 0000000000..7ffc308c9a --- /dev/null +++ b/spring-autowire/src/main/java/com/baeldung/autowire/sample/FormatterType.java @@ -0,0 +1,17 @@ +package com.baeldung.autowire.sample; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.beans.factory.annotation.Qualifier; + +@Qualifier +@Target({ElementType.FIELD, ElementType.METHOD,ElementType.TYPE, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface FormatterType { + + String value(); + +} diff --git a/spring-autowire/src/test/java/com/baeldung/autowire/sample/FooServiceTest.java b/spring-autowire/src/test/java/com/baeldung/autowire/sample/FooServiceTest.java new file mode 100644 index 0000000000..4607f527d9 --- /dev/null +++ b/spring-autowire/src/test/java/com/baeldung/autowire/sample/FooServiceTest.java @@ -0,0 +1,22 @@ +package com.baeldung.autowire.sample; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes=AppConfig.class, loader=AnnotationConfigContextLoader.class) +public class FooServiceTest { + + @Autowired + FooService fooService; + + @Test + public void whenFooFormatterType_thenReturnFoo(){ + Assert.assertEquals("foo", fooService.doStuff()); + } +} diff --git a/spring-batch/.classpath b/spring-batch/.classpath deleted file mode 100644 index e7ac9faf11..0000000000 --- a/spring-batch/.classpath +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-batch/.project b/spring-batch/.project deleted file mode 100644 index 0159a7237c..0000000000 --- a/spring-batch/.project +++ /dev/null @@ -1,29 +0,0 @@ - - - spring-batch - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - diff --git a/spring-batch/README.md b/spring-batch/README.md new file mode 100644 index 0000000000..953e652cea --- /dev/null +++ b/spring-batch/README.md @@ -0,0 +1,7 @@ +========= + +## Spring Batch + + +### Relevant Articles: +- [Introduction to Spring Batch](http://www.baeldung.com/introduction-to-spring-batch) diff --git a/spring-batch/pom.xml b/spring-batch/pom.xml index c85aeff6f3..5538dd912f 100644 --- a/spring-batch/pom.xml +++ b/spring-batch/pom.xml @@ -1,7 +1,7 @@ 4.0.0 - org.baeldung + com.baeldung spring-batch 0.1-SNAPSHOT jar diff --git a/spring-boot/.classpath b/spring-boot/.classpath deleted file mode 100644 index 26981b6dd7..0000000000 --- a/spring-boot/.classpath +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-boot/.gitignore b/spring-boot/.gitignore index 24d64373c4..e26d6af438 100644 --- a/spring-boot/.gitignore +++ b/spring-boot/.gitignore @@ -1 +1,4 @@ /target/ +.settings/ +.classpath +.project diff --git a/spring-boot/.project b/spring-boot/.project deleted file mode 100644 index e748dc5713..0000000000 --- a/spring-boot/.project +++ /dev/null @@ -1,48 +0,0 @@ - - - spring-boot - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-boot/README.MD b/spring-boot/README.MD new file mode 100644 index 0000000000..2a87b46021 --- /dev/null +++ b/spring-boot/README.MD @@ -0,0 +1,2 @@ +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml index 3a116a2974..5a20ff5602 100644 --- a/spring-boot/pom.xml +++ b/spring-boot/pom.xml @@ -1,73 +1,177 @@ - - 4.0.0 - org.baeldung - spring-boot - 0.0.1-SNAPSHOT - war - Spring Boot Actuator - This is simple boot application for Spring boot actuator test + + 4.0.0 + com.baeldung + spring-boot + 0.0.1-SNAPSHOT + war + Spring Boot Actuator + This is simple boot application for Spring boot actuator test - - - org.springframework.boot - spring-boot-starter-parent - 1.2.6.RELEASE - + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RC1 + + - - - org.springframework.boot - spring-boot-starter-web - + + + org.baeldung.boot.DemoApplication + UTF-8 + 1.8 + 4.3.1.RELEASE + - - org.springframework.boot - spring-boot-starter-actuator - + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + - - org.springframework.boot - spring-boot-starter-security - + + org.springframework.boot + spring-boot-starter-data-jpa + - - io.dropwizard.metrics - metrics-core - - + + org.springframework.boot + spring-boot-starter-actuator + - - spring-boot - - - src/main/resources - true - - + + org.springframework.boot + spring-boot-starter-security + - + + io.dropwizard.metrics + metrics-core + + + + com.h2database + h2 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter + + + com.jayway.jsonpath + json-path + test + + + org.springframework.boot + spring-boot-starter-mail + + + org.subethamail + subethasmtp + 3.1.7 + test + + + + org.webjars + bootstrap + 3.3.4 + + + org.webjars + jquery + 2.1.4 + + + + + spring-boot + + + src/main/resources + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + - org.springframework.boot - spring-boot-maven-plugin - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.8 - 1.8 - - - - - org.apache.maven.plugins - maven-war-plugin + pl.project13.maven + git-commit-id-plugin + 2.2.1 - +
    -
    \ No newline at end of file + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + diff --git a/spring-boot/src/main/java/com/baeldung/TestController.java b/spring-boot/src/main/java/com/baeldung/TestController.java new file mode 100644 index 0000000000..19a1c18c6b --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/TestController.java @@ -0,0 +1,15 @@ +package com.baeldung; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class TestController { + + @RequestMapping(value="/") + public String welcome(Model model){ + return "index"; + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/WebjarsdemoApplication.java b/spring-boot/src/main/java/com/baeldung/WebjarsdemoApplication.java new file mode 100644 index 0000000000..c14dc682af --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/WebjarsdemoApplication.java @@ -0,0 +1,12 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class WebjarsdemoApplication { + + public static void main(String[] args) { + SpringApplication.run(WebjarsdemoApplication.class, args); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/git/CommitIdApplication.java b/spring-boot/src/main/java/com/baeldung/git/CommitIdApplication.java new file mode 100644 index 0000000000..95abbf894c --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/git/CommitIdApplication.java @@ -0,0 +1,26 @@ +package com.baeldung.git; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.io.ClassPathResource; + +@SpringBootApplication(scanBasePackages = { "com.baeldung.git"}) +public class CommitIdApplication { + public static void main(String[] args) { + SpringApplication.run(CommitIdApplication.class, args); + } + + @Bean + public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() { + PropertySourcesPlaceholderConfigurer c = new PropertySourcesPlaceholderConfigurer(); + c.setLocation(new ClassPathResource("git.properties")); + c.setIgnoreResourceNotFound(true); + c.setIgnoreUnresolvablePlaceholders(true); + return c; + } +} + + + diff --git a/spring-boot/src/main/java/com/baeldung/git/CommitInfoController.java b/spring-boot/src/main/java/com/baeldung/git/CommitInfoController.java new file mode 100644 index 0000000000..1da2bd2989 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/git/CommitInfoController.java @@ -0,0 +1,30 @@ +package com.baeldung.git; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +@RestController +public class CommitInfoController { + + @Value("${git.commit.message.short}") + private String commitMessage; + + @Value("${git.branch}") + private String branch; + + @Value("${git.commit.id}") + private String commitId; + + @RequestMapping("/commitId") + public Map getCommitId() { + Map result = new HashMap<>(); + result.put("Commit message",commitMessage); + result.put("Commit branch", branch); + result.put("Commit id", commitId); + return result; + } +} diff --git a/spring-boot/src/main/java/org/baeldung/Application.java b/spring-boot/src/main/java/org/baeldung/Application.java new file mode 100644 index 0000000000..aae0c427a9 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/Application.java @@ -0,0 +1,13 @@ +package org.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.context.ApplicationContext; + +@org.springframework.boot.autoconfigure.SpringBootApplication +public class Application { + private static ApplicationContext applicationContext; + + public static void main(String[] args) { + applicationContext = SpringApplication.run(Application.class, args); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/DemoApplication.java b/spring-boot/src/main/java/org/baeldung/boot/DemoApplication.java new file mode 100644 index 0000000000..e61d140396 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/DemoApplication.java @@ -0,0 +1,14 @@ +package org.baeldung.boot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoApplication { + + public static void main(String[] args) { + System.setProperty("spring.config.name", "demo"); + SpringApplication.run(DemoApplication.class, args); + } + +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/model/Foo.java b/spring-boot/src/main/java/org/baeldung/boot/model/Foo.java new file mode 100644 index 0000000000..6a36459e3c --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/model/Foo.java @@ -0,0 +1,39 @@ +package org.baeldung.boot.model; + +import java.io.Serializable; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Foo implements Serializable { + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue + private Integer id; + private String name; + + public Foo() { + } + + public Foo(String name) { + this.name = name; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/repository/FooRepository.java b/spring-boot/src/main/java/org/baeldung/boot/repository/FooRepository.java new file mode 100644 index 0000000000..09d6975dba --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/repository/FooRepository.java @@ -0,0 +1,8 @@ +package org.baeldung.boot.repository; + +import org.baeldung.boot.model.Foo; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FooRepository extends JpaRepository { + public Foo findByName(String name); +} diff --git a/spring-boot/src/main/java/org/baeldung/client/Details.java b/spring-boot/src/main/java/org/baeldung/client/Details.java new file mode 100644 index 0000000000..2ae3adc38f --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/client/Details.java @@ -0,0 +1,32 @@ +package org.baeldung.client; + +public class Details { + + private String name; + + private String login; + + public Details() { + } + + public Details(String name, String login) { + this.name = name; + this.login = login; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } +} diff --git a/spring-boot/src/main/java/org/baeldung/client/DetailsServiceClient.java b/spring-boot/src/main/java/org/baeldung/client/DetailsServiceClient.java new file mode 100644 index 0000000000..51fa7c6181 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/client/DetailsServiceClient.java @@ -0,0 +1,20 @@ +package org.baeldung.client; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +public class DetailsServiceClient { + + private final RestTemplate restTemplate; + + public DetailsServiceClient(RestTemplateBuilder restTemplateBuilder) { + restTemplate = restTemplateBuilder.build(); + } + + public Details getUserDetails(String name) { + return restTemplate.getForObject("/{name}/details", Details.class, name); + } + +} \ No newline at end of file diff --git a/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java b/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java new file mode 100644 index 0000000000..b6f88e7cd5 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java @@ -0,0 +1,38 @@ +package org.baeldung.controller; + +import org.baeldung.domain.GenericEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; + +@RestController +public class GenericEntityController { + private List entityList = new ArrayList<>(); + + { + entityList.add(new GenericEntity(1l, "entity_1")); + entityList.add(new GenericEntity(2l, "entity_2")); + entityList.add(new GenericEntity(3l, "entity_3")); + entityList.add(new GenericEntity(4l, "entity_4")); + } + + @RequestMapping("/entity/all") + public List findAll() { + return entityList; + } + + @RequestMapping(value = "/entity", method = RequestMethod.POST) + public GenericEntity addEntity(GenericEntity entity) { + entityList.add(entity); + return entity; + } + + @RequestMapping("/entity/findby/{id}") + public GenericEntity findById(@PathVariable Long id) { + return entityList.stream().filter(entity -> entity.getId().equals(id)).findFirst().get(); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/domain/GenericEntity.java b/spring-boot/src/main/java/org/baeldung/domain/GenericEntity.java new file mode 100644 index 0000000000..7b1d27cb66 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/domain/GenericEntity.java @@ -0,0 +1,42 @@ +package org.baeldung.domain; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class GenericEntity { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + private String value; + + public GenericEntity() { + } + + public GenericEntity(String value) { + this.value = value; + } + + public GenericEntity(Long id, String value) { + this.id = id; + this.value = value; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/spring-boot/src/main/java/org/baeldung/main/SpringBootApplication.java b/spring-boot/src/main/java/org/baeldung/main/SpringBootApplication.java index 59955cc990..582d2d9e9c 100644 --- a/spring-boot/src/main/java/org/baeldung/main/SpringBootApplication.java +++ b/spring-boot/src/main/java/org/baeldung/main/SpringBootApplication.java @@ -1,8 +1,5 @@ package org.baeldung.main; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - import org.baeldung.common.error.SpringHelloServletRegistrationBean; import org.baeldung.common.resources.ExecutorServiceExitCodeGenerator; import org.baeldung.controller.servlet.HelloWorldServlet; @@ -17,6 +14,9 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + @RestController @EnableAutoConfiguration @ComponentScan({ "org.baeldung.common.error", "org.baeldung.common.error.controller", "org.baeldung.common.properties", "org.baeldung.common.resources", "org.baeldung.endpoints", "org.baeldung.service", "org.baeldung.monitor.jmx", "org.baeldung.service" }) @@ -55,28 +55,6 @@ public class SpringBootApplication { return bean; } - /* @Bean - public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() { - JettyEmbeddedServletContainerFactory jettyContainer = new JettyEmbeddedServletContainerFactory(); - jettyContainer.setPort(9000); - jettyContainer.setContextPath("/springbootapp"); - return jettyContainer; - } - - @Bean - public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() { - UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory(); - factory.addBuilderCustomizers(new UndertowBuilderCustomizer() { - - @Override - public void customize(io.undertow.Undertow.Builde builder) { - builder.addHttpListener(8080, "0.0.0.0"); - } - - }); - return factory; - }*/ - @Bean @Autowired public ExecutorServiceExitCodeGenerator executorServiceExitCodeGenerator(ExecutorService executorService) { diff --git a/spring-boot/src/main/java/org/baeldung/repository/GenericEntityRepository.java b/spring-boot/src/main/java/org/baeldung/repository/GenericEntityRepository.java new file mode 100644 index 0000000000..7bb1e6dcdc --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/repository/GenericEntityRepository.java @@ -0,0 +1,7 @@ +package org.baeldung.repository; + +import org.baeldung.domain.GenericEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface GenericEntityRepository extends JpaRepository { +} diff --git a/spring-boot/src/main/java/org/baeldung/session/exception/Application.java b/spring-boot/src/main/java/org/baeldung/session/exception/Application.java new file mode 100644 index 0000000000..23d741b98c --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/session/exception/Application.java @@ -0,0 +1,23 @@ +package org.baeldung.session.exception; + +import org.baeldung.boot.model.Foo; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Bean; +import org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean; + +@EntityScan(basePackageClasses = Foo.class) +@SpringBootApplication +public class Application { + public static void main(String[] args) { + System.setProperty("spring.config.name", "exception"); + System.setProperty("spring.profiles.active", "exception"); + SpringApplication.run(Application.class, args); + } + + @Bean + public HibernateJpaSessionFactoryBean sessionFactory() { + return new HibernateJpaSessionFactoryBean(); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/session/exception/repository/FooRepository.java b/spring-boot/src/main/java/org/baeldung/session/exception/repository/FooRepository.java new file mode 100644 index 0000000000..679d691b26 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/session/exception/repository/FooRepository.java @@ -0,0 +1,10 @@ +package org.baeldung.session.exception.repository; + +import org.baeldung.boot.model.Foo; + +public interface FooRepository { + + void save(Foo foo); + + Foo get(Integer id); +} diff --git a/spring-boot/src/main/java/org/baeldung/session/exception/repository/FooRepositoryImpl.java b/spring-boot/src/main/java/org/baeldung/session/exception/repository/FooRepositoryImpl.java new file mode 100644 index 0000000000..83de888e5e --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/session/exception/repository/FooRepositoryImpl.java @@ -0,0 +1,25 @@ +package org.baeldung.session.exception.repository; + +import org.baeldung.boot.model.Foo; +import org.hibernate.SessionFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +@Profile("exception") +@Repository +public class FooRepositoryImpl implements FooRepository { + @Autowired + private SessionFactory sessionFactory; + + @Override + public void save(Foo foo) { + sessionFactory.getCurrentSession().saveOrUpdate(foo); + } + + @Override + public Foo get(Integer id) { + return sessionFactory.getCurrentSession().get(Foo.class, id); + } + +} \ No newline at end of file diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index 8ee0ed29bc..d30045d1dc 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -1,4 +1,4 @@ -server.port=8083 +server.port=8080 server.contextPath=/springbootapp management.port=8081 management.address=127.0.0.1 @@ -26,4 +26,6 @@ info.app.version=1.0.0 ## Spring Security Configurations security.user.name=admin1 security.user.password=secret1 -management.security.role=SUPERUSER \ No newline at end of file +management.security.role=SUPERUSER + +logging.level.org.springframework=INFO \ No newline at end of file diff --git a/spring-boot/src/main/resources/demo.properties b/spring-boot/src/main/resources/demo.properties new file mode 100644 index 0000000000..649b64f59b --- /dev/null +++ b/spring-boot/src/main/resources/demo.properties @@ -0,0 +1,6 @@ +spring.output.ansi.enabled=never +server.port=7070 + +# Security +security.user.name=admin +security.user.password=password \ No newline at end of file diff --git a/spring-boot/src/main/resources/logback.xml b/spring-boot/src/main/resources/logback.xml new file mode 100644 index 0000000000..78913ee76f --- /dev/null +++ b/spring-boot/src/main/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + \ No newline at end of file diff --git a/spring-boot/src/main/resources/templates/index.html b/spring-boot/src/main/resources/templates/index.html new file mode 100644 index 0000000000..046d21600a --- /dev/null +++ b/spring-boot/src/main/resources/templates/index.html @@ -0,0 +1,19 @@ + + + WebJars Demo + + + + +

    +
    + × + Success! It is working as we expected. +
    +
    + + + + + + \ No newline at end of file diff --git a/spring-boot/src/test/java/com/baeldung/WebjarsdemoApplicationTests.java b/spring-boot/src/test/java/com/baeldung/WebjarsdemoApplicationTests.java new file mode 100644 index 0000000000..284cda5d31 --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/WebjarsdemoApplicationTests.java @@ -0,0 +1,18 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = WebjarsdemoApplication.class) +@WebAppConfiguration +public class WebjarsdemoApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/spring-boot/src/test/java/com/baeldung/git/CommitIdTest.java b/spring-boot/src/test/java/com/baeldung/git/CommitIdTest.java new file mode 100644 index 0000000000..e16791881e --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/git/CommitIdTest.java @@ -0,0 +1,44 @@ +package com.baeldung.git; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = CommitIdApplication.class) +public class CommitIdTest { + + private static final Logger LOG = LoggerFactory.getLogger(CommitIdTest.class); + + @Value("${git.commit.message.short:UNKNOWN}") + private String commitMessage; + + @Value("${git.branch:UNKNOWN}") + private String branch; + + @Value("${git.commit.id:UNKNOWN}") + private String commitId; + + @Test + public void whenInjecting_shouldDisplay() throws Exception { + + LOG.info(commitId); + LOG.info(commitMessage); + LOG.info(branch); + + assertThat(commitMessage) + .isNotEqualTo("UNKNOWN"); + + assertThat(branch) + .isNotEqualTo("UNKNOWN"); + + assertThat(commitId) + .isNotEqualTo("UNKNOWN"); + } +} \ No newline at end of file diff --git a/spring-boot/src/test/java/org/baeldung/SpringBootApplicationTest.java b/spring-boot/src/test/java/org/baeldung/SpringBootApplicationTest.java new file mode 100644 index 0000000000..ac7bcd62a9 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/SpringBootApplicationTest.java @@ -0,0 +1,52 @@ +package org.baeldung; + +import org.baeldung.domain.GenericEntity; +import org.baeldung.repository.GenericEntityRepository; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import java.nio.charset.Charset; + +import static org.hamcrest.Matchers.hasSize; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +public class SpringBootApplicationTest { + @Autowired + private WebApplicationContext webApplicationContext; + private MockMvc mockMvc; + + + @Before + public void setupMockMvc() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) + .build(); + } + + @Test + public void givenRequestHasBeenMade_whenMeetsAllOfGivenConditions_thenCorrect() throws Exception { + MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), + MediaType.APPLICATION_JSON.getSubtype(), + Charset.forName("utf8")); + + mockMvc.perform(MockMvcRequestBuilders.get("/entity/all")). + andExpect(MockMvcResultMatchers.status().isOk()). + andExpect(MockMvcResultMatchers.content().contentType(contentType)). + andExpect(jsonPath("$", hasSize(4))); + } +} diff --git a/spring-boot/src/test/java/org/baeldung/SpringBootJPATest.java b/spring-boot/src/test/java/org/baeldung/SpringBootJPATest.java new file mode 100644 index 0000000000..8a6b5139fe --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/SpringBootJPATest.java @@ -0,0 +1,27 @@ +package org.baeldung; + +import org.baeldung.domain.GenericEntity; +import org.baeldung.repository.GenericEntityRepository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +public class SpringBootJPATest { + @Autowired + private GenericEntityRepository genericEntityRepository; + + @Test + public void givenGenericEntityRepository_whenSaveAndRetreiveEntity_thenOK() { + GenericEntity genericEntity = genericEntityRepository.save(new GenericEntity("test")); + GenericEntity foundedEntity = genericEntityRepository.findOne(genericEntity.getId()); + assertNotNull(foundedEntity); + assertEquals(genericEntity.getValue(), foundedEntity.getValue()); + } +} diff --git a/spring-boot/src/test/java/org/baeldung/SpringBootMailTest.java b/spring-boot/src/test/java/org/baeldung/SpringBootMailTest.java new file mode 100644 index 0000000000..d36a7906a3 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/SpringBootMailTest.java @@ -0,0 +1,82 @@ +package org.baeldung; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.web.context.WebApplicationContext; +import org.subethamail.wiser.Wiser; +import org.subethamail.wiser.WiserMessage; + +import javax.mail.MessagingException; +import java.io.IOException; +import java.util.List; + +import static org.hamcrest.Matchers.hasSize; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +public class SpringBootMailTest { + @Autowired + private JavaMailSender javaMailSender; + + private Wiser wiser; + + private String userTo = "user2@localhost"; + private String userFrom = "user1@localhost"; + private String subject = "Test subject"; + private String textMail = "Text subject mail"; + + @Before + public void setUp() throws Exception { + final int TEST_PORT = 8025; + wiser = new Wiser(TEST_PORT); + wiser.start(); + } + + @After + public void tearDown() throws Exception { + wiser.stop(); + } + + @Test + public void givenMail_whenSendAndReceived_thenCorrect() throws Exception { + SimpleMailMessage message = composeEmailMessage(); + javaMailSender.send(message); + List messages = wiser.getMessages(); + + assertThat(messages, hasSize(1)); + WiserMessage wiserMessage = messages.get(0); + assertEquals(userFrom, wiserMessage.getEnvelopeSender()); + assertEquals(userTo, wiserMessage.getEnvelopeReceiver()); + assertEquals(subject, getSubject(wiserMessage)); + assertEquals(textMail, getMessage(wiserMessage)); + } + + private String getMessage(WiserMessage wiserMessage) throws MessagingException, IOException { + return wiserMessage.getMimeMessage().getContent().toString().trim(); + } + + private String getSubject(WiserMessage wiserMessage) throws MessagingException { + return wiserMessage.getMimeMessage().getSubject(); + } + + + private SimpleMailMessage composeEmailMessage() { + SimpleMailMessage mailMessage = new SimpleMailMessage(); + mailMessage.setTo(userTo); + mailMessage.setReplyTo(userFrom); + mailMessage.setFrom(userFrom); + mailMessage.setSubject(subject); + mailMessage.setText(textMail); + return mailMessage; + } +} diff --git a/spring-boot/src/test/java/org/baeldung/boot/ApplicationTests.java b/spring-boot/src/test/java/org/baeldung/boot/ApplicationTests.java new file mode 100644 index 0000000000..7911465048 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/ApplicationTests.java @@ -0,0 +1,17 @@ +package org.baeldung.boot; + +import org.baeldung.session.exception.Application; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = Application.class) +@TestPropertySource("classpath:exception.properties") +public class ApplicationTests { + @Test + public void contextLoads() { + } +} diff --git a/spring-boot/src/test/java/org/baeldung/boot/DemoApplicationTests.java b/spring-boot/src/test/java/org/baeldung/boot/DemoApplicationTests.java new file mode 100644 index 0000000000..7f9b2ba912 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/DemoApplicationTests.java @@ -0,0 +1,17 @@ +package org.baeldung.boot; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = DemoApplication.class) +@WebAppConfiguration +public class DemoApplicationTests { + + @Test + public void contextLoads() { + } +} diff --git a/spring-boot/src/test/java/org/baeldung/boot/repository/FooRepositoryTest.java b/spring-boot/src/test/java/org/baeldung/boot/repository/FooRepositoryTest.java new file mode 100644 index 0000000000..9de7790a75 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/repository/FooRepositoryTest.java @@ -0,0 +1,34 @@ +package org.baeldung.boot.repository; + +import static org.junit.Assert.assertThat; + +import org.baeldung.boot.DemoApplicationTests; +import org.baeldung.boot.model.Foo; + +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.is; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +public class FooRepositoryTest extends DemoApplicationTests { + @Autowired + private FooRepository fooRepository; + + @Before + public void setUp() { + fooRepository.save(new Foo("Foo")); + fooRepository.save(new Foo("Bar")); + } + + @Test + public void testFindByName() { + Foo foo = fooRepository.findByName("Bar"); + assertThat(foo, notNullValue()); + assertThat(foo.getId(), is(2)); + } + +} diff --git a/spring-boot/src/test/java/org/baeldung/boot/repository/HibernateSessionTest.java b/spring-boot/src/test/java/org/baeldung/boot/repository/HibernateSessionTest.java new file mode 100644 index 0000000000..4cb1b60cde --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/repository/HibernateSessionTest.java @@ -0,0 +1,32 @@ +package org.baeldung.boot.repository; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; + +import org.baeldung.boot.ApplicationTests; +import org.baeldung.boot.model.Foo; +import org.baeldung.session.exception.repository.FooRepository; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.TestPropertySource; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +@TestPropertySource("classpath:exception-hibernate.properties") +public class HibernateSessionTest extends ApplicationTests { + @Autowired + private FooRepository fooRepository; + + @Test + public void whenSavingWithCurrentSession_thenThrowNoException() { + Foo foo = new Foo("Exception Solved"); + fooRepository.save(foo); + foo = null; + foo = fooRepository.get(1); + + assertThat(foo, notNullValue()); + assertThat(foo.getId(), is(1)); + assertThat(foo.getName(), is("Exception Solved")); + } +} diff --git a/spring-boot/src/test/java/org/baeldung/boot/repository/NoHibernateSessionTest.java b/spring-boot/src/test/java/org/baeldung/boot/repository/NoHibernateSessionTest.java new file mode 100644 index 0000000000..5f5a49841a --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/repository/NoHibernateSessionTest.java @@ -0,0 +1,21 @@ +package org.baeldung.boot.repository; + +import org.baeldung.boot.ApplicationTests; +import org.baeldung.boot.model.Foo; +import org.baeldung.session.exception.repository.FooRepository; +import org.hibernate.HibernateException; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +public class NoHibernateSessionTest extends ApplicationTests { + @Autowired + private FooRepository fooRepository; + + @Test(expected = HibernateException.class) + public void whenSavingWithoutCurrentSession_thenThrowException() { + Foo foo = new Foo("Exception Thrown"); + fooRepository.save(foo); + } +} diff --git a/spring-boot/src/test/java/org/baeldung/client/DetailsServiceClientTest.java b/spring-boot/src/test/java/org/baeldung/client/DetailsServiceClientTest.java new file mode 100644 index 0000000000..c594610be2 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/client/DetailsServiceClientTest.java @@ -0,0 +1,47 @@ +package org.baeldung.client; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.client.RestClientTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.client.MockRestServiceServer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; + +@RunWith(SpringRunner.class) +@RestClientTest(DetailsServiceClient.class) +public class DetailsServiceClientTest { + + @Autowired + private DetailsServiceClient client; + + @Autowired + private MockRestServiceServer server; + + @Autowired + private ObjectMapper objectMapper; + + @Before + public void setUp() throws Exception { + String detailsString = objectMapper.writeValueAsString(new Details("John Smith", "john")); + this.server.expect(requestTo("/john/details")) + .andRespond(withSuccess(detailsString, MediaType.APPLICATION_JSON)); + } + + @Test + public void whenCallingGetUserDetails_thenClientExecutesCorrectCall() throws Exception { + + Details details = this.client.getUserDetails("john"); + + assertThat(details.getLogin()).isEqualTo("john"); + assertThat(details.getName()).isEqualTo("John Smith"); + + } + +} diff --git a/spring-boot/src/test/resources/application.properties b/spring-boot/src/test/resources/application.properties new file mode 100644 index 0000000000..14b190629e --- /dev/null +++ b/spring-boot/src/test/resources/application.properties @@ -0,0 +1,3 @@ +spring.mail.host=localhost +spring.mail.port=8025 +spring.mail.properties.mail.smtp.auth=false \ No newline at end of file diff --git a/spring-boot/src/test/resources/exception-hibernate.properties b/spring-boot/src/test/resources/exception-hibernate.properties new file mode 100644 index 0000000000..cde746acb9 --- /dev/null +++ b/spring-boot/src/test/resources/exception-hibernate.properties @@ -0,0 +1,2 @@ +spring.profiles.active=exception +spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext diff --git a/spring-boot/src/test/resources/exception.properties b/spring-boot/src/test/resources/exception.properties new file mode 100644 index 0000000000..c55e415a3a --- /dev/null +++ b/spring-boot/src/test/resources/exception.properties @@ -0,0 +1,6 @@ +# Security +security.user.name=admin +security.user.password=password + +spring.dao.exceptiontranslation.enabled=false +spring.profiles.active=exception \ No newline at end of file diff --git a/spring-cloud-config/README.md b/spring-cloud-config/README.md new file mode 100644 index 0000000000..b8ebb2bfe9 --- /dev/null +++ b/spring-cloud-config/README.md @@ -0,0 +1,27 @@ +## Spring Cloud Config ## + +To get this example working, you have to initialize a new *Git* repository in +the ```client-config``` directory first *and* you have to set the environment variable +```CONFIG_REPO``` to an absolute path of that directory. + +``` +$> cd client-config +$> git init +$> git add . +$> git commit -m 'Initial commit' +$> export CONFIG_REPO=$(pwd) +``` + +Then you're able to run the examples with ```mvn install spring-boot:run```. + +### Docker ### + +To get the *Docker* examples working, you have to repackage the ```spring-cloud-config-server``` +and ```spring-cloud-config-client``` modules first: + +``` +$> mvn install spring-boot:repackage +``` + +Don't forget to download the *Java JCE* package from +(Oracle)[http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html]. diff --git a/spring-cloud-config/docker/Dockerfile.client b/spring-cloud-config/docker/Dockerfile.client new file mode 100644 index 0000000000..0f9293bd22 --- /dev/null +++ b/spring-cloud-config/docker/Dockerfile.client @@ -0,0 +1,6 @@ +FROM alpine-java:base +MAINTAINER baeldung.com +RUN apk --no-cache add netcat-openbsd +COPY files/spring-cloud-config-client-1.0.0-SNAPSHOT.jar /opt/spring-cloud/lib/config-client.jar +COPY files/config-client-entrypoint.sh /opt/spring-cloud/bin/ +RUN chmod 755 /opt/spring-cloud/bin/config-client-entrypoint.sh diff --git a/spring-cloud-config/docker/Dockerfile.server b/spring-cloud-config/docker/Dockerfile.server new file mode 100644 index 0000000000..90d7e2a7cf --- /dev/null +++ b/spring-cloud-config/docker/Dockerfile.server @@ -0,0 +1,9 @@ +FROM alpine-java:base +MAINTAINER baeldung.com +COPY files/spring-cloud-config-server-1.0.0-SNAPSHOT.jar /opt/spring-cloud/lib/config-server.jar +ENV SPRING_APPLICATION_JSON='{"spring": {"cloud": {"config": {"server": \ + {"git": {"uri": "/var/lib/spring-cloud/config-repo", "clone-on-start": true}}}}}}' +ENTRYPOINT ["/usr/bin/java"] +CMD ["-jar", "/opt/spring-cloud/lib/config-server.jar"] +VOLUME /var/lib/spring-cloud/config-repo +EXPOSE 8888 diff --git a/spring-cloud-config/docker/files/.gitignore b/spring-cloud-config/docker/files/.gitignore new file mode 100644 index 0000000000..28ffcbffdb --- /dev/null +++ b/spring-cloud-config/docker/files/.gitignore @@ -0,0 +1,2 @@ +/UnlimitedJCEPolicyJDK8 +/*.jar diff --git a/spring-cloud-config/docker/files/config-client-entrypoint.sh b/spring-cloud-config/docker/files/config-client-entrypoint.sh new file mode 100644 index 0000000000..12352119fa --- /dev/null +++ b/spring-cloud-config/docker/files/config-client-entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +while ! nc -z config-server 8888 ; do + echo "Waiting for upcoming Config Server" + sleep 2 +done + +java -jar /opt/spring-cloud/lib/config-client.jar diff --git a/spring-cloud-config/pom.xml b/spring-cloud-config/pom.xml new file mode 100644 index 0000000000..3b1b59b037 --- /dev/null +++ b/spring-cloud-config/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + spring-cloud-config + pom + + + spring-cloud-config-server + spring-cloud-config-client + + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + + + org.springframework.boot + spring-boot-parent + 1.4.0.RELEASE + pom + import + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.SR4 + pom + import + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 1.4.0.RELEASE + + + + + diff --git a/spring-cloud-data-flow/README.MD b/spring-cloud-data-flow/README.MD new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/spring-cloud-data-flow/README.MD @@ -0,0 +1 @@ + diff --git a/spring-cloud/README.md b/spring-cloud/README.md new file mode 100644 index 0000000000..3e8cd21b82 --- /dev/null +++ b/spring-cloud/README.md @@ -0,0 +1,18 @@ +## The Module Holds Sources for the Following Articles + +- [Quick Intro to Spring Cloud Configuration](http://www.baeldung.com/spring-cloud-configuration) + + Spring Cloud Config is Spring’s client/server approach for storing and serving distributed configurations across multiple applications and environments. + + In this write-up, we’ll focus on an example of how to setup a Git-backed config server, use it in a simple REST application server and setup a secure environment including encrypted property values. + +- [Introduction to Spring Cloud Netflix – Eureka](http://www.baeldung.com/spring-cloud-netflix-eureka) + + In this article, we’ll introduce client-side service discovery via “Spring Cloud Netflix Eureka“. + + Client-side service discovery allows services to find and communicate with each other without hardcoding hostname and port. The only ‘fixed point’ in such an architecture consists of a service registry with which each service has to register. + +- [Intro to Spring Cloud Netflix - Hystrix](http://www.baeldung.com/spring-cloud-netflix-hystrix) +- [Dockerizing a Spring Boot Application](http://www.baeldung.com/dockerizing-spring-boot-application) + + diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml new file mode 100644 index 0000000000..2349613def --- /dev/null +++ b/spring-cloud/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT + + spring-cloud-config + spring-cloud-eureka + spring-cloud-hystrix + spring-cloud-bootstrap + + pom + + spring-cloud + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + UTF-8 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.springframework.boot + spring-boot-maven-plugin + 1.4.0.RELEASE + + + + + diff --git a/spring-cloud/spring-cloud-bootstrap/README.MD b/spring-cloud/spring-cloud-bootstrap/README.MD new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/README.MD @@ -0,0 +1 @@ + diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/discovery.properties b/spring-cloud/spring-cloud-bootstrap/application-config/discovery.properties new file mode 100644 index 0000000000..7f3df86c7e --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/application-config/discovery.properties @@ -0,0 +1,8 @@ +spring.application.name=discovery +server.port=8082 + +eureka.instance.hostname=localhost + +eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka/ +eureka.client.register-with-eureka=false +eureka.client.fetch-registry=false diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties b/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties new file mode 100644 index 0000000000..77faec8421 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties @@ -0,0 +1,10 @@ +spring.application.name=gateway +server.port=8080 + +eureka.client.region = default +eureka.client.registryFetchIntervalSeconds = 5 +eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka/ + +zuul.routes.resource.path=/resource/** +hystrix.command.resource.execution.isolation.thread.timeoutInMilliseconds: 5000 + diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/resource.properties b/spring-cloud/spring-cloud-bootstrap/application-config/resource.properties new file mode 100644 index 0000000000..4e6cf3817c --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/application-config/resource.properties @@ -0,0 +1,8 @@ +spring.application.name=resource +server.port=8083 + +resource.returnString=hello cloud + +eureka.client.region = default +eureka.client.registryFetchIntervalSeconds = 5 +eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka/ diff --git a/spring-cloud/spring-cloud-bootstrap/config/pom.xml b/spring-cloud/spring-cloud-bootstrap/config/pom.xml new file mode 100644 index 0000000000..0cb217acfb --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/config/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + config + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + + org.springframework.cloud + spring-cloud-config-server + + + org.springframework.cloud + spring-cloud-starter-eureka + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.RELEASE + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/integration/config/ConfigApplication.java b/spring-cloud/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/integration/config/ConfigApplication.java new file mode 100644 index 0000000000..ff6c093b8b --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/config/src/main/java/com/baeldung/spring/cloud/integration/config/ConfigApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud.integration.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.config.server.EnableConfigServer; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +@SpringBootApplication +@EnableConfigServer +@EnableEurekaClient +public class ConfigApplication { + public static void main(String[] args) { + SpringApplication.run(ConfigApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/config/src/main/resources/application.properties b/spring-cloud/spring-cloud-bootstrap/config/src/main/resources/application.properties new file mode 100644 index 0000000000..6f614d0690 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/config/src/main/resources/application.properties @@ -0,0 +1,8 @@ +server.port=8081 +spring.application.name=config + +spring.cloud.config.server.git.uri=file:///${user.home}/application-config + +eureka.client.region = default +eureka.client.registryFetchIntervalSeconds = 5 +eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml b/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml new file mode 100644 index 0000000000..ee7c589549 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + discovery + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + + org.springframework.cloud + spring-cloud-starter-config + + + org.springframework.cloud + spring-cloud-starter-eureka-server + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.RELEASE + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/integration/discovery/DiscoveryApplication.java b/spring-cloud/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/integration/discovery/DiscoveryApplication.java new file mode 100644 index 0000000000..a21c65312f --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/discovery/src/main/java/com/baeldung/spring/cloud/integration/discovery/DiscoveryApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.cloud.integration.discovery; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +@SpringBootApplication +@EnableEurekaServer +public class DiscoveryApplication { + public static void main(String[] args) { + SpringApplication.run(DiscoveryApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/discovery/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/discovery/src/main/resources/bootstrap.properties new file mode 100644 index 0000000000..ca9d59c9ed --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/discovery/src/main/resources/bootstrap.properties @@ -0,0 +1,2 @@ +spring.cloud.config.name=discovery +spring.cloud.config.uri=http://localhost:8081 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml new file mode 100644 index 0000000000..8e56d0fd35 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + gateway + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + + org.springframework.cloud + spring-cloud-starter-config + + + org.springframework.cloud + spring-cloud-starter-eureka + + + org.springframework.cloud + spring-cloud-starter-zuul + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.RELEASE + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/integration/resource/GatewayApplication.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/integration/resource/GatewayApplication.java new file mode 100644 index 0000000000..66e7c36f2a --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/integration/resource/GatewayApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud.integration.resource; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.netflix.zuul.EnableZuulProxy; + +@SpringBootApplication +@EnableZuulProxy +@EnableEurekaClient +public class GatewayApplication { + public static void main(String[] args) { + SpringApplication.run(GatewayApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/resources/bootstrap.properties new file mode 100644 index 0000000000..9610d72675 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/resources/bootstrap.properties @@ -0,0 +1,5 @@ +spring.cloud.config.name=gateway +spring.cloud.config.discovery.service-id=config +spring.cloud.config.discovery.enabled=true + +eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka/ \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/pom.xml b/spring-cloud/spring-cloud-bootstrap/pom.xml new file mode 100644 index 0000000000..c14c277d7f --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + + + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT + + + + config + discovery + gateway + resource + + + + spring-cloud-integration + 1.0.0-SNAPSHOT + pom + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/resource/pom.xml b/spring-cloud/spring-cloud-bootstrap/resource/pom.xml new file mode 100644 index 0000000000..78112fa3e0 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/resource/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + resource + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + + org.springframework.cloud + spring-cloud-starter-config + + + org.springframework.cloud + spring-cloud-starter-eureka + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.RELEASE + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/integration/resource/ResourceApplication.java b/spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/integration/resource/ResourceApplication.java new file mode 100644 index 0000000000..107a9d199f --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/integration/resource/ResourceApplication.java @@ -0,0 +1,25 @@ +package com.baeldung.spring.cloud.integration.resource; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@SpringBootApplication +@EnableEurekaClient +@RestController +public class ResourceApplication { + public static void main(String[] args) { + SpringApplication.run(ResourceApplication.class, args); + } + + @Value("${resource.returnString}") + private String returnString; + + @RequestMapping("/hello/cloud") + public String getString() { + return returnString; + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/resource/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/resource/src/main/resources/bootstrap.properties new file mode 100644 index 0000000000..3c88a0b520 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/resource/src/main/resources/bootstrap.properties @@ -0,0 +1,5 @@ +spring.cloud.config.name=resource +spring.cloud.config.discovery.service-id=config +spring.cloud.config.discovery.enabled=true + +eureka.client.serviceUrl.defaultZone=http://localhost:8082/eureka/ \ No newline at end of file diff --git a/spring-cloud/spring-cloud-config/client-config/config-client-development.properties b/spring-cloud/spring-cloud-config/client-config/config-client-development.properties new file mode 100644 index 0000000000..6401d1be7f --- /dev/null +++ b/spring-cloud/spring-cloud-config/client-config/config-client-development.properties @@ -0,0 +1,2 @@ +user.role=Developer +user.password=pass diff --git a/spring-cloud/spring-cloud-config/client-config/config-client-production.properties b/spring-cloud/spring-cloud-config/client-config/config-client-production.properties new file mode 100644 index 0000000000..cd2e14fcc3 --- /dev/null +++ b/spring-cloud/spring-cloud-config/client-config/config-client-production.properties @@ -0,0 +1 @@ +user.role=User diff --git a/spring-cloud/spring-cloud-config/client/pom.xml b/spring-cloud/spring-cloud-config/client/pom.xml new file mode 100644 index 0000000000..0ef4b35581 --- /dev/null +++ b/spring-cloud/spring-cloud-config/client/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + + com.baeldung.spring.cloud + spring-cloud-config + 0.0.1-SNAPSHOT + + client + jar + + client + Demo project for Spring Cloud Config Client + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.cloud + spring-cloud-starter-config + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.BUILD-SNAPSHOT + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + diff --git a/spring-cloud/spring-cloud-config/client/src/main/java/com/baeldung/spring/cloud/config/client/ConfigClient.java b/spring-cloud/spring-cloud-config/client/src/main/java/com/baeldung/spring/cloud/config/client/ConfigClient.java new file mode 100644 index 0000000000..1dd3bbdab0 --- /dev/null +++ b/spring-cloud/spring-cloud-config/client/src/main/java/com/baeldung/spring/cloud/config/client/ConfigClient.java @@ -0,0 +1,29 @@ +package com.baeldung.spring.cloud.config.client; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@SpringBootApplication +@RestController +public class ConfigClient { + @Value("${user.role}") + private String role; + + @Value("${user.password}") + private String password; + + public static void main(String[] args) { + SpringApplication.run(ConfigClient.class, args); + } + + @RequestMapping(value = "/whoami/{username}", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) + public String whoami(@PathVariable("username") String username) { + return String.format("Hello %s! You are a(n) %s and your password is '%s'.\n", username, role, password); + } +} diff --git a/spring-cloud/spring-cloud-config/client/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-config/client/src/main/resources/bootstrap.properties new file mode 100644 index 0000000000..18982a93b5 --- /dev/null +++ b/spring-cloud/spring-cloud-config/client/src/main/resources/bootstrap.properties @@ -0,0 +1,5 @@ +spring.application.name=config-client +spring.profiles.active=development +spring.cloud.config.uri=http://localhost:8888 +spring.cloud.config.username=root +spring.cloud.config.password=s3cr3t diff --git a/spring-cloud/spring-cloud-config/client/src/test/java/com/baeldung/spring/cloud/config/client/ConfigClientLiveTest.java b/spring-cloud/spring-cloud-config/client/src/test/java/com/baeldung/spring/cloud/config/client/ConfigClientLiveTest.java new file mode 100644 index 0000000000..058fd45f35 --- /dev/null +++ b/spring-cloud/spring-cloud-config/client/src/test/java/com/baeldung/spring/cloud/config/client/ConfigClientLiveTest.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.cloud.config.client; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = ConfigClient.class) +@WebAppConfiguration +public class ConfigClientLiveTest { + @Test + public void contextLoads() { + } +} diff --git a/spring-cloud/spring-cloud-config/docker/Dockerfile b/spring-cloud/spring-cloud-config/docker/Dockerfile new file mode 100644 index 0000000000..bdb37abf80 --- /dev/null +++ b/spring-cloud/spring-cloud-config/docker/Dockerfile @@ -0,0 +1,4 @@ +FROM alpine:edge +MAINTAINER baeldung.com +RUN apk add --no-cache openjdk8 +COPY files/UnlimitedJCEPolicyJDK8/* /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/ diff --git a/spring-cloud/spring-cloud-config/docker/Dockerfile.client b/spring-cloud/spring-cloud-config/docker/Dockerfile.client new file mode 100644 index 0000000000..5fbc0b98c0 --- /dev/null +++ b/spring-cloud/spring-cloud-config/docker/Dockerfile.client @@ -0,0 +1,6 @@ +FROM alpine-java:base +MAINTAINER baeldung.com +RUN apk --no-cache add netcat-openbsd +COPY files/config-client.jar /opt/spring-cloud/lib/ +COPY files/config-client-entrypoint.sh /opt/spring-cloud/bin/ +RUN chmod 755 /opt/spring-cloud/bin/config-client-entrypoint.sh diff --git a/spring-cloud/spring-cloud-config/docker/Dockerfile.server b/spring-cloud/spring-cloud-config/docker/Dockerfile.server new file mode 100644 index 0000000000..4f7bd751e8 --- /dev/null +++ b/spring-cloud/spring-cloud-config/docker/Dockerfile.server @@ -0,0 +1,9 @@ +FROM alpine-java:base +MAINTAINER baeldung.com +COPY files/config-server.jar /opt/spring-cloud/lib/ +ENV SPRING_APPLICATION_JSON='{"spring": {"cloud": {"config": {"server": \ + {"git": {"uri": "/var/lib/spring-cloud/config-repo", "clone-on-start": true}}}}}}' +ENTRYPOINT ["/usr/bin/java"] +CMD ["-jar", "/opt/spring-cloud/lib/config-server.jar"] +VOLUME /var/lib/spring-cloud/config-repo +EXPOSE 8888 diff --git a/spring-cloud/spring-cloud-config/docker/config-client-entrypoint.sh b/spring-cloud/spring-cloud-config/docker/config-client-entrypoint.sh new file mode 100644 index 0000000000..12352119fa --- /dev/null +++ b/spring-cloud/spring-cloud-config/docker/config-client-entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +while ! nc -z config-server 8888 ; do + echo "Waiting for upcoming Config Server" + sleep 2 +done + +java -jar /opt/spring-cloud/lib/config-client.jar diff --git a/spring-cloud/spring-cloud-config/docker/docker-compose.scale.yml b/spring-cloud/spring-cloud-config/docker/docker-compose.scale.yml new file mode 100644 index 0000000000..f74153bea3 --- /dev/null +++ b/spring-cloud/spring-cloud-config/docker/docker-compose.scale.yml @@ -0,0 +1,41 @@ +version: '2' +services: + config-server: + build: + context: . + dockerfile: Dockerfile.server + image: config-server:latest + expose: + - 8888 + networks: + - spring-cloud-network + volumes: + - spring-cloud-config-repo:/var/lib/spring-cloud/config-repo + logging: + driver: json-file + config-client: + build: + context: . + dockerfile: Dockerfile.client + image: config-client:latest + entrypoint: /opt/spring-cloud/bin/config-client-entrypoint.sh + environment: + SPRING_APPLICATION_JSON: '{"spring": {"cloud": {"config": {"uri": "http://config-server:8888"}}}}' + expose: + - 8080 + ports: + - 8080 + networks: + - spring-cloud-network + links: + - config-server:config-server + depends_on: + - config-server + logging: + driver: json-file +networks: + spring-cloud-network: + driver: bridge +volumes: + spring-cloud-config-repo: + external: true diff --git a/spring-cloud/spring-cloud-config/docker/docker-compose.yml b/spring-cloud/spring-cloud-config/docker/docker-compose.yml new file mode 100644 index 0000000000..74c71b651c --- /dev/null +++ b/spring-cloud/spring-cloud-config/docker/docker-compose.yml @@ -0,0 +1,43 @@ +version: '2' +services: + config-server: + container_name: config-server + build: + context: . + dockerfile: Dockerfile.server + image: config-server:latest + expose: + - 8888 + networks: + - spring-cloud-network + volumes: + - spring-cloud-config-repo:/var/lib/spring-cloud/config-repo + logging: + driver: json-file + config-client: + container_name: config-client + build: + context: . + dockerfile: Dockerfile.client + image: config-client:latest + entrypoint: /opt/spring-cloud/bin/config-client-entrypoint.sh + environment: + SPRING_APPLICATION_JSON: '{"spring": {"cloud": {"config": {"uri": "http://config-server:8888"}}}}' + expose: + - 8080 + ports: + - 8080:8080 + networks: + - spring-cloud-network + links: + - config-server:config-server + depends_on: + - config-server + logging: + driver: json-file +networks: + spring-cloud-network: + driver: bridge +volumes: + spring-cloud-config-repo: + external: true diff --git a/spring-cloud/spring-cloud-config/pom.xml b/spring-cloud/spring-cloud-config/pom.xml new file mode 100644 index 0000000000..8e0e4b8706 --- /dev/null +++ b/spring-cloud/spring-cloud-config/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + spring-cloud-config + 0.0.1-SNAPSHOT + pom + + + server + client + + + + org.springframework.boot + spring-boot-starter-parent + 1.3.5.RELEASE + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*LiveTest.java + + + + + + + + + 1.3.5.RELEASE + 2.19.1 + + diff --git a/spring-cloud/spring-cloud-config/server/pom.xml b/spring-cloud/spring-cloud-config/server/pom.xml new file mode 100644 index 0000000000..c3f68854bb --- /dev/null +++ b/spring-cloud/spring-cloud-config/server/pom.xml @@ -0,0 +1,82 @@ + + + 4.0.0 + + + com.baeldung.spring.cloud + spring-cloud-config + 0.0.1-SNAPSHOT + + server + + server + Demo project for Spring Cloud Config Server + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.cloud + spring-cloud-config-server + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.BUILD-SNAPSHOT + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + diff --git a/spring-cloud/spring-cloud-config/server/src/main/java/com/baeldung/spring/cloud/config/server/ConfigServer.java b/spring-cloud/spring-cloud-config/server/src/main/java/com/baeldung/spring/cloud/config/server/ConfigServer.java new file mode 100644 index 0000000000..4dd34ae3ff --- /dev/null +++ b/spring-cloud/spring-cloud-config/server/src/main/java/com/baeldung/spring/cloud/config/server/ConfigServer.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud.config.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.config.server.EnableConfigServer; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; + +@SpringBootApplication +@EnableConfigServer +@EnableWebSecurity +public class ConfigServer { + public static void main(String[] args) { + SpringApplication.run(ConfigServer.class, args); + } +} diff --git a/spring-cloud/spring-cloud-config/server/src/main/resources/application.properties b/spring-cloud/spring-cloud-config/server/src/main/resources/application.properties new file mode 100644 index 0000000000..2131f3b249 --- /dev/null +++ b/spring-cloud/spring-cloud-config/server/src/main/resources/application.properties @@ -0,0 +1,9 @@ +server.port=8888 +spring.cloud.config.server.git.uri=https://github.com/eugenp/tutorials/tree/master/spring-cloud-config/client-config +spring.cloud.config.server.git.clone-on-start=false +security.user.name=root +security.user.password=s3cr3t +encrypt.key-store.location=classpath:/config-server.jks +encrypt.key-store.password=my-s70r3-s3cr3t +encrypt.key-store.alias=config-server-key +encrypt.key-store.secret=my-k34-s3cr3t diff --git a/spring-cloud/spring-cloud-config/server/src/main/resources/config-server.jks b/spring-cloud/spring-cloud-config/server/src/main/resources/config-server.jks new file mode 100644 index 0000000000..f3dddb4a8f Binary files /dev/null and b/spring-cloud/spring-cloud-config/server/src/main/resources/config-server.jks differ diff --git a/spring-cloud/spring-cloud-config/server/src/test/java/com/baeldung/spring/cloud/config/server/ConfigServerListTest.java b/spring-cloud/spring-cloud-config/server/src/test/java/com/baeldung/spring/cloud/config/server/ConfigServerListTest.java new file mode 100644 index 0000000000..306c120e43 --- /dev/null +++ b/spring-cloud/spring-cloud-config/server/src/test/java/com/baeldung/spring/cloud/config/server/ConfigServerListTest.java @@ -0,0 +1,18 @@ +package com.baeldung.spring.cloud.config.server; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = ConfigServer.class) +@WebAppConfiguration +@Ignore +public class ConfigServerListTest { + @Test + public void contextLoads() { + } +} diff --git a/spring-cloud/spring-cloud-eureka/pom.xml b/spring-cloud/spring-cloud-eureka/pom.xml new file mode 100644 index 0000000000..f02bf7ad9c --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + spring-cloud-eureka + 1.0.0-SNAPSHOT + + spring-cloud-eureka-server + spring-cloud-eureka-client + spring-cloud-eureka-feign-client + + pom + + Spring Cloud Eureka + Spring Cloud Eureka Server and Sample Clients + + + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT + .. + + + + UTF-8 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.springframework.boot + spring-boot-maven-plugin + 1.4.0.RELEASE + + + + + diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml new file mode 100644 index 0000000000..720b49ddc2 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + spring-cloud-eureka-client + 1.0.0-SNAPSHOT + jar + + Spring Cloud Eureka Client + Spring Cloud Eureka Sample Client + + + com.baeldung.spring.cloud + spring-cloud-eureka + 1.0.0-SNAPSHOT + .. + + + + + org.springframework.cloud + spring-cloud-starter-eureka + 1.1.5.RELEASE + + + org.springframework.boot + spring-boot-starter-web + 1.4.0.RELEASE + + + + + + + org.springframework.cloud + spring-cloud-starter-parent + Brixton.SR4 + pom + import + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/src/main/java/com/baeldung/spring/cloud/eureka/client/EurekaClientApplication.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/src/main/java/com/baeldung/spring/cloud/eureka/client/EurekaClientApplication.java new file mode 100644 index 0000000000..48099eeaa2 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/src/main/java/com/baeldung/spring/cloud/eureka/client/EurekaClientApplication.java @@ -0,0 +1,32 @@ +package com.baeldung.spring.cloud.eureka.client; + +import com.netflix.discovery.EurekaClient; +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.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.context.annotation.Lazy; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@SpringBootApplication +@EnableEurekaClient +@RestController +public class EurekaClientApplication implements GreetingController { + @Autowired + @Lazy + private EurekaClient eurekaClient; + + @Value("${spring.application.name}") + private String appName; + + public static void main(String[] args) { + SpringApplication.run(EurekaClientApplication.class, args); + } + + @Override + public String greeting() { + return String.format("Hello from '%s'!", eurekaClient.getApplication(appName).getName()); + } +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/src/main/java/com/baeldung/spring/cloud/eureka/client/GreetingController.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/src/main/java/com/baeldung/spring/cloud/eureka/client/GreetingController.java new file mode 100644 index 0000000000..33ee2574b7 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/src/main/java/com/baeldung/spring/cloud/eureka/client/GreetingController.java @@ -0,0 +1,8 @@ +package com.baeldung.spring.cloud.eureka.client; + +import org.springframework.web.bind.annotation.RequestMapping; + +public interface GreetingController { + @RequestMapping("/greeting") + String greeting(); +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/src/main/resources/application.yml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/src/main/resources/application.yml new file mode 100644 index 0000000000..08624aa159 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/src/main/resources/application.yml @@ -0,0 +1,13 @@ +spring: + application: + name: spring-cloud-eureka-client + +server: + port: 0 + +eureka: + client: + serviceUrl: + defaultZone: ${EUREKA_URI:http://localhost:8761/eureka} + instance: + preferIpAddress: true \ No newline at end of file diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml new file mode 100644 index 0000000000..9e639c666a --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + spring-cloud-eureka-feign-client + 1.0.0-SNAPSHOT + jar + + Spring Cloud Eureka Feign Client + Spring Cloud Eureka - Sample Feign Client + + + com.baeldung.spring.cloud + spring-cloud-eureka + 1.0.0-SNAPSHOT + .. + + + + + com.baeldung.spring.cloud + spring-cloud-eureka-client + 1.0.0-SNAPSHOT + + + org.springframework.cloud + spring-cloud-starter-feign + 1.1.5.RELEASE + + + org.springframework.boot + spring-boot-starter-web + 1.4.0.RELEASE + + + org.springframework.boot + spring-boot-starter-thymeleaf + 1.4.0.RELEASE + + + + + + + org.springframework.cloud + spring-cloud-starter-parent + Brixton.SR4 + pom + import + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/java/com/baeldung/spring/cloud/feign/client/FeignClientApplication.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/java/com/baeldung/spring/cloud/feign/client/FeignClientApplication.java new file mode 100644 index 0000000000..7beb51d1ac --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/java/com/baeldung/spring/cloud/feign/client/FeignClientApplication.java @@ -0,0 +1,29 @@ +package com.baeldung.spring.cloud.feign.client; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.netflix.feign.EnableFeignClients; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +@SpringBootApplication +@EnableEurekaClient +@EnableFeignClients +@Controller +public class FeignClientApplication { + @Autowired + private GreetingClient greetingClient; + + public static void main(String[] args) { + SpringApplication.run(FeignClientApplication.class, args); + } + + @RequestMapping("/get-greeting") + public String greeting(Model model) { + model.addAttribute("greeting", greetingClient.greeting()); + return "greeting-view"; + } +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/java/com/baeldung/spring/cloud/feign/client/GreetingClient.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/java/com/baeldung/spring/cloud/feign/client/GreetingClient.java new file mode 100644 index 0000000000..6bd444b347 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/java/com/baeldung/spring/cloud/feign/client/GreetingClient.java @@ -0,0 +1,8 @@ +package com.baeldung.spring.cloud.feign.client; + +import com.baeldung.spring.cloud.eureka.client.GreetingController; +import org.springframework.cloud.netflix.feign.FeignClient; + +@FeignClient("spring-cloud-eureka-client") +public interface GreetingClient extends GreetingController { +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/resources/application.yml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/resources/application.yml new file mode 100644 index 0000000000..d053ef7a7e --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/resources/application.yml @@ -0,0 +1,11 @@ +spring: + application: + name: spring-cloud-eureka-feign-client + +server: + port: 8080 + +eureka: + client: + serviceUrl: + defaultZone: ${EUREKA_URI:http://localhost:8761/eureka} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/resources/templates/greeting-view.html b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/resources/templates/greeting-view.html new file mode 100644 index 0000000000..42cdadb487 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/src/main/resources/templates/greeting-view.html @@ -0,0 +1,9 @@ + + + + Greeting Page + + +

    + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml new file mode 100644 index 0000000000..f4d655f708 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + spring-cloud-eureka-server + 1.0.0-SNAPSHOT + jar + + Spring Cloud Eureka Server + Spring Cloud Eureka Server Demo + + + com.baeldung.spring.cloud + spring-cloud-eureka + 1.0.0-SNAPSHOT + .. + + + + + org.springframework.cloud + spring-cloud-starter-eureka-server + 1.1.5.RELEASE + + + + + + + org.springframework.cloud + spring-cloud-starter-parent + Brixton.SR4 + pom + import + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/src/main/java/com/baeldung/spring/cloud/eureka/server/EurekaServerApplication.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/src/main/java/com/baeldung/spring/cloud/eureka/server/EurekaServerApplication.java new file mode 100644 index 0000000000..d55145448d --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/src/main/java/com/baeldung/spring/cloud/eureka/server/EurekaServerApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.cloud.eureka.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +@SpringBootApplication +@EnableEurekaServer +public class EurekaServerApplication { + public static void main(String[] args) { + SpringApplication.run(EurekaServerApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/src/main/resources/application.yml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/src/main/resources/application.yml new file mode 100644 index 0000000000..49c3179bb5 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/src/main/resources/application.yml @@ -0,0 +1,7 @@ +server: + port: 8761 + +eureka: + client: + registerWithEureka: false + fetchRegistry: false \ No newline at end of file diff --git a/spring-cloud/spring-cloud-hystrix/README.MD b/spring-cloud/spring-cloud-hystrix/README.MD new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/README.MD @@ -0,0 +1 @@ + diff --git a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml new file mode 100644 index 0000000000..8209dc8c67 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + feign-rest-consumer + 1.0.0-SNAPSHOT + jar + + feign-rest-consumer + + + com.baeldung.spring.cloud + spring-cloud-hystrix + 1.0.0-SNAPSHOT + .. + + + + + com.baeldung.spring.cloud + rest-producer + 1.0.0-SNAPSHOT + + + org.springframework.cloud + spring-cloud-starter-hystrix + 1.1.5.RELEASE + + + org.springframework.cloud + spring-cloud-starter-hystrix-dashboard + 1.1.5.RELEASE + + + org.springframework.cloud + spring-cloud-starter-feign + 1.1.5.RELEASE + + + org.springframework.boot + spring-boot-starter-web + 1.4.0.RELEASE + + + org.springframework.boot + spring-boot-starter-thymeleaf + 1.4.0.RELEASE + + + org.springframework.boot + spring-boot-starter-actuator + 1.4.0.RELEASE + + + + + + + org.springframework.cloud + spring-cloud-starter-parent + Brixton.SR4 + pom + import + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingClient.java b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingClient.java new file mode 100644 index 0000000000..b715e8c052 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingClient.java @@ -0,0 +1,21 @@ +package com.baeldung.spring.cloud.hystrix.rest.consumer; + +import com.baeldung.spring.cloud.hystrix.rest.producer.GreetingController; +import org.springframework.cloud.netflix.feign.FeignClient; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.PathVariable; + +@FeignClient( + name = "rest-producer", + url = "http://localhost:9090", + fallback = GreetingClient.GreetingClientFallback.class +) +public interface GreetingClient extends GreetingController { + @Component + public static class GreetingClientFallback implements GreetingClient { + @Override + public String greeting(@PathVariable("username") String username) { + return "Hello User!"; + } + } +} diff --git a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingController.java b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingController.java new file mode 100644 index 0000000000..62dbbdd608 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingController.java @@ -0,0 +1,19 @@ +package com.baeldung.spring.cloud.hystrix.rest.consumer; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class GreetingController { + @Autowired + private GreetingClient greetingClient; + + @RequestMapping("/get-greeting/{username}") + public String getGreeting(Model model, @PathVariable("username") String username) { + model.addAttribute("greeting", greetingClient.greeting(username)); + return "greeting-view"; + } +} diff --git a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/RestConsumerFeignApplication.java b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/RestConsumerFeignApplication.java new file mode 100644 index 0000000000..2fc54216fe --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/RestConsumerFeignApplication.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.cloud.hystrix.rest.consumer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.cloud.netflix.feign.EnableFeignClients; +import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; + +@SpringBootApplication +@EnableCircuitBreaker +@EnableHystrixDashboard +@EnableFeignClients +public class RestConsumerFeignApplication { + public static void main(String[] args) { + SpringApplication.run(RestConsumerFeignApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/resources/application.properties b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/resources/application.properties new file mode 100644 index 0000000000..3cf12afeb9 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=8082 diff --git a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/resources/templates/greeting-view.html b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/resources/templates/greeting-view.html new file mode 100644 index 0000000000..302390fde0 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/src/main/resources/templates/greeting-view.html @@ -0,0 +1,9 @@ + + + + Greetings from Hystrix + + +

    + + diff --git a/spring-cloud/spring-cloud-hystrix/pom.xml b/spring-cloud/spring-cloud-hystrix/pom.xml new file mode 100644 index 0000000000..b992ce3846 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + spring-cloud-hystrix + 1.0.0-SNAPSHOT + + rest-producer + rest-consumer + feign-rest-consumer + + pom + + spring-cloud-hystrix + + + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT + .. + + + + UTF-8 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.springframework.boot + spring-boot-maven-plugin + 1.4.0.RELEASE + + + + + diff --git a/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml b/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml new file mode 100644 index 0000000000..649ca88eb3 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + rest-consumer + 1.0.0-SNAPSHOT + jar + + rest-consumer + + + com.baeldung.spring.cloud + spring-cloud-hystrix + 1.0.0-SNAPSHOT + .. + + + + + org.springframework.cloud + spring-cloud-starter-hystrix + 1.1.5.RELEASE + + + org.springframework.cloud + spring-cloud-starter-hystrix-dashboard + 1.1.5.RELEASE + + + org.springframework.boot + spring-boot-starter-web + 1.4.0.RELEASE + + + org.springframework.boot + spring-boot-starter-thymeleaf + 1.4.0.RELEASE + + + org.springframework.boot + spring-boot-starter-actuator + 1.4.0.RELEASE + + + + + + + org.springframework.cloud + spring-cloud-starter-parent + Brixton.SR4 + pom + import + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingController.java b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingController.java new file mode 100644 index 0000000000..112ad167f6 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingController.java @@ -0,0 +1,19 @@ +package com.baeldung.spring.cloud.hystrix.rest.consumer; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class GreetingController { + @Autowired + private GreetingService greetingService; + + @RequestMapping("/get-greeting/{username}") + public String getGreeting(Model model, @PathVariable("username") String username) { + model.addAttribute("greeting", greetingService.getGreeting(username)); + return "greeting-view"; + } +} diff --git a/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingService.java b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingService.java new file mode 100644 index 0000000000..2502e292df --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/GreetingService.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.cloud.hystrix.rest.consumer; + +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +public class GreetingService { + @HystrixCommand(fallbackMethod = "defaultGreeting") + public String getGreeting(String username) { + return new RestTemplate().getForObject("http://localhost:9090/greeting/{username}", String.class, username); + } + + private String defaultGreeting(String username) { + return "Hello User!"; + } +} diff --git a/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/RestConsumerApplication.java b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/RestConsumerApplication.java new file mode 100644 index 0000000000..113949c754 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/consumer/RestConsumerApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud.hystrix.rest.consumer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; + +@SpringBootApplication +@EnableCircuitBreaker +@EnableHystrixDashboard +public class RestConsumerApplication { + public static void main(String[] args) { + SpringApplication.run(RestConsumerApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/resources/application.properties b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/resources/application.properties new file mode 100644 index 0000000000..4c00e40deb --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=8080 diff --git a/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/resources/templates/greeting-view.html b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/resources/templates/greeting-view.html new file mode 100644 index 0000000000..302390fde0 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-consumer/src/main/resources/templates/greeting-view.html @@ -0,0 +1,9 @@ + + + + Greetings from Hystrix + + +

    + + diff --git a/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml b/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml new file mode 100644 index 0000000000..726d18d2c3 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + rest-producer + 1.0.0-SNAPSHOT + jar + + rest-producer + + + com.baeldung.spring.cloud + spring-cloud-hystrix + 1.0.0-SNAPSHOT + .. + + + + + org.springframework.boot + spring-boot-starter-web + 1.4.0.RELEASE + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/producer/GreetingController.java b/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/producer/GreetingController.java new file mode 100644 index 0000000000..e82220d27a --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/producer/GreetingController.java @@ -0,0 +1,9 @@ +package com.baeldung.spring.cloud.hystrix.rest.producer; + +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +public interface GreetingController { + @RequestMapping("/greeting/{username}") + String greeting(@PathVariable("username") String username); +} diff --git a/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/producer/GreetingControllerImpl.java b/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/producer/GreetingControllerImpl.java new file mode 100644 index 0000000000..3541035ba5 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/producer/GreetingControllerImpl.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.cloud.hystrix.rest.producer; + +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class GreetingControllerImpl implements GreetingController { + @Override + public String greeting(@PathVariable("username") String username) { + return String.format("Hello %s!\n", username); + } +} diff --git a/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/producer/RestProducerApplication.java b/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/producer/RestProducerApplication.java new file mode 100644 index 0000000000..206a6a2d03 --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/java/com/baeldung/spring/cloud/hystrix/rest/producer/RestProducerApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.spring.cloud.hystrix.rest.producer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RestProducerApplication { + public static void main(String[] args) { + SpringApplication.run(RestProducerApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/resources/application.properties b/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/resources/application.properties new file mode 100644 index 0000000000..9ce9d88ffb --- /dev/null +++ b/spring-cloud/spring-cloud-hystrix/rest-producer/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.application.name=rest-producer +server.port=9090 diff --git a/spring-cucumber/pom.xml b/spring-cucumber/pom.xml new file mode 100644 index 0000000000..f3b9c983f0 --- /dev/null +++ b/spring-cucumber/pom.xml @@ -0,0 +1,89 @@ + + + 4.0.0 + + com.baeldung + spring-cucumber + 0.0.1-SNAPSHOT + jar + + spring-cucumber + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.3.5.RELEASE + + + + + UTF-8 + 1.8 + 1.2.4 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + info.cukes + cucumber-core + ${cucumber.java.version} + test + + + + info.cukes + cucumber-java + ${cucumber.java.version} + test + + + + info.cukes + cucumber-junit + ${cucumber.java.version} + test + + + + info.cukes + cucumber-spring + ${cucumber.java.version} + test + + + + + org.apache.commons + commons-io + 1.3.2 + + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-cucumber/src/main/java/com/baeldung/BaeldungController.java b/spring-cucumber/src/main/java/com/baeldung/BaeldungController.java new file mode 100644 index 0000000000..8e87ed3028 --- /dev/null +++ b/spring-cucumber/src/main/java/com/baeldung/BaeldungController.java @@ -0,0 +1,22 @@ +package com.baeldung; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class BaeldungController { + + @RequestMapping(method = { RequestMethod.GET }, value = { "/hello" }) + public String sayHello(HttpServletResponse response) { + return "hello"; + } + + @RequestMapping(method = { RequestMethod.POST }, value = { "/baeldung" }) + public String sayHelloPost(HttpServletResponse response) { + return "hello"; + } + +} diff --git a/spring-cucumber/src/main/java/com/baeldung/SpringDemoApplication.java b/spring-cucumber/src/main/java/com/baeldung/SpringDemoApplication.java new file mode 100644 index 0000000000..60548dd6e3 --- /dev/null +++ b/spring-cucumber/src/main/java/com/baeldung/SpringDemoApplication.java @@ -0,0 +1,26 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.web.SpringBootServletInitializer; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +@SpringBootApplication +public class SpringDemoApplication extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(SpringDemoApplication.class, args); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(SpringDemoApplication.class); + } + + @Bean + public RestTemplate getRestTemplate(){ + return new RestTemplate(); + } +} diff --git a/spring-cucumber/src/main/java/com/baeldung/VersionController.java b/spring-cucumber/src/main/java/com/baeldung/VersionController.java new file mode 100644 index 0000000000..f673f0e31f --- /dev/null +++ b/spring-cucumber/src/main/java/com/baeldung/VersionController.java @@ -0,0 +1,14 @@ +package com.baeldung; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class VersionController { + + @RequestMapping(method = { RequestMethod.GET }, value = { "/version" }) + public String getVersion() { + return "1.0"; + } +} diff --git a/spring-cloud-data-flow/time-processor/src/main/resources/application.properties b/spring-cucumber/src/main/resources/application.properties similarity index 100% rename from spring-cloud-data-flow/time-processor/src/main/resources/application.properties rename to spring-cucumber/src/main/resources/application.properties diff --git a/spring-cucumber/src/test/java/com/baeldung/CucumberTest.java b/spring-cucumber/src/test/java/com/baeldung/CucumberTest.java new file mode 100644 index 0000000000..c31a35b271 --- /dev/null +++ b/spring-cucumber/src/test/java/com/baeldung/CucumberTest.java @@ -0,0 +1,10 @@ +package com.baeldung; + +import cucumber.api.CucumberOptions; +import cucumber.api.junit.Cucumber; +import org.junit.runner.RunWith; + +@RunWith(Cucumber.class) +@CucumberOptions(features = "src/test/resources") +public class CucumberTest { +} \ No newline at end of file diff --git a/spring-cucumber/src/test/java/com/baeldung/HeaderSettingRequestCallback.java b/spring-cucumber/src/test/java/com/baeldung/HeaderSettingRequestCallback.java new file mode 100644 index 0000000000..ab8a9c55b2 --- /dev/null +++ b/spring-cucumber/src/test/java/com/baeldung/HeaderSettingRequestCallback.java @@ -0,0 +1,33 @@ +package com.baeldung; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.web.client.RequestCallback; + +import java.io.IOException; +import java.util.Map; + +public class HeaderSettingRequestCallback implements RequestCallback { + final Map requestHeaders; + + private String body; + + public HeaderSettingRequestCallback(final Map headers) { + this.requestHeaders = headers; + } + + public void setBody(final String postBody) { + this.body = postBody; + } + + @Override + public void doWithRequest(ClientHttpRequest request) throws IOException { + final HttpHeaders clientHeaders = request.getHeaders(); + for (final Map.Entry entry : requestHeaders.entrySet()) { + clientHeaders.add(entry.getKey(), entry.getValue()); + } + if (null != body) { + request.getBody().write(body.getBytes()); + } + } +} \ No newline at end of file diff --git a/spring-cucumber/src/test/java/com/baeldung/OtherDefs.java b/spring-cucumber/src/test/java/com/baeldung/OtherDefs.java new file mode 100644 index 0000000000..edbc14f319 --- /dev/null +++ b/spring-cucumber/src/test/java/com/baeldung/OtherDefs.java @@ -0,0 +1,16 @@ +package com.baeldung; + +import cucumber.api.java.en.Given; +import cucumber.api.java.en.When; + +public class OtherDefs extends SpringIntegrationTest { + @When("^the client calls /baeldung$") + public void the_client_issues_POST_hello() throws Throwable { + executePost("http://localhost:8080/baeldung"); + } + + @Given("^the client calls /hello$") + public void the_client_issues_GET_hello() throws Throwable { + executeGet("http://localhost:8080/hello"); + } +} \ No newline at end of file diff --git a/spring-cucumber/src/test/java/com/baeldung/ResponseResults.java b/spring-cucumber/src/test/java/com/baeldung/ResponseResults.java new file mode 100644 index 0000000000..4c0125e9b4 --- /dev/null +++ b/spring-cucumber/src/test/java/com/baeldung/ResponseResults.java @@ -0,0 +1,33 @@ +package com.baeldung; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; + +import org.apache.commons.io.IOUtils; +import org.springframework.http.client.ClientHttpResponse; + +public class ResponseResults { + private final ClientHttpResponse theResponse; + private final String body; + + protected ResponseResults(final ClientHttpResponse response) throws IOException { + this.theResponse = response; + final InputStream bodyInputStream = response.getBody(); + if (null == bodyInputStream) { + this.body = "{}"; + } else { + final StringWriter stringWriter = new StringWriter(); + IOUtils.copy(bodyInputStream, stringWriter); + this.body = stringWriter.toString(); + } + } + + protected ClientHttpResponse getTheResponse() { + return theResponse; + } + + protected String getBody() { + return body; + } +} \ No newline at end of file diff --git a/spring-cucumber/src/test/java/com/baeldung/SpringIntegrationTest.java b/spring-cucumber/src/test/java/com/baeldung/SpringIntegrationTest.java new file mode 100644 index 0000000000..34efff63fb --- /dev/null +++ b/spring-cucumber/src/test/java/com/baeldung/SpringIntegrationTest.java @@ -0,0 +1,91 @@ +package com.baeldung; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.SpringApplicationContextLoader; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.ResponseExtractor; +import org.springframework.web.client.RestTemplate; + +//@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = SpringDemoApplication.class, loader = SpringApplicationContextLoader.class) +@WebAppConfiguration +@IntegrationTest +public class SpringIntegrationTest { + protected static ResponseResults latestResponse = null; + + @Autowired + protected RestTemplate restTemplate; + + protected void executeGet(String url) throws IOException { + final Map headers = new HashMap<>(); + headers.put("Accept", "application/json"); + final HeaderSettingRequestCallback requestCallback = new HeaderSettingRequestCallback(headers); + final ResponseResultErrorHandler errorHandler = new ResponseResultErrorHandler(); + + restTemplate.setErrorHandler(errorHandler); + latestResponse = restTemplate.execute(url, HttpMethod.GET, requestCallback, new ResponseExtractor() { + @Override + public ResponseResults extractData(ClientHttpResponse response) throws IOException { + if (errorHandler.hadError) { + return (errorHandler.getResults()); + } else { + return (new ResponseResults(response)); + } + } + }); + + } + + protected void executePost(String url) throws IOException { + final Map headers = new HashMap<>(); + headers.put("Accept", "application/json"); + final HeaderSettingRequestCallback requestCallback = new HeaderSettingRequestCallback(headers); + final ResponseResultErrorHandler errorHandler = new ResponseResultErrorHandler(); + + if (restTemplate == null) { + restTemplate = new RestTemplate(); + } + + restTemplate.setErrorHandler(errorHandler); + latestResponse = restTemplate.execute(url, HttpMethod.POST, requestCallback, new ResponseExtractor() { + @Override + public ResponseResults extractData(ClientHttpResponse response) throws IOException { + if (errorHandler.hadError) { + return (errorHandler.getResults()); + } else { + return (new ResponseResults(response)); + } + } + }); + + } + + private class ResponseResultErrorHandler implements ResponseErrorHandler { + private ResponseResults results = null; + private Boolean hadError = false; + + private ResponseResults getResults() { + return results; + } + + @Override + public boolean hasError(ClientHttpResponse response) throws IOException { + hadError = response.getRawStatusCode() >= 400; + return hadError; + } + + @Override + public void handleError(ClientHttpResponse response) throws IOException { + results = new ResponseResults(response); + } + } +} \ No newline at end of file diff --git a/spring-cucumber/src/test/java/com/baeldung/StepDefs.java b/spring-cucumber/src/test/java/com/baeldung/StepDefs.java new file mode 100644 index 0000000000..865a1e13fa --- /dev/null +++ b/spring-cucumber/src/test/java/com/baeldung/StepDefs.java @@ -0,0 +1,29 @@ +package com.baeldung; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import org.springframework.http.HttpStatus; + +import cucumber.api.java.en.And; +import cucumber.api.java.en.Then; +import cucumber.api.java.en.When; + +public class StepDefs extends SpringIntegrationTest { + + @When("^the client calls /version$") + public void the_client_issues_GET_version() throws Throwable { + executeGet("http://localhost:8080/version"); + } + + @Then("^the client receives status code of (\\d+)$") + public void the_client_receives_status_code_of(int statusCode) throws Throwable { + final HttpStatus currentStatusCode = latestResponse.getTheResponse().getStatusCode(); + assertThat("status code is incorrect : " + latestResponse.getBody(), currentStatusCode.value(), is(statusCode)); + } + + @And("^the client receives server version (.+)$") + public void the_client_receives_server_version_body(String version) throws Throwable { + assertThat(latestResponse.getBody(), is(version)); + } +} \ No newline at end of file diff --git a/spring-cucumber/src/test/resources/baelung.feature b/spring-cucumber/src/test/resources/baelung.feature new file mode 100644 index 0000000000..21f18db3a4 --- /dev/null +++ b/spring-cucumber/src/test/resources/baelung.feature @@ -0,0 +1,9 @@ +Feature: the message can be retrieved + Scenario: client makes call to POST /baeldung + When the client calls /baeldung + Then the client receives status code of 200 + And the client receives server version hello + Scenario: client makes call to GET /hello + Given the client calls /hello + When the client receives status code of 200 + Then the client receives server version hello \ No newline at end of file diff --git a/spring-cucumber/src/test/resources/version.feature b/spring-cucumber/src/test/resources/version.feature new file mode 100644 index 0000000000..12f77137ff --- /dev/null +++ b/spring-cucumber/src/test/resources/version.feature @@ -0,0 +1,6 @@ +Feature: the version can be retrieved + Scenario: client makes call to GET /version + When the client calls /version + Then the client receives status code of 200 + And the client receives server version 1.0 + \ No newline at end of file diff --git a/spring-data-cassandra/.classpath b/spring-data-cassandra/.classpath deleted file mode 100644 index 698778fef3..0000000000 --- a/spring-data-cassandra/.classpath +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-data-cassandra/.project b/spring-data-cassandra/.project deleted file mode 100644 index 239fa4f002..0000000000 --- a/spring-data-cassandra/.project +++ /dev/null @@ -1,29 +0,0 @@ - - - spring-data-cassandra - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - diff --git a/spring-data-cassandra/README.md b/spring-data-cassandra/README.md index a245ff62a1..456eefcf18 100644 --- a/spring-data-cassandra/README.md +++ b/spring-data-cassandra/README.md @@ -2,6 +2,7 @@ ### Relevant Articles: - [Introduction to Spring Data Cassandra](http://www.baeldung.com/spring-data-cassandra-tutorial) +- [Using the CassandraTemplate from Spring Data](http://www.baeldung.com/spring-data-cassandratemplate-cqltemplate) ### Build the Project with Tests Running ``` diff --git a/spring-data-cassandra/pom.xml b/spring-data-cassandra/pom.xml index 7e21859b5d..e5f8779942 100644 --- a/spring-data-cassandra/pom.xml +++ b/spring-data-cassandra/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.baeldung + com.baeldung spring-data-cassandra 0.0.1-SNAPSHOT jar @@ -12,7 +12,7 @@ UTF-8 - 4.2.3.RELEASE + 4.2.5.RELEASE 1.3.2.RELEASE diff --git a/spring-data-couchbase-2/README.md b/spring-data-couchbase-2/README.md new file mode 100644 index 0000000000..2e56b25fef --- /dev/null +++ b/spring-data-couchbase-2/README.md @@ -0,0 +1,53 @@ +## Spring Data Couchbase Tutorial Project + +### Relevant Articles: +- [Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase) +- [Entity Validation, Query Consistency, and Optimistic Locking in Spring Data Couchbase](http://www.baeldung.com/entity-validation-locking-and-query-consistency-in-spring-data-couchbase) +- [Multiple Buckets and Spatial View Queries in Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase-buckets-and-spatial-view-queries) + +### Overview +This Maven project contains the Java code for Spring Data Couchbase +entities, repositories, and template-based services +as described in the tutorials, as well as a unit/integration test +for each service implementation. + +### Working with the Code +The project was developed and tested using Java 7 and 8 in the Eclipse-based +Spring Source Toolkit (STS) and therefore should run fine in any +recent version of Eclipse or another IDE of your choice +that supports Java 7 or later. + +### Building the Project +You can also build the project using Maven outside of any IDE: +``` +mvn clean install +``` + +### Package Organization +Java classes for the first two tutorials listed above are in src/main/java in the package hierarchy +org.baeldung.spring.data.couchbase + +Java classes for the multiple-bucket tutorials are in src/main/java in the package hierarchy +org.baeldung.spring.data.couchbase2b + +### Running the tests +The test classes for the single-bucket tutorials are in src/test/java in the package +org.baeldung.spring.data.couchbase.service: +- PersonServiceTest (abstract) +- PersonRepositoryTest (concrete) +- PersonTemplateServiceTest (concrete) +- StudentServiceTest (abstract) +- StudentRepositoryTest (concrete) +- StudentTemplateServiceTest (concrete) + +The concrete test classes for the multiple-bucket tutorial are in src/test/java in the package +org.baeldung.spring.data.couchbase2b.service: +- CampusRepositoryServiceImplTest +- PersonRepositoryServiceImplTest +- StudentRepositoryServiceImplTest + +The concrete test classes may be run as JUnit tests from your IDE +or using the Maven command line: +``` +mvn test +``` diff --git a/spring-data-couchbase-2/pom.xml b/spring-data-couchbase-2/pom.xml new file mode 100644 index 0000000000..d24ef4aeaa --- /dev/null +++ b/spring-data-couchbase-2/pom.xml @@ -0,0 +1,105 @@ + + 4.0.0 + org.baeldung + spring-data-couchbase-2 + 0.1-SNAPSHOT + spring-data-couchbase-2 + jar + + + + + + org.springframework + spring-context + ${spring-framework.version} + + + org.springframework + spring-context-support + ${spring-framework.version} + + + org.springframework.data + spring-data-couchbase + ${spring-data-couchbase.version} + + + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + + + + joda-time + joda-time + ${joda-time.version} + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + compile + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + + + org.springframework + spring-test + ${spring-framework.version} + test + + + junit + junit + ${junit.version} + test + + + + + + + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + + 1.7 + UTF-8 + 4.2.4.RELEASE + 2.1.1.RELEASE + 5.2.4.Final + 2.9.2 + 1.1.3 + 1.7.12 + 4.11 + + + + diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/model/Campus.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/model/Campus.java new file mode 100644 index 0000000000..201b14cf0b --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/model/Campus.java @@ -0,0 +1,102 @@ +package org.baeldung.spring.data.couchbase.model; + +import javax.validation.constraints.NotNull; + +import org.springframework.data.annotation.Id; +import org.springframework.data.couchbase.core.mapping.Document; +import org.springframework.data.geo.Point; + +import com.couchbase.client.java.repository.annotation.Field; + +@Document +public class Campus { + + @Id + private String id; + @Field + @NotNull + private String name; + @Field + @NotNull + private Point location; + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public Point getLocation() { + return location; + } + public void setLocation(Point location) { + this.location = location; + } + + @Override + public int hashCode() { + int hash = 1; + if(id != null) { + hash = hash * 31 + id.hashCode(); + } + if(name != null) { + hash = hash * 31 + name.hashCode(); + } + if(location != null) { + hash = hash * 31 + location.hashCode(); + } + return hash; + } + + @Override + public boolean equals(Object obj) { + if((obj == null) || (obj.getClass() != this.getClass())) return false; + if(obj == this) return true; + Campus other = (Campus) obj; + return this.hashCode() == other.hashCode(); + } + + @SuppressWarnings("unused") + private Campus() {} + + public Campus(Builder b) { + this.id = b.id; + this.name = b.name; + this.location = b.location; + } + + public static class Builder { + private String id; + private String name; + private Point location; + + public static Builder newInstance() { + return new Builder(); + } + + public Campus build() { + return new Campus(this); + } + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder location(Point location) { + this.location = location; + return this; + } + } +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/model/Person.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/model/Person.java new file mode 100644 index 0000000000..9220e157ed --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/model/Person.java @@ -0,0 +1,87 @@ +package org.baeldung.spring.data.couchbase.model; + +import javax.validation.constraints.NotNull; + +import org.joda.time.DateTime; +import org.springframework.data.annotation.Id; +import org.springframework.data.couchbase.core.mapping.Document; + +import com.couchbase.client.java.repository.annotation.Field; + +@Document +public class Person { + + @Id + private String id; + @Field + @NotNull + private String firstName; + @Field + @NotNull + private String lastName; + @Field + @NotNull + private DateTime created; + @Field + private DateTime updated; + + public Person(String id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + public DateTime getCreated() { + return created; + } + public void setCreated(DateTime created) { + this.created = created; + } + public DateTime getUpdated() { + return updated; + } + public void setUpdated(DateTime updated) { + this.updated = updated; + } + + @Override + public int hashCode() { + int hash = 1; + if(id != null) { + hash = hash * 31 + id.hashCode(); + } + if(firstName != null) { + hash = hash * 31 + firstName.hashCode(); + } + if(lastName != null) { + hash = hash * 31 + lastName.hashCode(); + } + return hash; + } + + @Override + public boolean equals(Object obj) { + if((obj == null) || (obj.getClass() != this.getClass())) return false; + if(obj == this) return true; + Person other = (Person) obj; + return this.hashCode() == other.hashCode(); + } +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/model/Student.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/model/Student.java new file mode 100644 index 0000000000..9c266c2c62 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/model/Student.java @@ -0,0 +1,113 @@ +package org.baeldung.spring.data.couchbase.model; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Past; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + +import org.joda.time.DateTime; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Version; +import org.springframework.data.couchbase.core.mapping.Document; + +import com.couchbase.client.java.repository.annotation.Field; + +@Document +public class Student { + private static final String NAME_REGEX = "^[a-zA-Z .'-]+$"; + + @Id + private String id; + @Field + @NotNull + @Size(min=1, max=20) + @Pattern(regexp=NAME_REGEX) + private String firstName; + @Field + @NotNull + @Size(min=1, max=20) + @Pattern(regexp=NAME_REGEX) + private String lastName; + @Field + @Past + private DateTime dateOfBirth; + @Field + @NotNull + private DateTime created; + @Field + private DateTime updated; + @Version + private long version; + + public Student() {} + + public Student(String id, String firstName, String lastName, DateTime dateOfBirth) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.dateOfBirth = dateOfBirth; + } + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + public DateTime getDateOfBirth() { + return dateOfBirth; + } + public void setDateOfBirth(DateTime dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } + public DateTime getCreated() { + return created; + } + public void setCreated(DateTime created) { + this.created = created; + } + public DateTime getUpdated() { + return updated; + } + public void setUpdated(DateTime updated) { + this.updated = updated; + } + + @Override + public int hashCode() { + int hash = 1; + if(id != null) { + hash = hash * 31 + id.hashCode(); + } + if(firstName != null) { + hash = hash * 31 + firstName.hashCode(); + } + if(lastName != null) { + hash = hash * 31 + lastName.hashCode(); + } + if(dateOfBirth != null) { + hash = hash * 31 + dateOfBirth.hashCode(); + } + return hash; + } + + @Override + public boolean equals(Object obj) { + if((obj == null) || (obj.getClass() != this.getClass())) return false; + if(obj == this) return true; + Student other = (Student) obj; + return this.hashCode() == other.hashCode(); + } +} \ No newline at end of file diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/CustomStudentRepository.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/CustomStudentRepository.java new file mode 100644 index 0000000000..9a5bf21492 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/CustomStudentRepository.java @@ -0,0 +1,9 @@ +package org.baeldung.spring.data.couchbase.repos; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Student; + +public interface CustomStudentRepository { + List findByFirstNameStartsWith(String s); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/CustomStudentRepositoryImpl.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/CustomStudentRepositoryImpl.java new file mode 100644 index 0000000000..66b672a4fd --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/CustomStudentRepositoryImpl.java @@ -0,0 +1,25 @@ +package org.baeldung.spring.data.couchbase.repos; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Student; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.couchbase.core.CouchbaseTemplate; + +import com.couchbase.client.java.view.Stale; +import com.couchbase.client.java.view.ViewQuery; + +public class CustomStudentRepositoryImpl implements CustomStudentRepository { + + private static final String DESIGN_DOC = "student"; + + @Autowired + private CouchbaseTemplate template; + + public List findByFirstNameStartsWith(String s) { + return template.findByView(ViewQuery.from(DESIGN_DOC, "byFirstName") + .startKey(s) + .stale(Stale.FALSE), + Student.class); + } +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/PersonRepository.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/PersonRepository.java new file mode 100644 index 0000000000..14b77759e3 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/PersonRepository.java @@ -0,0 +1,11 @@ +package org.baeldung.spring.data.couchbase.repos; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Person; +import org.springframework.data.repository.CrudRepository; + +public interface PersonRepository extends CrudRepository { + List findByFirstName(String firstName); + List findByLastName(String lastName); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/StudentRepository.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/StudentRepository.java new file mode 100644 index 0000000000..331ddc553d --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/repos/StudentRepository.java @@ -0,0 +1,11 @@ +package org.baeldung.spring.data.couchbase.repos; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Student; +import org.springframework.data.repository.CrudRepository; + +public interface StudentRepository extends CrudRepository, CustomStudentRepository { + List findByFirstName(String firstName); + List findByLastName(String lastName); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryService.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryService.java new file mode 100644 index 0000000000..90cc36780a --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryService.java @@ -0,0 +1,58 @@ +package org.baeldung.spring.data.couchbase.service; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Person; +import org.baeldung.spring.data.couchbase.repos.PersonRepository; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +@Qualifier("PersonRepositoryService") +public class PersonRepositoryService implements PersonService { + + private PersonRepository repo; + @Autowired + public void setPersonRepository(PersonRepository repo) { + this.repo = repo; + } + + public Person findOne(String id) { + return repo.findOne(id); + } + + public List findAll() { + List people = new ArrayList(); + Iterator it = repo.findAll().iterator(); + while(it.hasNext()) { + people.add(it.next()); + } + return people; + } + + public List findByFirstName(String firstName) { + return repo.findByFirstName(firstName); + } + + public List findByLastName(String lastName) { + return repo.findByLastName(lastName); + } + + public void create(Person person) { + person.setCreated(DateTime.now()); + repo.save(person); + } + + public void update(Person person) { + person.setUpdated(DateTime.now()); + repo.save(person); + } + + public void delete(Person person) { + repo.delete(person); + } +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/PersonService.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/PersonService.java new file mode 100644 index 0000000000..a823908b01 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/PersonService.java @@ -0,0 +1,22 @@ +package org.baeldung.spring.data.couchbase.service; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Person; + +public interface PersonService { + + Person findOne(String id); + + List findAll(); + + List findByFirstName(String firstName); + + List findByLastName(String lastName); + + void create(Person person); + + void update(Person person); + + void delete(Person person); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/PersonTemplateService.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/PersonTemplateService.java new file mode 100644 index 0000000000..45e9b90a19 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/PersonTemplateService.java @@ -0,0 +1,55 @@ +package org.baeldung.spring.data.couchbase.service; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Person; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.couchbase.core.CouchbaseTemplate; +import org.springframework.stereotype.Service; + +import com.couchbase.client.java.view.ViewQuery; + +@Service +@Qualifier("PersonTemplateService") +public class PersonTemplateService implements PersonService { + + private static final String DESIGN_DOC = "person"; + + private CouchbaseTemplate template; + @Autowired + public void setCouchbaseTemplate(CouchbaseTemplate template) { + this.template = template; + } + + public Person findOne(String id) { + return template.findById(id, Person.class); + } + + public List findAll() { + return template.findByView(ViewQuery.from(DESIGN_DOC, "all"), Person.class); + } + + public List findByFirstName(String firstName) { + return template.findByView(ViewQuery.from(DESIGN_DOC, "byFirstName"), Person.class); + } + + public List findByLastName(String lastName) { + return template.findByView(ViewQuery.from(DESIGN_DOC, "byLastName"), Person.class); + } + + public void create(Person person) { + person.setCreated(DateTime.now()); + template.insert(person); + } + + public void update(Person person) { + person.setUpdated(DateTime.now()); + template.update(person); + } + + public void delete(Person person) { + template.remove(person); + } +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryService.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryService.java new file mode 100644 index 0000000000..58304afc1c --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryService.java @@ -0,0 +1,58 @@ +package org.baeldung.spring.data.couchbase.service; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Student; +import org.baeldung.spring.data.couchbase.repos.StudentRepository; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +@Qualifier("StudentRepositoryService") +public class StudentRepositoryService implements StudentService { + + private StudentRepository repo; + @Autowired + public void setStudentRepository(StudentRepository repo) { + this.repo = repo; + } + + public Student findOne(String id) { + return repo.findOne(id); + } + + public List findAll() { + List people = new ArrayList(); + Iterator it = repo.findAll().iterator(); + while(it.hasNext()) { + people.add(it.next()); + } + return people; + } + + public List findByFirstName(String firstName) { + return repo.findByFirstName(firstName); + } + + public List findByLastName(String lastName) { + return repo.findByLastName(lastName); + } + + public void create(Student student) { + student.setCreated(DateTime.now()); + repo.save(student); + } + + public void update(Student student) { + student.setUpdated(DateTime.now()); + repo.save(student); + } + + public void delete(Student student) { + repo.delete(student); + } +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/StudentService.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/StudentService.java new file mode 100644 index 0000000000..f483ef0fb6 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/StudentService.java @@ -0,0 +1,22 @@ +package org.baeldung.spring.data.couchbase.service; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Student; + +public interface StudentService { + + Student findOne(String id); + + List findAll(); + + List findByFirstName(String firstName); + + List findByLastName(String lastName); + + void create(Student student); + + void update(Student student); + + void delete(Student student); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/StudentTemplateService.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/StudentTemplateService.java new file mode 100644 index 0000000000..c3808e0015 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase/service/StudentTemplateService.java @@ -0,0 +1,55 @@ +package org.baeldung.spring.data.couchbase.service; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Student; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.couchbase.core.CouchbaseTemplate; +import org.springframework.stereotype.Service; + +import com.couchbase.client.java.view.ViewQuery; + +@Service +@Qualifier("StudentTemplateService") +public class StudentTemplateService implements StudentService { + + private static final String DESIGN_DOC = "student"; + + private CouchbaseTemplate template; + @Autowired + public void setCouchbaseTemplate(CouchbaseTemplate template) { + this.template = template; + } + + public Student findOne(String id) { + return template.findById(id, Student.class); + } + + public List findAll() { + return template.findByView(ViewQuery.from(DESIGN_DOC, "all"), Student.class); + } + + public List findByFirstName(String firstName) { + return template.findByView(ViewQuery.from(DESIGN_DOC, "byFirstName"), Student.class); + } + + public List findByLastName(String lastName) { + return template.findByView(ViewQuery.from(DESIGN_DOC, "byLastName"), Student.class); + } + + public void create(Student student) { + student.setCreated(DateTime.now()); + template.insert(student); + } + + public void update(Student student) { + student.setUpdated(DateTime.now()); + template.update(student); + } + + public void delete(Student student) { + template.remove(student); + } +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/repos/CampusRepository.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/repos/CampusRepository.java new file mode 100644 index 0000000000..2cf388f518 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/repos/CampusRepository.java @@ -0,0 +1,19 @@ +package org.baeldung.spring.data.couchbase2b.repos; + +import java.util.Set; + +import org.baeldung.spring.data.couchbase.model.Campus; +import org.springframework.data.couchbase.core.query.Dimensional; +import org.springframework.data.couchbase.core.query.View; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Point; +import org.springframework.data.repository.CrudRepository; + +public interface CampusRepository extends CrudRepository { + + @View(designDocument="campus", viewName="byName") + Set findByName(String name); + + @Dimensional(dimensions=2, designDocument="campus_spatial", spatialViewName="byLocation") + Set findByLocationNear(Point point, Distance distance); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/repos/PersonRepository.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/repos/PersonRepository.java new file mode 100644 index 0000000000..e441bec6e4 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/repos/PersonRepository.java @@ -0,0 +1,11 @@ +package org.baeldung.spring.data.couchbase2b.repos; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Person; +import org.springframework.data.repository.CrudRepository; + +public interface PersonRepository extends CrudRepository { + List findByFirstName(String firstName); + List findByLastName(String lastName); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/repos/StudentRepository.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/repos/StudentRepository.java new file mode 100644 index 0000000000..2a960d37de --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/repos/StudentRepository.java @@ -0,0 +1,11 @@ +package org.baeldung.spring.data.couchbase2b.repos; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Student; +import org.springframework.data.repository.CrudRepository; + +public interface StudentRepository extends CrudRepository { + List findByFirstName(String firstName); + List findByLastName(String lastName); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/CampusService.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/CampusService.java new file mode 100644 index 0000000000..d098c39011 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/CampusService.java @@ -0,0 +1,20 @@ +package org.baeldung.spring.data.couchbase2b.service; + +import java.util.Set; + +import org.baeldung.spring.data.couchbase.model.Campus; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Point; + +public interface CampusService { + + Campus find(String id); + + Set findByName(String name); + + Set findByLocationNear(Point point, Distance distance); + + Set findAll(); + + void save(Campus campus); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImpl.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImpl.java new file mode 100644 index 0000000000..612774fec9 --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImpl.java @@ -0,0 +1,52 @@ +package org.baeldung.spring.data.couchbase2b.service; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.baeldung.spring.data.couchbase.model.Campus; +import org.baeldung.spring.data.couchbase2b.repos.CampusRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Point; +import org.springframework.stereotype.Service; + +@Service +public class CampusServiceImpl implements CampusService { + + private CampusRepository repo; + @Autowired + public void setCampusRepository(CampusRepository repo) { + this.repo = repo; + } + + @Override + public Campus find(String id) { + return repo.findOne(id); + } + + @Override + public Set findByName(String name) { + return repo.findByName(name); + } + + @Override + public Set findByLocationNear(Point point, Distance distance) { + return repo.findByLocationNear(point, distance); + } + + @Override + public Set findAll() { + Set campuses = new HashSet<>(); + Iterator it = repo.findAll().iterator(); + while(it.hasNext()) { + campuses.add(it.next()); + } + return campuses; + } + + @Override + public void save(Campus campus) { + repo.save(campus); + } +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/PersonService.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/PersonService.java new file mode 100644 index 0000000000..c2c96ffb9c --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/PersonService.java @@ -0,0 +1,22 @@ +package org.baeldung.spring.data.couchbase2b.service; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Person; + +public interface PersonService { + + Person findOne(String id); + + List findAll(); + + List findByFirstName(String firstName); + + List findByLastName(String lastName); + + void create(Person person); + + void update(Person person); + + void delete(Person person); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImpl.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImpl.java new file mode 100644 index 0000000000..f1ff513bff --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImpl.java @@ -0,0 +1,56 @@ +package org.baeldung.spring.data.couchbase2b.service; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Person; +import org.baeldung.spring.data.couchbase2b.repos.PersonRepository; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class PersonServiceImpl implements PersonService { + + private PersonRepository repo; + @Autowired + public void setPersonRepository(PersonRepository repo) { + this.repo = repo; + } + + public Person findOne(String id) { + return repo.findOne(id); + } + + public List findAll() { + List people = new ArrayList(); + Iterator it = repo.findAll().iterator(); + while(it.hasNext()) { + people.add(it.next()); + } + return people; + } + + public List findByFirstName(String firstName) { + return repo.findByFirstName(firstName); + } + + public List findByLastName(String lastName) { + return repo.findByLastName(lastName); + } + + public void create(Person person) { + person.setCreated(DateTime.now()); + repo.save(person); + } + + public void update(Person person) { + person.setUpdated(DateTime.now()); + repo.save(person); + } + + public void delete(Person person) { + repo.delete(person); + } +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/StudentService.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/StudentService.java new file mode 100644 index 0000000000..5b83b403bb --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/StudentService.java @@ -0,0 +1,22 @@ +package org.baeldung.spring.data.couchbase2b.service; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Student; + +public interface StudentService { + + Student findOne(String id); + + List findAll(); + + List findByFirstName(String firstName); + + List findByLastName(String lastName); + + void create(Student student); + + void update(Student student); + + void delete(Student student); +} diff --git a/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImpl.java b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImpl.java new file mode 100644 index 0000000000..65400636cf --- /dev/null +++ b/spring-data-couchbase-2/src/main/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImpl.java @@ -0,0 +1,56 @@ +package org.baeldung.spring.data.couchbase2b.service; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Student; +import org.baeldung.spring.data.couchbase2b.repos.StudentRepository; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class StudentServiceImpl implements StudentService { + + private StudentRepository repo; + @Autowired + public void setStudentRepository(StudentRepository repo) { + this.repo = repo; + } + + public Student findOne(String id) { + return repo.findOne(id); + } + + public List findAll() { + List people = new ArrayList(); + Iterator it = repo.findAll().iterator(); + while(it.hasNext()) { + people.add(it.next()); + } + return people; + } + + public List findByFirstName(String firstName) { + return repo.findByFirstName(firstName); + } + + public List findByLastName(String lastName) { + return repo.findByLastName(lastName); + } + + public void create(Student student) { + student.setCreated(DateTime.now()); + repo.save(student); + } + + public void update(Student student) { + student.setUpdated(DateTime.now()); + repo.save(student); + } + + public void delete(Student student) { + repo.delete(student); + } +} diff --git a/spring-data-couchbase-2/src/main/resources/logback.xml b/spring-data-couchbase-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..d9067fd1da --- /dev/null +++ b/spring-data-couchbase-2/src/main/resources/logback.xml @@ -0,0 +1,17 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-couchbase-2/src/site/site.xml b/spring-data-couchbase-2/src/site/site.xml new file mode 100644 index 0000000000..dda96feecd --- /dev/null +++ b/spring-data-couchbase-2/src/site/site.xml @@ -0,0 +1,25 @@ + + + + + Spring Sample: ${project.name} + index.html + + + + org.springframework.maven.skins + maven-spring-skin + 1.0.5 + + + + + + + + + + + + + diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/CustomTypeKeyCouchbaseConfig.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/CustomTypeKeyCouchbaseConfig.java new file mode 100644 index 0000000000..0e2e8d5dd3 --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/CustomTypeKeyCouchbaseConfig.java @@ -0,0 +1,11 @@ +package org.baeldung.spring.data.couchbase; + +import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter; + +public class CustomTypeKeyCouchbaseConfig extends MyCouchbaseConfig { + + @Override + public String typeKey() { + return MappingCouchbaseConverter.TYPEKEY_SYNCGATEWAY_COMPATIBLE; + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/IntegrationTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/IntegrationTest.java new file mode 100644 index 0000000000..ce2daa92cd --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/IntegrationTest.java @@ -0,0 +1,13 @@ +package org.baeldung.spring.data.couchbase; + +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { MyCouchbaseConfig.class, IntegrationTestConfig.class }) +@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class }) +public abstract class IntegrationTest { +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/IntegrationTestConfig.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/IntegrationTestConfig.java new file mode 100644 index 0000000000..6f040c34db --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/IntegrationTestConfig.java @@ -0,0 +1,9 @@ +package org.baeldung.spring.data.couchbase; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages = "org.baeldung.spring.data.couchbase") +public class IntegrationTestConfig { +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/MyCouchbaseConfig.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/MyCouchbaseConfig.java new file mode 100644 index 0000000000..8e6b971dbf --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/MyCouchbaseConfig.java @@ -0,0 +1,51 @@ +package org.baeldung.spring.data.couchbase; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; +import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener; +import org.springframework.data.couchbase.core.query.Consistency; +import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories; +import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; + +@Configuration +@EnableCouchbaseRepositories(basePackages={"org.baeldung.spring.data.couchbase"}) +public class MyCouchbaseConfig extends AbstractCouchbaseConfiguration { + + public static final List NODE_LIST = Arrays.asList("localhost"); + public static final String BUCKET_NAME = "baeldung"; + public static final String BUCKET_PASSWORD = ""; + + @Override + protected List getBootstrapHosts() { + return NODE_LIST; + } + + @Override + protected String getBucketName() { + return BUCKET_NAME; + } + + @Override + protected String getBucketPassword() { + return BUCKET_PASSWORD; + } + + @Override + protected Consistency getDefaultConsistency() { + return Consistency.READ_YOUR_OWN_WRITES; + } + + @Bean + public LocalValidatorFactoryBean localValidatorFactoryBean() { + return new LocalValidatorFactoryBean(); + } + + @Bean + public ValidatingCouchbaseEventListener validatingCouchbaseEventListener() { + return new ValidatingCouchbaseEventListener(localValidatorFactoryBean()); + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/ReadYourOwnWritesCouchbaseConfig.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/ReadYourOwnWritesCouchbaseConfig.java new file mode 100644 index 0000000000..b4a372487e --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/ReadYourOwnWritesCouchbaseConfig.java @@ -0,0 +1,11 @@ +package org.baeldung.spring.data.couchbase; + +import org.springframework.data.couchbase.core.query.Consistency; + +public class ReadYourOwnWritesCouchbaseConfig extends MyCouchbaseConfig { + + @Override + public Consistency getDefaultConsistency() { + return Consistency.READ_YOUR_OWN_WRITES; + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceTest.java new file mode 100644 index 0000000000..ce5cf7667d --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceTest.java @@ -0,0 +1,13 @@ +package org.baeldung.spring.data.couchbase.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +public class PersonRepositoryServiceTest extends PersonServiceTest { + + @Autowired + @Qualifier("PersonRepositoryService") + public void setPersonService(PersonService service) { + this.personService = service; + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonServiceTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonServiceTest.java new file mode 100644 index 0000000000..c3bf9f2138 --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonServiceTest.java @@ -0,0 +1,118 @@ +package org.baeldung.spring.data.couchbase.service; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.IntegrationTest; +import org.baeldung.spring.data.couchbase.MyCouchbaseConfig; +import org.baeldung.spring.data.couchbase.model.Person; +import org.joda.time.DateTime; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.CouchbaseCluster; +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.document.json.JsonObject; + +public abstract class PersonServiceTest extends IntegrationTest { + + static final String typeField = "_class"; + static final String john = "John"; + static final String smith = "Smith"; + static final String johnSmithId = "person:" + john + ":" + smith; + static final Person johnSmith = new Person(johnSmithId, john, smith); + static final JsonObject jsonJohnSmith = JsonObject.empty().put(typeField, Person.class.getName()).put("firstName", john).put("lastName", smith).put("created", DateTime.now().getMillis()); + + static final String foo = "Foo"; + static final String bar = "Bar"; + static final String foobarId = "person:" + foo + ":" + bar; + static final Person foobar = new Person(foobarId, foo, bar); + static final JsonObject jsonFooBar = JsonObject.empty().put(typeField, Person.class.getName()).put("firstName", foo).put("lastName", bar).put("created", DateTime.now().getMillis()); + + PersonService personService; + + @BeforeClass + public static void setupBeforeClass() { + final Cluster cluster = CouchbaseCluster.create(MyCouchbaseConfig.NODE_LIST); + final Bucket bucket = cluster.openBucket(MyCouchbaseConfig.BUCKET_NAME, MyCouchbaseConfig.BUCKET_PASSWORD); + bucket.upsert(JsonDocument.create(johnSmithId, jsonJohnSmith)); + bucket.upsert(JsonDocument.create(foobarId, jsonFooBar)); + bucket.close(); + cluster.disconnect(); + } + + @Test + public void whenFindingPersonByJohnSmithId_thenReturnsJohnSmith() { + final Person actualPerson = personService.findOne(johnSmithId); + assertNotNull(actualPerson); + assertNotNull(actualPerson.getCreated()); + assertEquals(johnSmith, actualPerson); + } + + @Test + public void whenFindingAllPersons_thenReturnsTwoOrMorePersonsIncludingJohnSmithAndFooBar() { + final List resultList = personService.findAll(); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(resultContains(resultList, johnSmith)); + assertTrue(resultContains(resultList, foobar)); + assertTrue(resultList.size() >= 2); + } + + @Test + public void whenFindingByFirstNameJohn_thenReturnsOnlyPersonsNamedJohn() { + final String expectedFirstName = john; + final List resultList = personService.findByFirstName(expectedFirstName); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(allResultsContainExpectedFirstName(resultList, expectedFirstName)); + } + + @Test + public void whenFindingByLastNameSmith_thenReturnsOnlyPersonsNamedSmith() { + final String expectedLastName = smith; + final List resultList = personService.findByLastName(expectedLastName); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(allResultsContainExpectedLastName(resultList, expectedLastName)); + } + + private boolean resultContains(List resultList, Person person) { + boolean found = false; + for (final Person p : resultList) { + if (p.equals(person)) { + found = true; + break; + } + } + return found; + } + + private boolean allResultsContainExpectedFirstName(List resultList, String firstName) { + boolean found = false; + for (final Person p : resultList) { + if (p.getFirstName().equals(firstName)) { + found = true; + break; + } + } + return found; + } + + private boolean allResultsContainExpectedLastName(List resultList, String lastName) { + boolean found = false; + for (final Person p : resultList) { + if (p.getLastName().equals(lastName)) { + found = true; + break; + } + } + return found; + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonTemplateServiceTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonTemplateServiceTest.java new file mode 100644 index 0000000000..0238fa21fb --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonTemplateServiceTest.java @@ -0,0 +1,13 @@ +package org.baeldung.spring.data.couchbase.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +public class PersonTemplateServiceTest extends PersonServiceTest { + + @Autowired + @Qualifier("PersonTemplateService") + public void setPersonService(PersonService service) { + this.personService = service; + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceTest.java new file mode 100644 index 0000000000..040453fd73 --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceTest.java @@ -0,0 +1,13 @@ +package org.baeldung.spring.data.couchbase.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +public class StudentRepositoryServiceTest extends StudentServiceTest { + + @Autowired + @Qualifier("StudentRepositoryService") + public void setStudentService(StudentService service) { + this.studentService = service; + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentServiceTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentServiceTest.java new file mode 100644 index 0000000000..79948cbedf --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentServiceTest.java @@ -0,0 +1,166 @@ +package org.baeldung.spring.data.couchbase.service; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import javax.validation.ConstraintViolationException; + +import org.baeldung.spring.data.couchbase.IntegrationTest; +import org.baeldung.spring.data.couchbase.MyCouchbaseConfig; +import org.baeldung.spring.data.couchbase.model.Student; +import org.joda.time.DateTime; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.CouchbaseCluster; +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.document.json.JsonObject; + +public abstract class StudentServiceTest extends IntegrationTest { + + static final String typeField = "_class"; + static final String joe = "Joe"; + static final String college = "College"; + static final String joeCollegeId = "student:" + joe + ":" + college; + static final DateTime joeCollegeDob = DateTime.now().minusYears(21); + static final Student joeCollege = new Student(joeCollegeId, joe, college, joeCollegeDob); + static final JsonObject jsonJoeCollege = JsonObject.empty() + .put(typeField, Student.class.getName()) + .put("firstName", joe) + .put("lastName", college) + .put("created", DateTime.now().getMillis()) + .put("version", 1); + + static final String judy = "Judy"; + static final String jetson = "Jetson"; + static final String judyJetsonId = "student:" + judy + ":" + jetson; + static final DateTime judyJetsonDob = DateTime.now().minusYears(19).minusMonths(5).minusDays(3); + static final Student judyJetson = new Student(judyJetsonId, judy, jetson, judyJetsonDob); + static final JsonObject jsonJudyJetson = JsonObject.empty() + .put(typeField, Student.class.getName()) + .put("firstName", judy) + .put("lastName", jetson) + .put("created", DateTime.now().getMillis()) + .put("version", 1); + + StudentService studentService; + + @BeforeClass + public static void setupBeforeClass() { + Cluster cluster = CouchbaseCluster.create(MyCouchbaseConfig.NODE_LIST); + Bucket bucket = cluster.openBucket(MyCouchbaseConfig.BUCKET_NAME, MyCouchbaseConfig.BUCKET_PASSWORD); + bucket.upsert(JsonDocument.create(joeCollegeId, jsonJoeCollege)); + bucket.upsert(JsonDocument.create(judyJetsonId, jsonJudyJetson)); + bucket.close(); + cluster.disconnect(); + } + + @Test + public void whenCreatingStudent_thenDocumentIsPersisted() { + String firstName = "Eric"; + String lastName = "Stratton"; + DateTime dateOfBirth = DateTime.now().minusYears(25); + String id = "student:" + firstName + ":" + lastName; + Student expectedStudent = new Student(id, firstName, lastName, dateOfBirth); + studentService.create(expectedStudent); + Student actualStudent = studentService.findOne(id); + assertNotNull(actualStudent.getCreated()); + assertNotNull(actualStudent); + assertEquals(expectedStudent.getId(), actualStudent.getId()); + } + + @Test(expected=ConstraintViolationException.class) + public void whenCreatingStudentWithInvalidFirstName_thenConstraintViolationException() { + String firstName = "Er+ic"; + String lastName = "Stratton"; + DateTime dateOfBirth = DateTime.now().minusYears(25); + String id = "student:" + firstName + ":" + lastName; + Student student = new Student(id, firstName, lastName, dateOfBirth); + studentService.create(student); + } + + @Test(expected=ConstraintViolationException.class) + public void whenCreatingStudentWithFutureDob_thenConstraintViolationException() { + String firstName = "Jane"; + String lastName = "Doe"; + DateTime dateOfBirth = DateTime.now().plusDays(1); + String id = "student:" + firstName + ":" + lastName; + Student student = new Student(id, firstName, lastName, dateOfBirth); + studentService.create(student); + } + + @Test + public void whenFindingStudentByJohnSmithId_thenReturnsJohnSmith() { + Student actualStudent = studentService.findOne(joeCollegeId); + assertNotNull(actualStudent); + assertNotNull(actualStudent.getCreated()); + assertEquals(joeCollegeId, actualStudent.getId()); + } + + @Test + public void whenFindingAllStudents_thenReturnsTwoOrMoreStudentsIncludingJoeCollegeAndJudyJetson() { + List resultList = studentService.findAll(); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(resultContains(resultList, joeCollege)); + assertTrue(resultContains(resultList, judyJetson)); + assertTrue(resultList.size() >= 2); + } + + @Test + public void whenFindingByFirstNameJohn_thenReturnsOnlyStudentsNamedJohn() { + String expectedFirstName = joe; + List resultList = studentService.findByFirstName(expectedFirstName); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(allResultsContainExpectedFirstName(resultList, expectedFirstName)); + } + + @Test + public void whenFindingByLastNameSmith_thenReturnsOnlyStudentsNamedSmith() { + String expectedLastName = college; + List resultList = studentService.findByLastName(expectedLastName); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(allResultsContainExpectedLastName(resultList, expectedLastName)); + } + + private boolean resultContains(List resultList, Student student) { + boolean found = false; + for(Student p : resultList) { + if(p.getId().equals(student.getId())) { + found = true; + break; + } + } + return found; + } + + private boolean allResultsContainExpectedFirstName(List resultList, String firstName) { + boolean found = false; + for(Student p : resultList) { + if(p.getFirstName().equals(firstName)) { + found = true; + break; + } + } + return found; + } + + private boolean allResultsContainExpectedLastName(List resultList, String lastName) { + boolean found = false; + for(Student p : resultList) { + if(p.getLastName().equals(lastName)) { + found = true; + break; + } + } + return found; + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentTemplateServiceTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentTemplateServiceTest.java new file mode 100644 index 0000000000..dd5be8e059 --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentTemplateServiceTest.java @@ -0,0 +1,13 @@ +package org.baeldung.spring.data.couchbase.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +public class StudentTemplateServiceTest extends StudentServiceTest { + + @Autowired + @Qualifier("StudentTemplateService") + public void setStudentService(StudentService service) { + this.studentService = service; + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketCouchbaseConfig.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketCouchbaseConfig.java new file mode 100644 index 0000000000..f419ba3499 --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketCouchbaseConfig.java @@ -0,0 +1,81 @@ +package org.baeldung.spring.data.couchbase2b; + +import java.util.Arrays; +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Campus; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; +import org.springframework.data.couchbase.core.CouchbaseTemplate; +import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener; +import org.springframework.data.couchbase.core.query.Consistency; +import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories; +import org.springframework.data.couchbase.repository.config.RepositoryOperationsMapping; +import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; + +import com.couchbase.client.java.Bucket; + +@Configuration +@EnableCouchbaseRepositories(basePackages = { "org.baeldung.spring.data.couchbase2b" }) +public class MultiBucketCouchbaseConfig extends AbstractCouchbaseConfiguration { + + public static final List NODE_LIST = Arrays.asList("localhost"); + public static final String DEFAULT_BUCKET_NAME = "baeldung"; + public static final String DEFAULT_BUCKET_PASSWORD = ""; + + @Override + protected List getBootstrapHosts() { + return NODE_LIST; + } + + @Override + protected String getBucketName() { + return DEFAULT_BUCKET_NAME; + } + + @Override + protected String getBucketPassword() { + return DEFAULT_BUCKET_PASSWORD; + } + + @Bean + public Bucket campusBucket() throws Exception { + return couchbaseCluster().openBucket("baeldung2", ""); + } + + @Bean(name = "campusTemplate") + public CouchbaseTemplate campusTemplate() throws Exception { + CouchbaseTemplate template = new CouchbaseTemplate( + couchbaseClusterInfo(), + campusBucket(), + mappingCouchbaseConverter(), + translationService()); + template.setDefaultConsistency(getDefaultConsistency()); + return template; + } + + @Override + public void configureRepositoryOperationsMapping(RepositoryOperationsMapping baseMapping) { + try { + baseMapping.mapEntity(Campus.class, campusTemplate()); + } catch (Exception e) { + //custom Exception handling + } + } + + @Override + protected Consistency getDefaultConsistency() { + return Consistency.READ_YOUR_OWN_WRITES; + } + + @Bean + public LocalValidatorFactoryBean localValidatorFactoryBean() { + return new LocalValidatorFactoryBean(); + } + + @Bean + public ValidatingCouchbaseEventListener validatingCouchbaseEventListener() { + return new ValidatingCouchbaseEventListener(localValidatorFactoryBean()); + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketIntegationTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketIntegationTest.java new file mode 100644 index 0000000000..cb671dc469 --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketIntegationTest.java @@ -0,0 +1,14 @@ +package org.baeldung.spring.data.couchbase2b; + +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { MultiBucketCouchbaseConfig.class, MultiBucketIntegrationTestConfig.class }) +@TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class }) +public abstract class MultiBucketIntegationTest { + +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketIntegrationTestConfig.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketIntegrationTestConfig.java new file mode 100644 index 0000000000..94a95b06bb --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketIntegrationTestConfig.java @@ -0,0 +1,10 @@ +package org.baeldung.spring.data.couchbase2b; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages = { "org.baeldung.spring.data.couchbase2b" }) +public class MultiBucketIntegrationTestConfig { + +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImplTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImplTest.java new file mode 100644 index 0000000000..7e24952e32 --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImplTest.java @@ -0,0 +1,136 @@ +package org.baeldung.spring.data.couchbase2b.service; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Set; + +import javax.annotation.PostConstruct; + +import org.baeldung.spring.data.couchbase.model.Campus; +import org.baeldung.spring.data.couchbase2b.MultiBucketIntegationTest; +import org.baeldung.spring.data.couchbase2b.repos.CampusRepository; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.geo.Distance; +import org.springframework.data.geo.Metrics; +import org.springframework.data.geo.Point; + +public class CampusServiceImplTest extends MultiBucketIntegationTest { + + @Autowired + private CampusServiceImpl campusService; + + @Autowired + private CampusRepository campusRepo; + + private final Campus Brown = Campus.Builder.newInstance() + .id("campus:Brown") + .name("Brown") + .location(new Point(71.4025, 51.8268)) + .build(); + + private final Campus Cornell = Campus.Builder.newInstance() + .id("campus:Cornell") + .name("Cornell") + .location(new Point(76.4833, 42.4459)) + .build(); + + private final Campus Columbia = Campus.Builder.newInstance() + .id("campus:Columbia") + .name("Columbia") + .location(new Point(73.9626, 40.8075)) + .build(); + + private final Campus Dartmouth = Campus.Builder.newInstance() + .id("campus:Dartmouth") + .name("Dartmouth") + .location(new Point(72.2887, 43.7044)) + .build(); + + private final Campus Harvard = Campus.Builder.newInstance() + .id("campus:Harvard") + .name("Harvard") + .location(new Point(71.1167, 42.3770)) + .build(); + + private final Campus Penn = Campus.Builder.newInstance() + .id("campus:Penn") + .name("Penn") + .location(new Point(75.1932, 39.9522)) + .build(); + + private final Campus Princeton = Campus.Builder.newInstance() + .id("campus:Princeton") + .name("Princeton") + .location(new Point(74.6514, 40.3340)) + .build(); + + private final Campus Yale = Campus.Builder.newInstance() + .id("campus:Yale") + .name("Yale") + .location(new Point(72.9223, 41.3163)) + .build(); + + private final Point Boston = new Point(71.0589, 42.3601); + private final Point NewYorkCity = new Point(74.0059, 40.7128); + + @PostConstruct + private void loadCampuses() throws Exception { + campusRepo.save(Brown); + campusRepo.save(Columbia); + campusRepo.save(Cornell); + campusRepo.save(Dartmouth); + campusRepo.save(Harvard); + campusRepo.save(Penn); + campusRepo.save(Princeton); + campusRepo.save(Yale); + } + + @Test + public final void givenNameHarvard_whenFindByName_thenReturnsHarvard() throws Exception { + Set campuses = campusService.findByName(Harvard.getName()); + assertNotNull(campuses); + assertFalse(campuses.isEmpty()); + assertTrue(campuses.size() == 1); + assertTrue(campuses.contains(Harvard)); + } + + @Test + public final void givenHarvardId_whenFind_thenReturnsHarvard() throws Exception { + Campus actual = campusService.find(Harvard.getId()); + assertNotNull(actual); + assertEquals(Harvard, actual); + } + + @Test + public final void whenFindAll_thenReturnsAll() throws Exception { + Set campuses = campusService.findAll(); + assertTrue(campuses.contains(Brown)); + assertTrue(campuses.contains(Columbia)); + assertTrue(campuses.contains(Cornell)); + assertTrue(campuses.contains(Dartmouth)); + assertTrue(campuses.contains(Harvard)); + assertTrue(campuses.contains(Penn)); + assertTrue(campuses.contains(Princeton)); + assertTrue(campuses.contains(Yale)); + } + + @Test + public final void whenFindByLocationNearBoston_thenResultContainsHarvard() throws Exception { + Set campuses = campusService.findByLocationNear(Boston, new Distance(1, Metrics.NEUTRAL)); + assertFalse(campuses.isEmpty()); + assertTrue(campuses.contains(Harvard)); + assertFalse(campuses.contains(Columbia)); + } + + @Test + public final void whenFindByLocationNearNewYorkCity_thenResultContainsColumbia() throws Exception { + Set campuses = campusService.findByLocationNear(NewYorkCity, new Distance(1, Metrics.NEUTRAL)); + assertFalse(campuses.isEmpty()); + assertTrue(campuses.contains(Columbia)); + assertFalse(campuses.contains(Harvard)); + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImplTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImplTest.java new file mode 100644 index 0000000000..e1a880d9da --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImplTest.java @@ -0,0 +1,120 @@ +package org.baeldung.spring.data.couchbase2b.service; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.baeldung.spring.data.couchbase.model.Person; +import org.baeldung.spring.data.couchbase2b.MultiBucketCouchbaseConfig; +import org.baeldung.spring.data.couchbase2b.MultiBucketIntegationTest; +import org.joda.time.DateTime; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.CouchbaseCluster; +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.document.json.JsonObject; + +public class PersonServiceImplTest extends MultiBucketIntegationTest { + + static final String typeField = "_class"; + static final String john = "John"; + static final String smith = "Smith"; + static final String johnSmithId = "person:" + john + ":" + smith; + static final Person johnSmith = new Person(johnSmithId, john, smith); + static final JsonObject jsonJohnSmith = JsonObject.empty().put(typeField, Person.class.getName()).put("firstName", john).put("lastName", smith).put("created", DateTime.now().getMillis()); + + static final String foo = "Foo"; + static final String bar = "Bar"; + static final String foobarId = "person:" + foo + ":" + bar; + static final Person foobar = new Person(foobarId, foo, bar); + static final JsonObject jsonFooBar = JsonObject.empty().put(typeField, Person.class.getName()).put("firstName", foo).put("lastName", bar).put("created", DateTime.now().getMillis()); + + @Autowired + private PersonServiceImpl personService; + + @BeforeClass + public static void setupBeforeClass() { + final Cluster cluster = CouchbaseCluster.create(MultiBucketCouchbaseConfig.NODE_LIST); + final Bucket bucket = cluster.openBucket(MultiBucketCouchbaseConfig.DEFAULT_BUCKET_NAME, MultiBucketCouchbaseConfig.DEFAULT_BUCKET_PASSWORD); + bucket.upsert(JsonDocument.create(johnSmithId, jsonJohnSmith)); + bucket.upsert(JsonDocument.create(foobarId, jsonFooBar)); + bucket.close(); + cluster.disconnect(); + } + + @Test + public void whenFindingPersonByJohnSmithId_thenReturnsJohnSmith() { + final Person actualPerson = personService.findOne(johnSmithId); + assertNotNull(actualPerson); + assertNotNull(actualPerson.getCreated()); + assertEquals(johnSmith, actualPerson); + } + + @Test + public void whenFindingAllPersons_thenReturnsTwoOrMorePersonsIncludingJohnSmithAndFooBar() { + final List resultList = personService.findAll(); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(resultContains(resultList, johnSmith)); + assertTrue(resultContains(resultList, foobar)); + assertTrue(resultList.size() >= 2); + } + + @Test + public void whenFindingByFirstNameJohn_thenReturnsOnlyPersonsNamedJohn() { + final String expectedFirstName = john; + final List resultList = personService.findByFirstName(expectedFirstName); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(allResultsContainExpectedFirstName(resultList, expectedFirstName)); + } + + @Test + public void whenFindingByLastNameSmith_thenReturnsOnlyPersonsNamedSmith() { + final String expectedLastName = smith; + final List resultList = personService.findByLastName(expectedLastName); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(allResultsContainExpectedLastName(resultList, expectedLastName)); + } + + private boolean resultContains(List resultList, Person person) { + boolean found = false; + for (final Person p : resultList) { + if (p.equals(person)) { + found = true; + break; + } + } + return found; + } + + private boolean allResultsContainExpectedFirstName(List resultList, String firstName) { + boolean found = false; + for (final Person p : resultList) { + if (p.getFirstName().equals(firstName)) { + found = true; + break; + } + } + return found; + } + + private boolean allResultsContainExpectedLastName(List resultList, String lastName) { + boolean found = false; + for (final Person p : resultList) { + if (p.getLastName().equals(lastName)) { + found = true; + break; + } + } + return found; + } +} diff --git a/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImplTest.java b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImplTest.java new file mode 100644 index 0000000000..220c2c3b00 --- /dev/null +++ b/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImplTest.java @@ -0,0 +1,168 @@ +package org.baeldung.spring.data.couchbase2b.service; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import javax.validation.ConstraintViolationException; + +import org.baeldung.spring.data.couchbase.model.Student; +import org.baeldung.spring.data.couchbase2b.MultiBucketCouchbaseConfig; +import org.baeldung.spring.data.couchbase2b.MultiBucketIntegationTest; +import org.joda.time.DateTime; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.CouchbaseCluster; +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.document.json.JsonObject; + +public class StudentServiceImplTest extends MultiBucketIntegationTest { + + static final String typeField = "_class"; + static final String joe = "Joe"; + static final String college = "College"; + static final String joeCollegeId = "student:" + joe + ":" + college; + static final DateTime joeCollegeDob = DateTime.now().minusYears(21); + static final Student joeCollege = new Student(joeCollegeId, joe, college, joeCollegeDob); + static final JsonObject jsonJoeCollege = JsonObject.empty() + .put(typeField, Student.class.getName()) + .put("firstName", joe) + .put("lastName", college) + .put("created", DateTime.now().getMillis()) + .put("version", 1); + + static final String judy = "Judy"; + static final String jetson = "Jetson"; + static final String judyJetsonId = "student:" + judy + ":" + jetson; + static final DateTime judyJetsonDob = DateTime.now().minusYears(19).minusMonths(5).minusDays(3); + static final Student judyJetson = new Student(judyJetsonId, judy, jetson, judyJetsonDob); + static final JsonObject jsonJudyJetson = JsonObject.empty() + .put(typeField, Student.class.getName()) + .put("firstName", judy) + .put("lastName", jetson) + .put("created", DateTime.now().getMillis()) + .put("version", 1); + + @Autowired + StudentServiceImpl studentService; + + @BeforeClass + public static void setupBeforeClass() { + Cluster cluster = CouchbaseCluster.create(MultiBucketCouchbaseConfig.NODE_LIST); + Bucket bucket = cluster.openBucket(MultiBucketCouchbaseConfig.DEFAULT_BUCKET_NAME, MultiBucketCouchbaseConfig.DEFAULT_BUCKET_PASSWORD); + bucket.upsert(JsonDocument.create(joeCollegeId, jsonJoeCollege)); + bucket.upsert(JsonDocument.create(judyJetsonId, jsonJudyJetson)); + bucket.close(); + cluster.disconnect(); + } + + @Test + public void whenCreatingStudent_thenDocumentIsPersisted() { + String firstName = "Eric"; + String lastName = "Stratton"; + DateTime dateOfBirth = DateTime.now().minusYears(25); + String id = "student:" + firstName + ":" + lastName; + Student expectedStudent = new Student(id, firstName, lastName, dateOfBirth); + studentService.create(expectedStudent); + Student actualStudent = studentService.findOne(id); + assertNotNull(actualStudent.getCreated()); + assertNotNull(actualStudent); + assertEquals(expectedStudent.getId(), actualStudent.getId()); + } + + @Test(expected=ConstraintViolationException.class) + public void whenCreatingStudentWithInvalidFirstName_thenConstraintViolationException() { + String firstName = "Er+ic"; + String lastName = "Stratton"; + DateTime dateOfBirth = DateTime.now().minusYears(25); + String id = "student:" + firstName + ":" + lastName; + Student student = new Student(id, firstName, lastName, dateOfBirth); + studentService.create(student); + } + + @Test(expected=ConstraintViolationException.class) + public void whenCreatingStudentWithFutureDob_thenConstraintViolationException() { + String firstName = "Jane"; + String lastName = "Doe"; + DateTime dateOfBirth = DateTime.now().plusDays(1); + String id = "student:" + firstName + ":" + lastName; + Student student = new Student(id, firstName, lastName, dateOfBirth); + studentService.create(student); + } + + @Test + public void whenFindingStudentByJohnSmithId_thenReturnsJohnSmith() { + Student actualStudent = studentService.findOne(joeCollegeId); + assertNotNull(actualStudent); + assertNotNull(actualStudent.getCreated()); + assertEquals(joeCollegeId, actualStudent.getId()); + } + + @Test + public void whenFindingAllStudents_thenReturnsTwoOrMoreStudentsIncludingJoeCollegeAndJudyJetson() { + List resultList = studentService.findAll(); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(resultContains(resultList, joeCollege)); + assertTrue(resultContains(resultList, judyJetson)); + assertTrue(resultList.size() >= 2); + } + + @Test + public void whenFindingByFirstNameJohn_thenReturnsOnlyStudentsNamedJohn() { + String expectedFirstName = joe; + List resultList = studentService.findByFirstName(expectedFirstName); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(allResultsContainExpectedFirstName(resultList, expectedFirstName)); + } + + @Test + public void whenFindingByLastNameSmith_thenReturnsOnlyStudentsNamedSmith() { + String expectedLastName = college; + List resultList = studentService.findByLastName(expectedLastName); + assertNotNull(resultList); + assertFalse(resultList.isEmpty()); + assertTrue(allResultsContainExpectedLastName(resultList, expectedLastName)); + } + + private boolean resultContains(List resultList, Student student) { + boolean found = false; + for(Student p : resultList) { + if(p.getId().equals(student.getId())) { + found = true; + break; + } + } + return found; + } + + private boolean allResultsContainExpectedFirstName(List resultList, String firstName) { + boolean found = false; + for(Student p : resultList) { + if(p.getFirstName().equals(firstName)) { + found = true; + break; + } + } + return found; + } + + private boolean allResultsContainExpectedLastName(List resultList, String lastName) { + boolean found = false; + for(Student p : resultList) { + if(p.getLastName().equals(lastName)) { + found = true; + break; + } + } + return found; + } +} diff --git a/spring-data-couchbase-2/src/test/resources/logback.xml b/spring-data-couchbase-2/src/test/resources/logback.xml new file mode 100644 index 0000000000..d9067fd1da --- /dev/null +++ b/spring-data-couchbase-2/src/test/resources/logback.xml @@ -0,0 +1,17 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-elasticsearch/README.md b/spring-data-elasticsearch/README.md new file mode 100644 index 0000000000..74d9e4f642 --- /dev/null +++ b/spring-data-elasticsearch/README.md @@ -0,0 +1,13 @@ +## Spring Data Elasticsearch +- [Introduction to Spring Data Elasticsearch](http://www.baeldung.com/spring-data-elasticsearch-tutorial) + +### Build the Project with Tests Running +``` +mvn clean install +``` + +### Run Tests Directly +``` +mvn test +``` + diff --git a/spring-data-elasticsearch/pom.xml b/spring-data-elasticsearch/pom.xml new file mode 100644 index 0000000000..084695c2f3 --- /dev/null +++ b/spring-data-elasticsearch/pom.xml @@ -0,0 +1,96 @@ + + 4.0.0 + + com.baeldung + spring-data-elasticsearch + 0.0.1-SNAPSHOT + jar + + spring-data-elasticsearch + + + UTF-8 + + 1.3.2.RELEASE + 4.2.5.RELEASE + + 4.11 + 1.7.12 + 1.1.3 + 2.0.1.RELEASE + + + + + org.springframework + spring-core + ${org.springframework.version} + + + junit + junit-dep + ${junit.version} + test + + + org.springframework + spring-test + ${org.springframework.version} + test + + + org.springframework.data + spring-data-elasticsearch + ${elasticsearch.version} + + net.java.dev.jna + jna + 4.1.0 + test + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + + org.elasticsearch + elasticsearch + 2.3.5 + + + com.alibaba + fastjson + 1.2.13 + + + + + + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + + + + + diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/elasticsearch/Person.java b/spring-data-elasticsearch/src/main/java/com/baeldung/elasticsearch/Person.java new file mode 100644 index 0000000000..b8ad59e2e2 --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/elasticsearch/Person.java @@ -0,0 +1,52 @@ +package com.baeldung.elasticsearch; + +import java.util.Date; + +public class Person { + + private int age; + + private String fullName; + + private Date dateOfBirth; + + public Person() { + + } + + public Person(int age, String fullName, Date dateOfBirth) { + super(); + this.age = age; + this.fullName = fullName; + this.dateOfBirth = dateOfBirth; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public Date getDateOfBirth() { + return dateOfBirth; + } + + public void setDateOfBirth(Date dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } + + @Override + public String toString() { + return "Person [age=" + age + ", fullName=" + fullName + ", dateOfBirth=" + dateOfBirth + "]"; + } +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java new file mode 100644 index 0000000000..f93999a1cc --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java @@ -0,0 +1,57 @@ +package com.baeldung.spring.data.es.config; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.elasticsearch.client.Client; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.node.NodeBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; + +@Configuration +@EnableElasticsearchRepositories(basePackages = "com.baeldung.spring.data.es.repository") +@ComponentScan(basePackages = { "com.baeldung.spring.data.es.service" }) +public class Config { + + @Value("${elasticsearch.home:/usr/local/Cellar/elasticsearch/2.3.2}") + private String elasticsearchHome; + + private static Logger logger = LoggerFactory.getLogger(Config.class); + + @Bean + public Client client() { + try { + final Path tmpDir = Files.createTempDirectory(Paths.get(System.getProperty("java.io.tmpdir")), "elasticsearch_data"); + + // @formatter:off + + final Settings.Builder elasticsearchSettings = + Settings.settingsBuilder().put("http.enabled", "false") + .put("path.data", tmpDir.toAbsolutePath().toString()) + .put("path.home", elasticsearchHome); + // @formatter:on + + logger.debug(tmpDir.toAbsolutePath().toString()); + + return new NodeBuilder().local(true).settings(elasticsearchSettings.build()).node().client(); + } catch (final IOException ioex) { + logger.error("Cannot create temp dir", ioex); + throw new RuntimeException(); + } + } + + @Bean + public ElasticsearchOperations elasticsearchTemplate() { + return new ElasticsearchTemplate(client()); + } +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Article.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Article.java new file mode 100644 index 0000000000..01330a6c9c --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Article.java @@ -0,0 +1,74 @@ +package com.baeldung.spring.data.es.model; + +import static org.springframework.data.elasticsearch.annotations.FieldIndex.not_analyzed; +import static org.springframework.data.elasticsearch.annotations.FieldType.Nested; +import static org.springframework.data.elasticsearch.annotations.FieldType.String; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.InnerField; +import org.springframework.data.elasticsearch.annotations.MultiField; + +@Document(indexName = "blog", type = "article") +public class Article { + + @Id + private String id; + + @MultiField(mainField = @Field(type = String), otherFields = { @InnerField(index = not_analyzed, suffix = "verbatim", type = String) }) + private String title; + + @Field(type = Nested) + private List authors; + + @Field(type = String, index = not_analyzed) + private String[] tags; + + public Article() { + } + + public Article(String title) { + this.title = title; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getAuthors() { + return authors; + } + + public void setAuthors(List authors) { + this.authors = authors; + } + + public String[] getTags() { + return tags; + } + + public void setTags(String... tags) { + this.tags = tags; + } + + @Override + public String toString() { + return "Article{" + "id='" + id + '\'' + ", title='" + title + '\'' + ", authors=" + authors + ", tags=" + Arrays.toString(tags) + '}'; + } +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Author.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Author.java new file mode 100644 index 0000000000..38f50e1614 --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Author.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.data.es.model; + +public class Author { + + private String name; + + public Author() { + } + + public Author(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Author{" + "name='" + name + '\'' + '}'; + } +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/repository/ArticleRepository.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/repository/ArticleRepository.java new file mode 100644 index 0000000000..8aef865401 --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/repository/ArticleRepository.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.data.es.repository; + +import com.baeldung.spring.data.es.model.Article; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.annotations.Query; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ArticleRepository extends ElasticsearchRepository { + + Page
    findByAuthorsName(String name, Pageable pageable); + + @Query("{\"bool\": {\"must\": [{\"match\": {\"authors.name\": \"?0\"}}]}}") + Page
    findByAuthorsNameUsingCustomQuery(String name, Pageable pageable); +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleService.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleService.java new file mode 100644 index 0000000000..b5a8fde633 --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleService.java @@ -0,0 +1,21 @@ +package com.baeldung.spring.data.es.service; + +import com.baeldung.spring.data.es.model.Article; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface ArticleService { + Article save(Article article); + + Article findOne(String id); + + Iterable
    findAll(); + + Page
    findByAuthorName(String name, Pageable pageable); + + Page
    findByAuthorNameUsingCustomQuery(String name, Pageable pageable); + + long count(); + + void delete(Article article); +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleServiceImpl.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleServiceImpl.java new file mode 100644 index 0000000000..0ea922bdd3 --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleServiceImpl.java @@ -0,0 +1,54 @@ +package com.baeldung.spring.data.es.service; + +import com.baeldung.spring.data.es.repository.ArticleRepository; +import com.baeldung.spring.data.es.model.Article; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +public class ArticleServiceImpl implements ArticleService { + + private ArticleRepository articleRepository; + + @Autowired + public void setArticleRepository(ArticleRepository articleRepository) { + this.articleRepository = articleRepository; + } + + @Override + public Article save(Article article) { + return articleRepository.save(article); + } + + @Override + public Article findOne(String id) { + return articleRepository.findOne(id); + } + + @Override + public Iterable
    findAll() { + return articleRepository.findAll(); + } + + @Override + public Page
    findByAuthorName(String name, Pageable pageable) { + return articleRepository.findByAuthorsName(name, pageable); + } + + @Override + public Page
    findByAuthorNameUsingCustomQuery(String name, Pageable pageable) { + return articleRepository.findByAuthorsNameUsingCustomQuery(name, pageable); + } + + @Override + public long count() { + return articleRepository.count(); + } + + @Override + public void delete(Article article) { + articleRepository.delete(article); + } +} diff --git a/spring-data-elasticsearch/src/main/resources/logback.xml b/spring-data-elasticsearch/src/main/resources/logback.xml new file mode 100644 index 0000000000..37a9e2edbf --- /dev/null +++ b/spring-data-elasticsearch/src/main/resources/logback.xml @@ -0,0 +1,20 @@ + + + + + elasticsearch - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchUnitTests.java b/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchUnitTests.java new file mode 100644 index 0000000000..db304ee78d --- /dev/null +++ b/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchUnitTests.java @@ -0,0 +1,127 @@ +package com.baeldung.elasticsearch; + +import static org.elasticsearch.node.NodeBuilder.*; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import org.elasticsearch.action.delete.DeleteResponse; +import org.elasticsearch.action.index.IndexResponse; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.search.SearchType; +import org.elasticsearch.client.Client; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.node.Node; +import org.elasticsearch.search.SearchHit; +import org.junit.Before; +import org.junit.Test; + +import com.alibaba.fastjson.JSON; + +public class ElasticSearchUnitTests { + private List listOfPersons = new ArrayList(); + String jsonString = null; + Client client = null; + + @Before + public void setUp() { + Person person1 = new Person(10, "John Doe", new Date()); + Person person2 = new Person(25, "Janette Doe", new Date()); + listOfPersons.add(person1); + listOfPersons.add(person2); + jsonString = JSON.toJSONString(listOfPersons); + Node node = nodeBuilder().clusterName("elasticsearch").client(true).node(); + client = node.client(); + } + + @Test + public void givenJsonString_whenJavaObject_thenIndexDocument() { + String jsonObject = "{\"age\":20,\"dateOfBirth\":1471466076564,\"fullName\":\"John Doe\"}"; + IndexResponse response = client.prepareIndex("people", "Doe") + .setSource(jsonObject).get(); + String index = response.getIndex(); + String type = response.getType(); + assertTrue(response.isCreated()); + assertEquals(index, "people"); + assertEquals(type, "Doe"); + } + + @Test + public void givenDocumentId_whenJavaObject_thenDeleteDocument() { + String jsonObject = "{\"age\":10,\"dateOfBirth\":1471455886564,\"fullName\":\"Johan Doe\"}"; + IndexResponse response = client.prepareIndex("people", "Doe") + .setSource(jsonObject).get(); + String id = response.getId(); + DeleteResponse deleteResponse = client.prepareDelete("people", "Doe", id).get(); + assertTrue(deleteResponse.isFound()); + } + + @Test + public void givenSearchRequest_whenMatchAll_thenReturnAllResults() { + SearchResponse response = client.prepareSearch().execute().actionGet(); + SearchHit[] searchHits = response.getHits().getHits(); + List results = new ArrayList(); + for (SearchHit hit : searchHits) { + String sourceAsString = hit.getSourceAsString(); + Person person = JSON.parseObject(sourceAsString, Person.class); + results.add(person); + } + } + + @Test + public void givenSearchParamters_thenReturnResults() { + boolean isExecutedSuccessfully = true; + SearchResponse response = client.prepareSearch() + .setTypes() + .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) + .setPostFilter(QueryBuilders.rangeQuery("age").from(5).to(15)) + .setFrom(0).setSize(60).setExplain(true) + .execute() + .actionGet(); + + SearchResponse response2 = client.prepareSearch() + .setTypes() + .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) + .setPostFilter(QueryBuilders.simpleQueryStringQuery("+John -Doe OR Janette")) + .setFrom(0).setSize(60).setExplain(true) + .execute() + .actionGet(); + + SearchResponse response3 = client.prepareSearch() + .setTypes() + .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) + .setPostFilter(QueryBuilders.matchQuery("John", "Name*")) + .setFrom(0).setSize(60).setExplain(true) + .execute() + .actionGet(); + try { + response2.getHits(); + response3.getHits(); + List searchHits = Arrays.asList(response.getHits().getHits()); + final List results = new ArrayList(); + searchHits.forEach(hit -> results.add(JSON.parseObject(hit.getSourceAsString(), Person.class))); + } catch (Exception e) { + isExecutedSuccessfully = false; + } + assertTrue(isExecutedSuccessfully); + } + + @Test + public void givenContentBuilder_whenHelpers_thanIndexJson() throws IOException { + XContentBuilder builder = XContentFactory.jsonBuilder() + .startObject() + .field("fullName", "Test") + .field("salary", "11500") + .field("age", "10") + .endObject(); + IndexResponse response = client.prepareIndex("people", "Doe") + .setSource(builder).get(); + assertTrue(response.isCreated()); + } +} diff --git a/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryTest.java b/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryTest.java new file mode 100644 index 0000000000..1551d6442e --- /dev/null +++ b/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryTest.java @@ -0,0 +1,178 @@ +package com.baeldung.spring.data.es; + +import static java.util.Arrays.asList; +import static java.util.stream.Collectors.toList; +import static org.elasticsearch.index.query.MatchQueryBuilder.Operator.AND; +import static org.elasticsearch.index.query.QueryBuilders.boolQuery; +import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery; +import static org.elasticsearch.index.query.QueryBuilders.matchQuery; +import static org.elasticsearch.index.query.QueryBuilders.multiMatchQuery; +import static org.elasticsearch.index.query.QueryBuilders.nestedQuery; +import static org.elasticsearch.index.query.QueryBuilders.termQuery; +import static org.junit.Assert.assertEquals; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.common.unit.Fuzziness; +import org.elasticsearch.index.query.MultiMatchQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.AggregationBuilders; +import org.elasticsearch.search.aggregations.bucket.terms.StringTerms; +import org.elasticsearch.search.aggregations.bucket.terms.Terms; +import org.elasticsearch.search.aggregations.bucket.terms.TermsBuilder; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.core.query.SearchQuery; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.spring.data.es.config.Config; +import com.baeldung.spring.data.es.model.Article; +import com.baeldung.spring.data.es.model.Author; +import com.baeldung.spring.data.es.service.ArticleService; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { Config.class }, loader = AnnotationConfigContextLoader.class) +public class ElasticSearchQueryTest { + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + @Autowired + private ArticleService articleService; + + @Autowired + private Client client; + + private final Author johnSmith = new Author("John Smith"); + private final Author johnDoe = new Author("John Doe"); + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(Article.class); + elasticsearchTemplate.createIndex(Article.class); + elasticsearchTemplate.putMapping(Article.class); + elasticsearchTemplate.refresh(Article.class); + + Article article = new Article("Spring Data Elasticsearch"); + article.setAuthors(asList(johnSmith, johnDoe)); + article.setTags("elasticsearch", "spring data"); + articleService.save(article); + + article = new Article("Search engines"); + article.setAuthors(asList(johnDoe)); + article.setTags("search engines", "tutorial"); + articleService.save(article); + + article = new Article("Second Article About Elasticsearch"); + article.setAuthors(asList(johnSmith)); + article.setTags("elasticsearch", "spring data"); + articleService.save(article); + + article = new Article("Elasticsearch Tutorial"); + article.setAuthors(asList(johnDoe)); + article.setTags("elasticsearch"); + articleService.save(article); + } + + @Test + public void givenFullTitle_whenRunMatchQuery_thenDocIsFound() { + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "Search engines").operator(AND)).build(); + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(1, articles.size()); + } + + @Test + public void givenOneTermFromTitle_whenRunMatchQuery_thenDocIsFound() { + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "Engines Solutions")).build(); + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(1, articles.size()); + assertEquals("Search engines", articles.get(0).getTitle()); + } + + @Test + public void givenPartTitle_whenRunMatchQuery_thenDocIsFound() { + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "elasticsearch data")).build(); + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(3, articles.size()); + } + + @Test + public void givenFullTitle_whenRunMatchQueryOnVerbatimField_thenDocIsFound() { + SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title.verbatim", "Second Article About Elasticsearch")).build(); + List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(1, articles.size()); + + searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title.verbatim", "Second Article About")).build(); + articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(0, articles.size()); + } + + @Test + public void givenNestedObject_whenQueryByAuthorsName_thenFoundArticlesByThatAuthor() { + final QueryBuilder builder = nestedQuery("authors", boolQuery().must(termQuery("authors.name", "smith"))); + + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build(); + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + + assertEquals(2, articles.size()); + } + + @Test + public void givenAnalyzedQuery_whenMakeAggregationOnTermCount_thenEachTokenCountsSeparately() { + final TermsBuilder aggregation = AggregationBuilders.terms("top_tags").field("title"); + final SearchResponse response = client.prepareSearch("blog").setTypes("article").addAggregation(aggregation).execute().actionGet(); + + final Map results = response.getAggregations().asMap(); + final StringTerms topTags = (StringTerms) results.get("top_tags"); + + final List keys = topTags.getBuckets().stream().map(b -> b.getKeyAsString()).collect(toList()); + Collections.sort(keys); + assertEquals(asList("about", "article", "data", "elasticsearch", "engines", "search", "second", "spring", "tutorial"), keys); + } + + @Test + public void givenNotAnalyzedQuery_whenMakeAggregationOnTermCount_thenEachTermCountsIndividually() { + final TermsBuilder aggregation = AggregationBuilders.terms("top_tags").field("tags").order(Terms.Order.aggregation("_count", false)); + final SearchResponse response = client.prepareSearch("blog").setTypes("article").addAggregation(aggregation).execute().actionGet(); + + final Map results = response.getAggregations().asMap(); + final StringTerms topTags = (StringTerms) results.get("top_tags"); + + final List keys = topTags.getBuckets().stream().map(b -> b.getKeyAsString()).collect(toList()); + assertEquals(asList("elasticsearch", "spring data", "search engines", "tutorial"), keys); + } + + @Test + public void givenNotExactPhrase_whenUseSlop_thenQueryMatches() { + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchPhraseQuery("title", "spring elasticsearch").slop(1)).build(); + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(1, articles.size()); + } + + @Test + public void givenPhraseWithType_whenUseFuzziness_thenQueryMatches() { + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "spring date elasticserch").operator(AND).fuzziness(Fuzziness.ONE).prefixLength(3)).build(); + + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(1, articles.size()); + } + + @Test + public void givenMultimatchQuery_whenDoSearch_thenAllProvidedFieldsMatch() { + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(multiMatchQuery("tutorial").field("title").field("tags").type(MultiMatchQueryBuilder.Type.BEST_FIELDS)).build(); + + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(2, articles.size()); + } +} diff --git a/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchTest.java b/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchTest.java new file mode 100644 index 0000000000..e10b5f48d7 --- /dev/null +++ b/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchTest.java @@ -0,0 +1,132 @@ +package com.baeldung.spring.data.es; + +import static java.util.Arrays.asList; +import static org.elasticsearch.index.query.MatchQueryBuilder.Operator.AND; +import static org.elasticsearch.index.query.QueryBuilders.fuzzyQuery; +import static org.elasticsearch.index.query.QueryBuilders.matchQuery; +import static org.elasticsearch.index.query.QueryBuilders.regexpQuery; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.core.query.SearchQuery; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.spring.data.es.config.Config; +import com.baeldung.spring.data.es.model.Article; +import com.baeldung.spring.data.es.model.Author; +import com.baeldung.spring.data.es.service.ArticleService; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { Config.class }, loader = AnnotationConfigContextLoader.class) +public class ElasticSearchTest { + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + @Autowired + private ArticleService articleService; + + private final Author johnSmith = new Author("John Smith"); + private final Author johnDoe = new Author("John Doe"); + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(Article.class); + elasticsearchTemplate.createIndex(Article.class); + + Article article = new Article("Spring Data Elasticsearch"); + article.setAuthors(asList(johnSmith, johnDoe)); + articleService.save(article); + + article = new Article("Search engines"); + article.setAuthors(asList(johnDoe)); + articleService.save(article); + + article = new Article("Second Article About Elasticsearch"); + article.setAuthors(asList(johnSmith)); + articleService.save(article); + } + + @Test + public void givenArticleService_whenSaveArticle_thenIdIsAssigned() { + final List authors = asList(new Author("John Smith"), johnDoe); + + Article article = new Article("Making Search Elastic"); + article.setAuthors(authors); + + article = articleService.save(article); + assertNotNull(article.getId()); + } + + @Test + public void givenPersistedArticles_whenSearchByAuthorsName_thenRightFound() { + + final Page
    articleByAuthorName = articleService.findByAuthorName(johnSmith.getName(), new PageRequest(0, 10)); + assertEquals(2L, articleByAuthorName.getTotalElements()); + } + + @Test + public void givenCustomQuery_whenSearchByAuthorsName_thenArticleIsFound() { + + final Page
    articleByAuthorName = articleService.findByAuthorNameUsingCustomQuery("John Smith", new PageRequest(0, 10)); + assertEquals(3L, articleByAuthorName.getTotalElements()); + } + + @Test + public void givenPersistedArticles_whenUseRegexQuery_thenRightArticlesFound() { + + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withFilter(regexpQuery("title", ".*data.*")).build(); + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + + assertEquals(1, articles.size()); + } + + @Test + public void givenSavedDoc_whenTitleUpdated_thenCouldFindByUpdatedTitle() { + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(fuzzyQuery("title", "serch")).build(); + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + + assertEquals(1, articles.size()); + + final Article article = articles.get(0); + final String newTitle = "Getting started with Search Engines"; + article.setTitle(newTitle); + articleService.save(article); + + assertEquals(newTitle, articleService.findOne(article.getId()).getTitle()); + } + + @Test + public void givenSavedDoc_whenDelete_thenRemovedFromIndex() { + + final String articleTitle = "Spring Data Elasticsearch"; + + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", articleTitle).minimumShouldMatch("75%")).build(); + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(1, articles.size()); + final long count = articleService.count(); + + articleService.delete(articles.get(0)); + + assertEquals(count - 1, articleService.count()); + } + + @Test + public void givenSavedDoc_whenOneTermMatches_thenFindByTitle() { + final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "Search engines").operator(AND)).build(); + final List
    articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(1, articles.size()); + } +} diff --git a/spring-data-mongodb/.classpath b/spring-data-mongodb/.classpath deleted file mode 100644 index baf7c98131..0000000000 --- a/spring-data-mongodb/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-data-mongodb/.project b/spring-data-mongodb/.project deleted file mode 100644 index 2e5a0d4bac..0000000000 --- a/spring-data-mongodb/.project +++ /dev/null @@ -1,29 +0,0 @@ - - - spring-data-mongodb - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - diff --git a/spring-data-mongodb/README.md b/spring-data-mongodb/README.md new file mode 100644 index 0000000000..d656bc897c --- /dev/null +++ b/spring-data-mongodb/README.md @@ -0,0 +1,11 @@ +========= + +## Spring Data MongoDB + + +### Relevant Articles: +- [A Guide to Queries in Spring Data MongoDB](http://www.baeldung.com/queries-in-spring-data-mongodb) +- [Spring Data MongoDB – Indexes, Annotations and Converters](http://www.baeldung.com/spring-data-mongodb-index-annotations-converter) +- [Custom Cascading in Spring Data MongoDB](http://www.baeldung.com/cascading-with-dbref-and-lifecycle-events-in-spring-data-mongodb) +- [GridFS in Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-gridfs) +- [Introduction to Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-tutorial) diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 558af930b3..102344a3fa 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -1,7 +1,7 @@ 4.0.0 - org.baeldung + com.baeldung spring-data-mongodb 0.0.1-SNAPSHOT @@ -118,13 +118,13 @@ UTF-8 - 4.2.4.RELEASE + 4.2.5.RELEASE 1.7.1.RELEASE 1.3 4.11 - 2.4.1 + 2.9.0 3.6.6 1.1.3 diff --git a/spring-data-mongodb/src/main/java/org/baeldung/converter/UserWriterConverter.java b/spring-data-mongodb/src/main/java/org/baeldung/converter/UserWriterConverter.java index 54fa78e2d0..2dedda46ec 100644 --- a/spring-data-mongodb/src/main/java/org/baeldung/converter/UserWriterConverter.java +++ b/spring-data-mongodb/src/main/java/org/baeldung/converter/UserWriterConverter.java @@ -9,6 +9,7 @@ import com.mongodb.DBObject; @Component public class UserWriterConverter implements Converter { + @Override public DBObject convert(final User user) { final DBObject dbObject = new BasicDBObject(); @@ -22,4 +23,5 @@ public class UserWriterConverter implements Converter { dbObject.removeField("_class"); return dbObject; } + } diff --git a/spring-data-neo4j/README.md b/spring-data-neo4j/README.md new file mode 100644 index 0000000000..0f13d9dbc9 --- /dev/null +++ b/spring-data-neo4j/README.md @@ -0,0 +1,15 @@ +## Spring Data Neo4j + +### Relevant Articles: +- [Introduction to Spring Data Neo4j](http://www.baeldung.com/spring-data-neo4j-intro) + +### Build the Project with Tests Running +``` +mvn clean install +``` + +### Run Tests Directly +``` +mvn test +``` + diff --git a/spring-data-neo4j/pom.xml b/spring-data-neo4j/pom.xml new file mode 100644 index 0000000000..b0cf62ef2e --- /dev/null +++ b/spring-data-neo4j/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + com.baeldung + spring-data-neo4j + 1.0 + jar + + + 1.8 + UTF-8 + UTF-8 + 3.0.1 + 4.1.1.RELEASE + + + + + org.springframework.data + spring-data-neo4j + ${spring-data-neo4j.version} + + + + com.voodoodyne.jackson.jsog + jackson-jsog + 1.1 + compile + + + + org.springframework.boot + spring-boot-starter-test + 1.3.6.RELEASE + test + + + + org.springframework.data + spring-data-neo4j + ${spring-data-neo4j.version} + test-jar + + + + org.neo4j + neo4j-kernel + ${neo4j.version} + test-jar + + + + org.neo4j.app + neo4j-server + ${neo4j.version} + test-jar + + + + org.neo4j + neo4j-ogm-test + 2.0.2 + test + + + + org.neo4j.test + neo4j-harness + ${neo4j.version} + test + + + junit + junit + 4.12 + + + org.springframework + spring-test + 4.2.3.RELEASE + + + + + + + + maven-compiler-plugin + + + + + diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jConfiguration.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jConfiguration.java new file mode 100644 index 0000000000..ac9a7260be --- /dev/null +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jConfiguration.java @@ -0,0 +1,34 @@ +package com.baeldung.spring.data.neo4j.config; + +import org.neo4j.ogm.session.SessionFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.neo4j.config.Neo4jConfiguration; +import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + + +@ComponentScan(basePackages = {"com.baeldung.spring.data.neo4j.services"}) +@Configuration +@EnableNeo4jRepositories(basePackages = "com.baeldung.spring.data.neo4j.repostory") +public class MovieDatabaseNeo4jConfiguration extends Neo4jConfiguration { + + public static final String URL = System.getenv("NEO4J_URL") != null ? System.getenv("NEO4J_URL") : "http://neo4j:movies@localhost:7474"; + + @Bean + public org.neo4j.ogm.config.Configuration getConfiguration() { + org.neo4j.ogm.config.Configuration config = new org.neo4j.ogm.config.Configuration(); + config + .driverConfiguration() + .setDriverClassName("org.neo4j.ogm.drivers.http.driver.HttpDriver") + .setURI(URL); + return config; + } + + @Override + public SessionFactory getSessionFactory() { + return new SessionFactory(getConfiguration(), "com.baeldung.spring.data.neo4j.domain"); + } +} diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java new file mode 100644 index 0000000000..2b6394184d --- /dev/null +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java @@ -0,0 +1,34 @@ +package com.baeldung.spring.data.neo4j.config; + +import org.neo4j.ogm.session.SessionFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.data.neo4j.config.Neo4jConfiguration; +import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories; +import org.springframework.data.neo4j.server.Neo4jServer; +import org.springframework.transaction.annotation.EnableTransactionManagement; + + +@EnableTransactionManagement +@ComponentScan(basePackages = {"com.baeldung.spring.data.neo4j.services"}) +@Configuration +@EnableNeo4jRepositories(basePackages = "com.baeldung.spring.data.neo4j.repostory") +@Profile({"embedded", "test"}) +public class MovieDatabaseNeo4jTestConfiguration extends Neo4jConfiguration { + + @Bean + public org.neo4j.ogm.config.Configuration getConfiguration() { + org.neo4j.ogm.config.Configuration config = new org.neo4j.ogm.config.Configuration(); + config + .driverConfiguration() + .setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver"); + return config; + } + + @Override + public SessionFactory getSessionFactory() { + return new SessionFactory(getConfiguration(), "com.baeldung.spring.data.neo4j.domain"); + } +} diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Movie.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Movie.java new file mode 100644 index 0000000000..e48dfaf276 --- /dev/null +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Movie.java @@ -0,0 +1,61 @@ +package com.baeldung.spring.data.neo4j.domain; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.voodoodyne.jackson.jsog.JSOGGenerator; +import org.neo4j.ogm.annotation.GraphId; +import org.neo4j.ogm.annotation.NodeEntity; +import org.neo4j.ogm.annotation.Relationship; + +import java.util.Collection; +import java.util.List; + +@JsonIdentityInfo(generator=JSOGGenerator.class) + +@NodeEntity +public class Movie { + @GraphId + Long id; + + private String title; + + private int released; + private String tagline; + + @Relationship(type="ACTED_IN", direction = Relationship.INCOMING) private List roles; + + public Movie() { } + + public String getTitle() { + return title; + } + + public int getReleased() { + return released; + } + + public String getTagline() { + return tagline; + } + + public Collection getRoles() { + return roles; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setReleased(int released) { + this.released = released; + } + + public void setTagline(String tagline) { + this.tagline = tagline; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + +} diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Person.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Person.java new file mode 100644 index 0000000000..d96dc07530 --- /dev/null +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Person.java @@ -0,0 +1,50 @@ +package com.baeldung.spring.data.neo4j.domain; + + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.voodoodyne.jackson.jsog.JSOGGenerator; +import org.neo4j.ogm.annotation.GraphId; +import org.neo4j.ogm.annotation.NodeEntity; +import org.neo4j.ogm.annotation.Relationship; + +import java.util.List; + +@JsonIdentityInfo(generator=JSOGGenerator.class) +@NodeEntity +public class Person { + @GraphId + Long id; + + private String name; + private int born; + + @Relationship(type = "ACTED_IN") + private List movies; + + public Person() { } + + public String getName() { + return name; + } + + public int getBorn() { + return born; + } + + public List getMovies() { + return movies; + } + + public void setName(String name) { + this.name = name; + } + + public void setBorn(int born) { + this.born = born; + } + + public void setMovies(List movies) { + this.movies = movies; + } + +} diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Role.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Role.java new file mode 100644 index 0000000000..20512a10ad --- /dev/null +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Role.java @@ -0,0 +1,50 @@ +package com.baeldung.spring.data.neo4j.domain; + + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.voodoodyne.jackson.jsog.JSOGGenerator; +import org.neo4j.ogm.annotation.EndNode; +import org.neo4j.ogm.annotation.GraphId; +import org.neo4j.ogm.annotation.RelationshipEntity; +import org.neo4j.ogm.annotation.StartNode; + +import java.util.Collection; + +@JsonIdentityInfo(generator=JSOGGenerator.class) +@RelationshipEntity(type = "ACTED_IN") +public class Role { + @GraphId + Long id; + private Collection roles; + @StartNode + private Person person; + @EndNode + private Movie movie; + + public Role() { + } + + public Collection getRoles() { + return roles; + } + + public Person getPerson() { + return person; + } + + public Movie getMovie() { + return movie; + } + + public void setRoles(Collection roles) { + this.roles = roles; + } + + public void setPerson(Person person) { + this.person = person; + } + + public void setMovie(Movie movie) { + this.movie = movie; + } +} diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/MovieRepository.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/MovieRepository.java new file mode 100644 index 0000000000..850d2336ba --- /dev/null +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/MovieRepository.java @@ -0,0 +1,24 @@ +package com.baeldung.spring.data.neo4j.repostory; + +import com.baeldung.spring.data.neo4j.domain.Movie; +import org.springframework.data.neo4j.annotation.Query; +import org.springframework.data.neo4j.repository.GraphRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +@Repository +public interface MovieRepository extends GraphRepository { + Movie findByTitle(@Param("title") String title); + + @Query("MATCH (m:Movie) WHERE m.title =~ ('(?i).*'+{title}+'.*') RETURN m") + Collection findByTitleContaining(@Param("title") String title); + + @Query("MATCH (m:Movie)<-[:ACTED_IN]-(a:Person) RETURN m.title as movie, collect(a.name) as cast LIMIT {limit}") + List> graph(@Param("limit") int limit); +} + + diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/PersonRepository.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/PersonRepository.java new file mode 100644 index 0000000000..4c287f99a4 --- /dev/null +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/PersonRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.spring.data.neo4j.repostory; + +import com.baeldung.spring.data.neo4j.domain.Person; +import org.springframework.data.neo4j.repository.GraphRepository; +import org.springframework.stereotype.Repository; + + +@Repository +public interface PersonRepository extends GraphRepository { + +} diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/services/MovieService.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/services/MovieService.java new file mode 100644 index 0000000000..532cc79091 --- /dev/null +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/services/MovieService.java @@ -0,0 +1,50 @@ +package com.baeldung.spring.data.neo4j.services; + +import com.baeldung.spring.data.neo4j.repostory.MovieRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; + +@Service +@Transactional +public class MovieService { + + @Autowired + MovieRepository movieRepository; + + private Map toD3Format(Iterator> result) { + List> nodes = new ArrayList>(); + List> rels= new ArrayList>(); + int i=0; + while (result.hasNext()) { + Map row = result.next(); + nodes.add(map("title",row.get("movie"),"label","movie")); + int target=i; + i++; + for (Object name : (Collection) row.get("cast")) { + Map actor = map("title", name,"label","actor"); + int source = nodes.indexOf(actor); + if (source == -1) { + nodes.add(actor); + source = i++; + } + rels.add(map("source",source,"target",target)); + } + } + return map("nodes", nodes, "links", rels); + } + + private Map map(String key1, Object value1, String key2, Object value2) { + Map result = new HashMap(2); + result.put(key1,value1); + result.put(key2,value2); + return result; + } + + public Map graph(int limit) { + Iterator> result = movieRepository.graph(limit).iterator(); + return toD3Format(result); + } +} diff --git a/spring-data-neo4j/src/main/resources/logback.xml b/spring-data-neo4j/src/main/resources/logback.xml new file mode 100644 index 0000000000..215eeede64 --- /dev/null +++ b/spring-data-neo4j/src/main/resources/logback.xml @@ -0,0 +1,20 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-neo4j/src/main/resources/test.png b/spring-data-neo4j/src/main/resources/test.png new file mode 100644 index 0000000000..c3b5e80276 Binary files /dev/null and b/spring-data-neo4j/src/main/resources/test.png differ diff --git a/spring-data-neo4j/src/test/java/com/baeldung/spring/data/neo4j/MovieRepositoryTest.java b/spring-data-neo4j/src/test/java/com/baeldung/spring/data/neo4j/MovieRepositoryTest.java new file mode 100644 index 0000000000..8061b3c2a7 --- /dev/null +++ b/spring-data-neo4j/src/test/java/com/baeldung/spring/data/neo4j/MovieRepositoryTest.java @@ -0,0 +1,133 @@ +package com.baeldung.spring.data.neo4j; + +import com.baeldung.spring.data.neo4j.config.MovieDatabaseNeo4jTestConfiguration; +import com.baeldung.spring.data.neo4j.domain.Movie; +import com.baeldung.spring.data.neo4j.domain.Person; +import com.baeldung.spring.data.neo4j.domain.Role; +import com.baeldung.spring.data.neo4j.repostory.MovieRepository; +import com.baeldung.spring.data.neo4j.repostory.PersonRepository; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.*; + +import static junit.framework.TestCase.assertNull; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = MovieDatabaseNeo4jTestConfiguration.class) +@ActiveProfiles(profiles = "test") +public class MovieRepositoryTest { + + @Autowired + private MovieRepository movieRepository; + + @Autowired + private PersonRepository personRepository; + + public MovieRepositoryTest() { + } + + @Before + public void initializeDatabase() { + System.out.println("seeding embedded database"); + Movie italianJob = new Movie(); + italianJob.setTitle("The Italian Job"); + italianJob.setReleased(1999); + movieRepository.save(italianJob); + + Person mark = new Person(); + mark.setName("Mark Wahlberg"); + personRepository.save(mark); + + Role charlie = new Role(); + charlie.setMovie(italianJob); + charlie.setPerson(mark); + Collection roleNames = new HashSet(); + roleNames.add("Charlie Croker"); + charlie.setRoles(roleNames); + List roles = new ArrayList(); + roles.add(charlie); + italianJob.setRoles(roles); + movieRepository.save(italianJob); + } + + @Test + @DirtiesContext + public void testFindByTitle() { + System.out.println("findByTitle"); + String title = "The Italian Job"; + Movie result = movieRepository.findByTitle(title); + assertNotNull(result); + assertEquals(1999, result.getReleased()); + } + + @Test + @DirtiesContext + public void testCount() { + System.out.println("count"); + long movieCount = movieRepository.count(); + assertNotNull(movieCount); + assertEquals(1, movieCount); + } + + @Test + @DirtiesContext + public void testFindAll() { + System.out.println("findAll"); + Collection result = + (Collection) movieRepository.findAll(); + assertNotNull(result); + assertEquals(1, result.size()); + } + + @Test + @DirtiesContext + public void testFindByTitleContaining() { + System.out.println("findByTitleContaining"); + String title = "Italian"; + Collection result = + movieRepository.findByTitleContaining(title); + assertNotNull(result); + assertEquals(1, result.size()); + } + + @Test + @DirtiesContext + public void testGraph() { + System.out.println("graph"); + List> graph = movieRepository.graph(5); + assertEquals(1, graph.size()); + Map map = graph.get(0); + assertEquals(2, map.size()); + String[] cast = (String[]) map.get("cast"); + String movie = (String) map.get("movie"); + assertEquals("The Italian Job", movie); + assertEquals("Mark Wahlberg", cast[0]); + } + + @Test + @DirtiesContext + public void testDeleteMovie() { + System.out.println("deleteMovie"); + movieRepository.delete(movieRepository.findByTitle("The Italian Job")); + assertNull(movieRepository.findByTitle("The Italian Job")); + } + + @Test + @DirtiesContext + public void testDeleteAll() { + System.out.println("deleteAll"); + movieRepository.deleteAll(); + Collection result = + (Collection) movieRepository.findAll(); + assertEquals(0, result.size()); + } +} diff --git a/spring-data-redis/README.md b/spring-data-redis/README.md index b9b2e5d93d..89eae99f05 100644 --- a/spring-data-redis/README.md +++ b/spring-data-redis/README.md @@ -1,7 +1,7 @@ ## Spring Data Redis ### Relevant Articles: -- [Introduction to Spring Data Redis] +- [Introduction to Spring Data Redis](http://www.baeldung.com/spring-data-redis-tutorial) ### Build the Project with Tests Running ``` diff --git a/spring-data-redis/pom.xml b/spring-data-redis/pom.xml index 98da69934c..25686fca16 100644 --- a/spring-data-redis/pom.xml +++ b/spring-data-redis/pom.xml @@ -1,76 +1,76 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + 4.0.0 + com.baeldung + spring-data-redis + 1.0 + jar - org.baeldung - sprint-data-redis - 0.0.1-SNAPSHOT - jar + + UTF-8 + 4.2.5.RELEASE + 1.6.2.RELEASE + 0.8.0 + - - UTF-8 - 4.2.2.RELEASE - 1.6.2.RELEASE - 0.8.0 - + + + org.springframework.data + spring-data-redis + ${spring-data-redis} + - - - org.springframework.data - spring-data-redis - ${spring-data-redis} - + + cglib + cglib-nodep + 2.2 + - - cglib - cglib-nodep - 2.2 - + + log4j + log4j + 1.2.16 + - - log4j - log4j - 1.2.16 - + + redis.clients + jedis + 2.5.1 + jar + - - redis.clients - jedis - 2.5.1 - jar - + + org.springframework + spring-core + ${spring.version} + - - org.springframework - spring-core - ${spring.version} - + + org.springframework + spring-context + ${spring.version} + - - org.springframework - spring-context - ${spring.version} - + + junit + junit + 4.12 + test + - - junit - junit - 4.12 - test - + + org.springframework + spring-test + ${spring.version} + test + - - org.springframework - spring-test - ${spring.version} - test - - - - com.lordofthejars - nosqlunit-redis - ${nosqlunit.version} - - - + + com.lordofthejars + nosqlunit-redis + ${nosqlunit.version} + + + diff --git a/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java new file mode 100644 index 0000000000..4fd83a2bb6 --- /dev/null +++ b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java @@ -0,0 +1,55 @@ +package com.baeldung.spring.data.redis.config; + +import com.baeldung.spring.data.redis.queue.MessagePublisher; +import com.baeldung.spring.data.redis.queue.RedisMessagePublisher; +import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.data.redis.listener.RedisMessageListenerContainer; +import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; +import org.springframework.data.redis.serializer.GenericToStringSerializer; + +@Configuration +@ComponentScan("com.baeldung.spring.data.redis") +public class RedisConfig { + + @Bean + JedisConnectionFactory jedisConnectionFactory() { + return new JedisConnectionFactory(); + } + + @Bean + public RedisTemplate redisTemplate() { + final RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(jedisConnectionFactory()); + template.setValueSerializer(new GenericToStringSerializer(Object.class)); + return template; + } + + @Bean + MessageListenerAdapter messageListener() { + return new MessageListenerAdapter(new RedisMessageSubscriber()); + } + + @Bean + RedisMessageListenerContainer redisContainer() { + final RedisMessageListenerContainer container = new RedisMessageListenerContainer(); + container.setConnectionFactory(jedisConnectionFactory()); + container.addMessageListener(messageListener(), topic()); + return container; + } + + @Bean + MessagePublisher redisPublisher() { + return new RedisMessagePublisher(redisTemplate(), topic()); + } + + @Bean + ChannelTopic topic() { + return new ChannelTopic("pubsub:queue"); + } +} diff --git a/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java new file mode 100644 index 0000000000..10ba0f5ef4 --- /dev/null +++ b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java @@ -0,0 +1,59 @@ +package com.baeldung.spring.data.redis.model; + +import java.io.Serializable; + +public class Student implements Serializable { + + public enum Gender { + MALE, FEMALE + } + + private String id; + private String name; + private Gender gender; + private int grade; + + public Student(String id, String name, Gender gender, int grade) { + this.id = id; + this.name = name; + this.gender = gender; + this.grade = grade; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Gender getGender() { + return gender; + } + + public void setGender(Gender gender) { + this.gender = gender; + } + + public int getGrade() { + return grade; + } + + public void setGrade(int grade) { + this.grade = grade; + } + + @Override + public String toString() { + return "Student{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", gender=" + gender + ", grade=" + grade + '}'; + } +} \ No newline at end of file diff --git a/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/MessagePublisher.java b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/MessagePublisher.java new file mode 100644 index 0000000000..9a42545d6c --- /dev/null +++ b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/MessagePublisher.java @@ -0,0 +1,7 @@ +package com.baeldung.spring.data.redis.queue; + + +public interface MessagePublisher { + + void publish(final String message); +} diff --git a/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessagePublisher.java b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessagePublisher.java new file mode 100644 index 0000000000..f4b3180a37 --- /dev/null +++ b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessagePublisher.java @@ -0,0 +1,28 @@ +package com.baeldung.spring.data.redis.queue; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.listener.ChannelTopic; +import org.springframework.stereotype.Service; + +@Service +public class RedisMessagePublisher implements MessagePublisher { + + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private ChannelTopic topic; + + public RedisMessagePublisher() { + } + + public RedisMessagePublisher(final RedisTemplate redisTemplate, + final ChannelTopic topic) { + this.redisTemplate = redisTemplate; + this.topic = topic; + } + + public void publish(final String message) { + redisTemplate.convertAndSend(topic.getTopic(), message); + } +} diff --git a/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java new file mode 100644 index 0000000000..849e1fb59f --- /dev/null +++ b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java @@ -0,0 +1,19 @@ +package com.baeldung.spring.data.redis.queue; + +import org.springframework.data.redis.connection.Message; +import org.springframework.data.redis.connection.MessageListener; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class RedisMessageSubscriber implements MessageListener { + + public static List messageList = new ArrayList(); + + public void onMessage(final Message message, final byte[] pattern) { + messageList.add(message.toString()); + System.out.println("Message received: " + new String(message.getBody())); + } +} \ No newline at end of file diff --git a/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/repo/StudentRepository.java b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/repo/StudentRepository.java new file mode 100644 index 0000000000..250c227f00 --- /dev/null +++ b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/repo/StudentRepository.java @@ -0,0 +1,18 @@ +package com.baeldung.spring.data.redis.repo; + +import com.baeldung.spring.data.redis.model.Student; + +import java.util.Map; + +public interface StudentRepository { + + void saveStudent(Student person); + + void updateStudent(Student student); + + Student findStudent(String id); + + Map findAllStudents(); + + void deleteStudent(String id); +} diff --git a/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/repo/StudentRepositoryImpl.java b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/repo/StudentRepositoryImpl.java new file mode 100644 index 0000000000..f13bef0f54 --- /dev/null +++ b/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/repo/StudentRepositoryImpl.java @@ -0,0 +1,49 @@ +package com.baeldung.spring.data.redis.repo; + +import com.baeldung.spring.data.redis.model.Student; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +import javax.annotation.PostConstruct; +import java.util.Map; + +@Repository +public class StudentRepositoryImpl implements StudentRepository { + + private static final String KEY = "Student"; + + private RedisTemplate redisTemplate; + private HashOperations hashOperations; + + @Autowired + public StudentRepositoryImpl(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + @PostConstruct + private void init() { + hashOperations = redisTemplate.opsForHash(); + } + + public void saveStudent(final Student student) { + hashOperations.put(KEY, student.getId(), student); + } + + public void updateStudent(final Student student) { + hashOperations.put(KEY, student.getId(), student); + } + + public Student findStudent(final String id) { + return (Student) hashOperations.get(KEY, id); + } + + public Map findAllStudents() { + return hashOperations.entries(KEY); + } + + public void deleteStudent(final String id) { + hashOperations.delete(KEY, id); + } +} diff --git a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/config/RedisConfig.java b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/config/RedisConfig.java deleted file mode 100644 index a7e75a438a..0000000000 --- a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/config/RedisConfig.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.baeldung.spring.data.redis.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; - -@Configuration -@ComponentScan("org.baeldung.spring.data.redis") -public class RedisConfig { - - @Bean - JedisConnectionFactory jedisConnectionFactory() { - return new JedisConnectionFactory(); - } - - @Bean - public RedisTemplate redisTemplate() { - final RedisTemplate< String, Object> template = new RedisTemplate(); - template.setConnectionFactory(jedisConnectionFactory()); - return template; - } -} diff --git a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/model/Student.java b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/model/Student.java deleted file mode 100644 index acc96899ce..0000000000 --- a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/model/Student.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.baeldung.spring.data.redis.model; - -import java.io.Serializable; - -public class Student implements Serializable { - - public enum Gender { - MALE, FEMALE - } - - private String id; - private String name; - private Gender gender; - private int grade; - - public Student(String id, String name, Gender gender, int grade) { - this.id = id; - this.name = name; - this.gender = gender; - this.grade = grade; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Gender getGender() { - return gender; - } - - public void setGender(Gender gender) { - this.gender = gender; - } - - public int getGrade() { - return grade; - } - - public void setGrade(int grade) { - this.grade = grade; - } - - @Override - public String toString() { - return "Student{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", gender=" + gender + ", grade=" + grade + '}'; - } -} \ No newline at end of file diff --git a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepository.java b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepository.java deleted file mode 100644 index 6a909ed137..0000000000 --- a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.baeldung.spring.data.redis.repo; - -import org.baeldung.spring.data.redis.model.Student; -import org.springframework.stereotype.Component; - -import java.util.Map; - -public interface StudentRepository { - - void saveStudent(Student person); - - void updateStudent(Student student); - - Student findStudent(String id); - - Map findAllStudents(); - - void deleteStudent(String id); -} diff --git a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepositoryImpl.java b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepositoryImpl.java deleted file mode 100644 index 55e6ad5edc..0000000000 --- a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepositoryImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.baeldung.spring.data.redis.repo; - -import org.baeldung.spring.data.redis.model.Student; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Repository; - -import java.util.Map; - -@Repository -public class StudentRepositoryImpl implements StudentRepository { - - private static final String KEY = "Student"; - - @Autowired - private RedisTemplate redisTemplate; - - public void saveStudent(final Student student) { - redisTemplate.opsForHash().put(KEY, student.getId(), student); - } - - public void updateStudent(final Student student) { - redisTemplate.opsForHash().put(KEY, student.getId(), student); - } - - public Student findStudent(final String id) { - return (Student) redisTemplate.opsForHash().get(KEY, id); - } - - public Map findAllStudents() { - return redisTemplate.opsForHash().entries(KEY); - } - - public void deleteStudent(final String id) { - this.redisTemplate.opsForHash().delete(KEY, id); - } -} diff --git a/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerTest.java b/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerTest.java new file mode 100644 index 0000000000..403cf990e0 --- /dev/null +++ b/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/RedisMessageListenerTest.java @@ -0,0 +1,30 @@ +package com.baeldung.spring.data.redis; + +import com.baeldung.spring.data.redis.config.RedisConfig; +import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber; +import com.baeldung.spring.data.redis.queue.RedisMessagePublisher; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.UUID; + +import static org.junit.Assert.assertTrue; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = RedisConfig.class) +public class RedisMessageListenerTest { + + @Autowired + private RedisMessagePublisher redisMessagePublisher; + + @Test + public void testOnMessage() throws Exception { + String message = "Message " + UUID.randomUUID(); + redisMessagePublisher.publish(message); + Thread.sleep(100); + assertTrue(RedisMessageSubscriber.messageList.get(0).contains(message)); + } +} \ No newline at end of file diff --git a/spring-data-redis/src/test/java/org/baeldung/spring/data/redis/repo/StudentRepositoryTest.java b/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryTest.java similarity index 93% rename from spring-data-redis/src/test/java/org/baeldung/spring/data/redis/repo/StudentRepositoryTest.java rename to spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryTest.java index 08540abd36..c32dfc7670 100644 --- a/spring-data-redis/src/test/java/org/baeldung/spring/data/redis/repo/StudentRepositoryTest.java +++ b/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryTest.java @@ -1,8 +1,7 @@ -package org.baeldung.spring.data.redis.repo; +package com.baeldung.spring.data.redis.repo; -import org.baeldung.spring.data.redis.config.RedisConfig; -import org.baeldung.spring.data.redis.model.Student; -import org.junit.Before; +import com.baeldung.spring.data.redis.config.RedisConfig; +import com.baeldung.spring.data.redis.model.Student; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-data-rest/README.md b/spring-data-rest/README.md new file mode 100644 index 0000000000..7dc439206b --- /dev/null +++ b/spring-data-rest/README.md @@ -0,0 +1,14 @@ +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +# About this project +This project contains examples from the [Introduction to Spring Data REST](http://www.baeldung.com/spring-data-rest-intro) article from Baeldung. + +# Running the project +The application uses [Spring Boot](http://projects.spring.io/spring-boot/), so it is easy to run. You can start it any of a few ways: +* Run the `main` method from `SpringDataRestApplication` +* Use the Maven Spring Boot plugin: `mvn spring-boot:run` +* Package the application as a JAR and run it using `java -jar intro-spring-data-rest.jar` + +# Viewing the running application +To view the running application, visit [http://localhost:8080](http://localhost:8080) in your browser diff --git a/spring-data-rest/pom.xml b/spring-data-rest/pom.xml new file mode 100644 index 0000000000..5ae694a04f --- /dev/null +++ b/spring-data-rest/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + com.baeldung + intro-spring-data-rest + 1.0 + jar + + intro-spring-data-rest + Intro to Spring Data REST + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-data-rest + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-data-rest/src/main/java/com/baeldung/SpringDataRestApplication.java b/spring-data-rest/src/main/java/com/baeldung/SpringDataRestApplication.java new file mode 100644 index 0000000000..94eddc5b3e --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/SpringDataRestApplication.java @@ -0,0 +1,11 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringDataRestApplication { + public static void main(String[] args) { + SpringApplication.run(SpringDataRestApplication.class, args); + } +} diff --git a/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java b/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java new file mode 100644 index 0000000000..89ab848e81 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java @@ -0,0 +1,30 @@ +package com.baeldung.config; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener; +import org.springframework.validation.Validator; + +@Configuration +public class ValidatorEventRegister implements InitializingBean { + + @Autowired + ValidatingRepositoryEventListener validatingRepositoryEventListener; + + @Autowired + private Map validators; + + @Override + public void afterPropertiesSet() throws Exception { + List events = Arrays.asList("beforeCreate", "afterCreate", "beforeSave", "afterSave", "beforeLinkSave", "afterLinkSave", "beforeDelete", "afterDelete"); + + for (Map.Entry entry : validators.entrySet()) { + events.stream().filter(p -> entry.getKey().startsWith(p)).findFirst().ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue())); + } + } +} diff --git a/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java b/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java new file mode 100644 index 0000000000..ee84738e7a --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java @@ -0,0 +1,25 @@ +package com.baeldung.exception.handlers; + +import java.util.stream.Collectors; + +import org.springframework.data.rest.core.RepositoryConstraintViolationException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@ControllerAdvice +public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { + + @ExceptionHandler({ RepositoryConstraintViolationException.class }) + public ResponseEntity handleAccessDeniedException(Exception ex, WebRequest request) { + RepositoryConstraintViolationException nevEx = (RepositoryConstraintViolationException) ex; + + String errors = nevEx.getErrors().getAllErrors().stream().map(p -> p.toString()).collect(Collectors.joining("\n")); + return new ResponseEntity(errors, new HttpHeaders(), HttpStatus.NOT_ACCEPTABLE); + } + +} \ No newline at end of file diff --git a/spring-data-rest/src/main/java/com/baeldung/models/WebsiteUser.java b/spring-data-rest/src/main/java/com/baeldung/models/WebsiteUser.java new file mode 100644 index 0000000000..4eb9773e36 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/models/WebsiteUser.java @@ -0,0 +1,41 @@ +package com.baeldung.models; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class WebsiteUser { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + private String email; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } +} diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/UserRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/UserRepository.java new file mode 100644 index 0000000000..0b55ac89b6 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/repositories/UserRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.repositories; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; + +import com.baeldung.models.WebsiteUser; + +@RepositoryRestResource(collectionResourceRel = "users", path = "users") +public interface UserRepository extends CrudRepository { + +} diff --git a/spring-data-rest/src/main/java/com/baeldung/validators/WebsiteUserValidator.java b/spring-data-rest/src/main/java/com/baeldung/validators/WebsiteUserValidator.java new file mode 100644 index 0000000000..0380332708 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/validators/WebsiteUserValidator.java @@ -0,0 +1,33 @@ +package com.baeldung.validators; + +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +import com.baeldung.models.WebsiteUser; + +@Component("beforeCreateWebsiteUserValidator") +public class WebsiteUserValidator implements Validator { + + @Override + public boolean supports(Class clazz) { + return WebsiteUser.class.equals(clazz); + } + + @Override + public void validate(Object obj, Errors errors) { + + WebsiteUser user = (WebsiteUser) obj; + if (checkInputString(user.getName())) { + errors.rejectValue("name", "name.empty"); + } + + if (checkInputString(user.getEmail())) { + errors.rejectValue("email", "email.empty"); + } + } + + private boolean checkInputString(String input) { + return (input == null || input.trim().length() == 0); + } +} diff --git a/spring-cloud-data-flow/time-source/src/main/resources/application.properties b/spring-data-rest/src/main/resources/application.properties similarity index 100% rename from spring-cloud-data-flow/time-source/src/main/resources/application.properties rename to spring-data-rest/src/main/resources/application.properties diff --git a/spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java b/spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java new file mode 100644 index 0000000000..b185c6d5ab --- /dev/null +++ b/spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java @@ -0,0 +1,100 @@ +package com.baeldung.validator; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.ResultMatcher; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.SpringDataRestApplication; +import com.baeldung.models.WebsiteUser; +import com.fasterxml.jackson.databind.ObjectMapper; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SpringDataRestApplication.class) +@WebAppConfiguration +public class SpringDataRestValidatorTest { + public static final String URL = "http://localhost"; + + private MockMvc mockMvc; + + @Autowired + protected WebApplicationContext wac; + + @Before + public void setup() { + mockMvc = webAppContextSetup(wac).build(); + } + + @Test + public void whenStartingApplication_thenCorrectStatusCode() throws Exception { + mockMvc.perform(get("/users")).andExpect(status().is2xxSuccessful()); + }; + + @Test + public void whenAddingNewCorrectUser_thenCorrectStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + user.setName("John Doe"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) + .andExpect(status().is2xxSuccessful()) + .andExpect(redirectedUrl("http://localhost/users/1")); + } + + @Test + public void whenAddingNewUserWithoutName_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) + .andExpect(status().isNotAcceptable()) + .andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithEmptyName_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + user.setName(""); + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) + .andExpect(status().isNotAcceptable()) + .andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithoutEmail_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setName("John Doe"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) + .andExpect(status().isNotAcceptable()) + .andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithEmptyEmail_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setName("John Doe"); + user.setEmail(""); + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) + .andExpect(status().isNotAcceptable()) + .andExpect(redirectedUrl(null)); + } + +} diff --git a/spring-exceptions/.classpath b/spring-exceptions/.classpath deleted file mode 100644 index 6b533711d3..0000000000 --- a/spring-exceptions/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-exceptions/.gitignore b/spring-exceptions/.gitignore index 83c05e60c8..2d669fa30b 100644 --- a/spring-exceptions/.gitignore +++ b/spring-exceptions/.gitignore @@ -1,5 +1,7 @@ *.class +derby.log + #folders# /target /neoDb* diff --git a/spring-exceptions/.project b/spring-exceptions/.project deleted file mode 100644 index 810b4a9286..0000000000 --- a/spring-exceptions/.project +++ /dev/null @@ -1,43 +0,0 @@ - - - spring-exceptions - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-exceptions/.settings/.jsdtscope b/spring-exceptions/.settings/.jsdtscope deleted file mode 100644 index b46b9207a8..0000000000 --- a/spring-exceptions/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-exceptions/.settings/org.eclipse.jdt.core.prefs b/spring-exceptions/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index fb671a82a6..0000000000 --- a/spring-exceptions/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-exceptions/.settings/org.eclipse.jdt.ui.prefs b/spring-exceptions/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-exceptions/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-exceptions/.settings/org.eclipse.m2e.core.prefs b/spring-exceptions/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-exceptions/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-exceptions/.settings/org.eclipse.m2e.wtp.prefs b/spring-exceptions/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-exceptions/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-exceptions/.settings/org.eclipse.wst.common.component b/spring-exceptions/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 7785d041ba..0000000000 --- a/spring-exceptions/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-exceptions/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-exceptions/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 9ca0d1c1b7..0000000000 --- a/spring-exceptions/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/spring-exceptions/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-exceptions/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-exceptions/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-exceptions/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-exceptions/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-exceptions/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-exceptions/.settings/org.eclipse.wst.validation.prefs b/spring-exceptions/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-exceptions/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-exceptions/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-exceptions/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-exceptions/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-exceptions/.springBeans b/spring-exceptions/.springBeans deleted file mode 100644 index 7623a7e888..0000000000 --- a/spring-exceptions/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/spring-exceptions/pom.xml b/spring-exceptions/pom.xml index 324b7475b3..733a721c58 100644 --- a/spring-exceptions/pom.xml +++ b/spring-exceptions/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-exceptions 0.1-SNAPSHOT @@ -130,6 +130,32 @@ test + + javax.el + el-api + 2.2 + + + + org.apache.derby + derby + 10.12.1.1 + + + org.apache.derby + derbyclient + 10.12.1.1 + + + org.apache.derby + derbynet + 10.12.1.1 + + + org.apache.derby + derbytools + 10.12.1.1 + @@ -203,14 +229,14 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.3.2.RELEASE + 4.1.1.RELEASE 3.20.0-GA 1.2 4.3.11.Final - 5.1.37 + 5.1.38 7.0.42 @@ -232,15 +258,15 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 1.8.9 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-exceptions/src/main/java/org/baeldung/ex/nontransientexception/cause/Cause1NonTransientConfig.java b/spring-exceptions/src/main/java/org/baeldung/ex/nontransientexception/cause/Cause1NonTransientConfig.java new file mode 100644 index 0000000000..3337e4796d --- /dev/null +++ b/spring-exceptions/src/main/java/org/baeldung/ex/nontransientexception/cause/Cause1NonTransientConfig.java @@ -0,0 +1,76 @@ +package org.baeldung.ex.nontransientexception.cause; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.apache.tomcat.dbcp.dbcp.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.orm.hibernate4.HibernateTransactionManager; +import org.springframework.orm.hibernate4.LocalSessionFactoryBean; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-derby.properties" }) +@ComponentScan({ "org.baeldung.persistence" }) +public class Cause1NonTransientConfig { + + @Autowired + private Environment env; + + public Cause1NonTransientConfig() { + super(); + } + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(restDataSource()); + sessionFactory.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + + @Bean + public DataSource restDataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public HibernateTransactionManager transactionManager() { + final HibernateTransactionManager txManager = new HibernateTransactionManager(); + txManager.setSessionFactory(sessionFactory().getObject()); + + return txManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); + return hibernateProperties; + } + +} diff --git a/spring-exceptions/src/main/java/org/baeldung/ex/nontransientexception/cause/Cause4NonTransientConfig.java b/spring-exceptions/src/main/java/org/baeldung/ex/nontransientexception/cause/Cause4NonTransientConfig.java new file mode 100644 index 0000000000..3543526f37 --- /dev/null +++ b/spring-exceptions/src/main/java/org/baeldung/ex/nontransientexception/cause/Cause4NonTransientConfig.java @@ -0,0 +1,75 @@ +package org.baeldung.ex.nontransientexception.cause; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.apache.tomcat.dbcp.dbcp.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.orm.hibernate4.HibernateTransactionManager; +import org.springframework.orm.hibernate4.LocalSessionFactoryBean; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-derby.properties" }) +@ComponentScan({ "org.baeldung.persistence" }) +public class Cause4NonTransientConfig { + + @Autowired + private Environment env; + + public Cause4NonTransientConfig() { + super(); + } + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(restDataSource()); + sessionFactory.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + + @Bean + public DataSource restDataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public HibernateTransactionManager transactionManager() { + final HibernateTransactionManager txManager = new HibernateTransactionManager(); + txManager.setSessionFactory(sessionFactory().getObject()); + + return txManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); + return hibernateProperties; + } +} diff --git a/spring-exceptions/src/main/java/org/baeldung/ex/nontransientexception/cause/Cause5NonTransientConfig.java b/spring-exceptions/src/main/java/org/baeldung/ex/nontransientexception/cause/Cause5NonTransientConfig.java new file mode 100644 index 0000000000..6d5d998c5b --- /dev/null +++ b/spring-exceptions/src/main/java/org/baeldung/ex/nontransientexception/cause/Cause5NonTransientConfig.java @@ -0,0 +1,75 @@ +package org.baeldung.ex.nontransientexception.cause; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.apache.tomcat.dbcp.dbcp.BasicDataSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.orm.hibernate4.HibernateTransactionManager; +import org.springframework.orm.hibernate4.LocalSessionFactoryBean; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-mysql-incorrect.properties" }) +@ComponentScan({ "org.baeldung.persistence" }) +public class Cause5NonTransientConfig { + + @Autowired + private Environment env; + + public Cause5NonTransientConfig() { + super(); + } + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(restDataSource()); + sessionFactory.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + + @Bean + public DataSource restDataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public HibernateTransactionManager transactionManager() { + final HibernateTransactionManager txManager = new HibernateTransactionManager(); + txManager.setSessionFactory(sessionFactory().getObject()); + + return txManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); + return hibernateProperties; + } +} diff --git a/spring-exceptions/src/main/resources/persistence-derby.properties b/spring-exceptions/src/main/resources/persistence-derby.properties new file mode 100644 index 0000000000..49fac9877e --- /dev/null +++ b/spring-exceptions/src/main/resources/persistence-derby.properties @@ -0,0 +1,10 @@ +# jdbc.X +jdbc.driverClassName=org.apache.derby.jdbc.EmbeddedDriver +jdbc.url=jdbc:derby:memory:spring_exceptions;create=true +jdbc.user=tutorialuser +jdbc.pass=tutorialpass + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.DerbyDialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create diff --git a/spring-exceptions/src/main/resources/persistence-mysql-incorrect.properties b/spring-exceptions/src/main/resources/persistence-mysql-incorrect.properties new file mode 100644 index 0000000000..b5b8095104 --- /dev/null +++ b/spring-exceptions/src/main/resources/persistence-mysql-incorrect.properties @@ -0,0 +1,10 @@ +# jdbc.X +jdbc.driverClassName=com.mysql.jdbc.Driver +jdbc.url=jdbc:mysql:3306://localhost/spring_hibernate4_exceptions?createDatabaseIfNotExist=true +jdbc.user=tutorialuser +jdbc.pass=tutorialmy5ql + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.MySQL5Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create diff --git a/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/CannotGetJdbcConnectionExceptionTest.java b/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/CannotGetJdbcConnectionExceptionTest.java new file mode 100644 index 0000000000..7a1804ec49 --- /dev/null +++ b/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/CannotGetJdbcConnectionExceptionTest.java @@ -0,0 +1,31 @@ +package org.baeldung.ex.nontransientdataaccessexception; + +import javax.sql.DataSource; + +import org.baeldung.ex.nontransientexception.cause.Cause1NonTransientConfig; +import org.baeldung.ex.nontransientexception.cause.Cause5NonTransientConfig; +import org.baeldung.persistence.model.Foo; +import org.baeldung.persistence.service.IFooService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.jdbc.CannotGetJdbcConnectionException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { Cause5NonTransientConfig.class }, loader = AnnotationConfigContextLoader.class) +public class CannotGetJdbcConnectionExceptionTest { + + @Autowired + private DataSource restDataSource; + + @Test(expected = CannotGetJdbcConnectionException.class) + public void whenJdbcUrlIncorrect_thenCannotGetJdbcConnectionException() { + JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource); + jdbcTemplate.execute("select * from foo"); + } +} diff --git a/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/DataIntegrityExceptionTest.java b/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/DataIntegrityExceptionTest.java new file mode 100644 index 0000000000..357eb168cd --- /dev/null +++ b/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/DataIntegrityExceptionTest.java @@ -0,0 +1,46 @@ +package org.baeldung.ex.nontransientdataaccessexception; + +import javax.sql.DataSource; + +import org.baeldung.ex.nontransientexception.cause.Cause1NonTransientConfig; +import org.baeldung.persistence.model.Foo; +import org.baeldung.persistence.service.IFooService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { Cause1NonTransientConfig.class }, loader = AnnotationConfigContextLoader.class) +public class DataIntegrityExceptionTest { + + @Autowired + private IFooService fooService; + + @Autowired + private DataSource restDataSource; + + @Test(expected = DataIntegrityViolationException.class) + public void whenSavingNullValue_thenDataIntegrityException() { + final Foo fooEntity = new Foo(); + fooService.create(fooEntity); + } + + @Test(expected = DuplicateKeyException.class) + public void whenSavingDuplicateKeyValues_thenDuplicateKeyException() { + final JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource); + + try { + jdbcTemplate.execute("insert into foo(id,name) values (1,'a')"); + jdbcTemplate.execute("insert into foo(id,name) values (1,'b')"); + } finally { + jdbcTemplate.execute("delete from foo where id=1"); + } + } + +} diff --git a/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/DataRetrievalExceptionTest.java b/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/DataRetrievalExceptionTest.java new file mode 100644 index 0000000000..69b98b0539 --- /dev/null +++ b/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/DataRetrievalExceptionTest.java @@ -0,0 +1,53 @@ +package org.baeldung.ex.nontransientdataaccessexception; + +import javax.sql.DataSource; + +import org.baeldung.ex.nontransientexception.cause.Cause1NonTransientConfig; +import org.baeldung.persistence.model.Foo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataRetrievalFailureException; +import org.springframework.dao.IncorrectResultSizeDataAccessException; +import org.springframework.jdbc.IncorrectResultSetColumnCountException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { Cause1NonTransientConfig.class }, loader = AnnotationConfigContextLoader.class) +public class DataRetrievalExceptionTest { + + @Autowired + private DataSource restDataSource; + + @Test(expected = DataRetrievalFailureException.class) + public void whenRetrievingNonExistentValue_thenDataRetrievalException() { + final JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource); + + jdbcTemplate.queryForObject("select * from foo where id=3", Integer.class); + } + + @Test(expected = IncorrectResultSetColumnCountException.class) + public void whenRetrievingMultipleColumns_thenIncorrectResultSetColumnCountException() { + final JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource); + try { + jdbcTemplate.execute("insert into foo(id,name) values (1,'a')"); + jdbcTemplate.queryForList("select id,name from foo where id=1", Foo.class); + } finally { + jdbcTemplate.execute("delete from foo where id=1"); + } + } + + @Test(expected = IncorrectResultSizeDataAccessException.class) + public void whenRetrievingMultipleValues_thenIncorrectResultSizeException() { + final JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource); + + jdbcTemplate.execute("insert into foo(name) values ('a')"); + jdbcTemplate.execute("insert into foo(name) values ('a')"); + + jdbcTemplate.queryForObject("select id from foo where name='a'", Integer.class); + } + +} diff --git a/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/DataSourceLookupExceptionTest.java b/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/DataSourceLookupExceptionTest.java new file mode 100644 index 0000000000..036f99ac8f --- /dev/null +++ b/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/DataSourceLookupExceptionTest.java @@ -0,0 +1,24 @@ +package org.baeldung.ex.nontransientdataaccessexception; + +import javax.sql.DataSource; + +import org.baeldung.ex.nontransientexception.cause.Cause4NonTransientConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException; +import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { Cause4NonTransientConfig.class }, loader = AnnotationConfigContextLoader.class) +public class DataSourceLookupExceptionTest { + + @Test(expected = DataSourceLookupFailureException.class) + public void whenLookupNonExistentDataSource_thenDataSourceLookupFailureException() { + final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup(); + dsLookup.setResourceRef(true); + final DataSource dataSource = dsLookup.getDataSource("java:comp/env/jdbc/example_db"); + } +} diff --git a/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/InvalidResourceUsageExceptionTest.java b/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/InvalidResourceUsageExceptionTest.java new file mode 100644 index 0000000000..9c4fd55fa4 --- /dev/null +++ b/spring-exceptions/src/test/java/org/baeldung/ex/nontransientdataaccessexception/InvalidResourceUsageExceptionTest.java @@ -0,0 +1,46 @@ +package org.baeldung.ex.nontransientdataaccessexception; + +import org.baeldung.ex.nontransientexception.cause.Cause1NonTransientConfig; +import org.baeldung.persistence.service.IFooService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.InvalidDataAccessResourceUsageException; +import org.springframework.jdbc.BadSqlGrammarException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import javax.sql.DataSource; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { Cause1NonTransientConfig.class }, loader = AnnotationConfigContextLoader.class) +public class InvalidResourceUsageExceptionTest { + + @Autowired + private IFooService fooService; + + @Autowired + private DataSource restDataSource; + + @Test(expected = InvalidDataAccessResourceUsageException.class) + public void whenRetrievingDataUserNoSelectRights_thenInvalidResourceUsageException() { + final JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource); + jdbcTemplate.execute("revoke select from tutorialuser"); + + try { + fooService.findAll(); + } finally { + jdbcTemplate.execute("grant select to tutorialuser"); + } + } + + @Test(expected = BadSqlGrammarException.class) + public void whenIncorrectSql_thenBadSqlGrammarException() { + final JdbcTemplate jdbcTemplate = new JdbcTemplate(restDataSource); + + jdbcTemplate.queryForObject("select * fro foo where id=3", Integer.class); + } + +} diff --git a/spring-freemarker/README.md b/spring-freemarker/README.md new file mode 100644 index 0000000000..bd939d11e9 --- /dev/null +++ b/spring-freemarker/README.md @@ -0,0 +1,7 @@ +========= + +## Using FreeMarker in Spring MVC + + +### Relevant Articles: +- [Introduction to Using FreeMarker in Spring MVC](http://www.baeldung.com/freemarker-in-spring-mvc-tutorial) diff --git a/spring-hibernate3/.classpath b/spring-hibernate3/.classpath deleted file mode 100644 index 5efa587d72..0000000000 --- a/spring-hibernate3/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-hibernate3/.project b/spring-hibernate3/.project deleted file mode 100644 index 1184fb6b23..0000000000 --- a/spring-hibernate3/.project +++ /dev/null @@ -1,43 +0,0 @@ - - - spring-hibernate3 - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-hibernate3/.settings/.jsdtscope b/spring-hibernate3/.settings/.jsdtscope deleted file mode 100644 index b46b9207a8..0000000000 --- a/spring-hibernate3/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-hibernate3/.settings/org.eclipse.jdt.core.prefs b/spring-hibernate3/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 13146d5df6..0000000000 --- a/spring-hibernate3/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-hibernate3/.settings/org.eclipse.jdt.ui.prefs b/spring-hibernate3/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-hibernate3/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-hibernate3/.settings/org.eclipse.m2e.core.prefs b/spring-hibernate3/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-hibernate3/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-hibernate3/.settings/org.eclipse.m2e.wtp.prefs b/spring-hibernate3/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-hibernate3/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-hibernate3/.settings/org.eclipse.wst.common.component b/spring-hibernate3/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 14b1679703..0000000000 --- a/spring-hibernate3/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-hibernate3/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-hibernate3/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 9ca0d1c1b7..0000000000 --- a/spring-hibernate3/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/spring-hibernate3/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-hibernate3/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-hibernate3/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-hibernate3/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-hibernate3/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-hibernate3/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-hibernate3/.settings/org.eclipse.wst.validation.prefs b/spring-hibernate3/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-hibernate3/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-hibernate3/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-hibernate3/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-hibernate3/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-hibernate3/.springBeans b/spring-hibernate3/.springBeans deleted file mode 100644 index b854542b58..0000000000 --- a/spring-hibernate3/.springBeans +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - - - - - - - - diff --git a/spring-hibernate3/pom.xml b/spring-hibernate3/pom.xml index d88358168f..59053be596 100644 --- a/spring-hibernate3/pom.xml +++ b/spring-hibernate3/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-hibernate3 0.1-SNAPSHOT @@ -162,13 +162,13 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 3.20.0-GA 3.6.10.Final - 5.1.37 + 5.1.38 7.0.47 @@ -190,13 +190,13 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 - 2.18.1 + 3.5.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-hibernate4/.classpath b/spring-hibernate4/.classpath deleted file mode 100644 index fa5dbd4c0e..0000000000 --- a/spring-hibernate4/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-hibernate4/.project b/spring-hibernate4/.project deleted file mode 100644 index b687191646..0000000000 --- a/spring-hibernate4/.project +++ /dev/null @@ -1,43 +0,0 @@ - - - spring-hibernate4 - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-hibernate4/.settings/.jsdtscope b/spring-hibernate4/.settings/.jsdtscope deleted file mode 100644 index b46b9207a8..0000000000 --- a/spring-hibernate4/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-hibernate4/.settings/org.eclipse.jdt.core.prefs b/spring-hibernate4/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 4561074422..0000000000 --- a/spring-hibernate4/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-hibernate4/.settings/org.eclipse.jdt.ui.prefs b/spring-hibernate4/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-hibernate4/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-hibernate4/.settings/org.eclipse.m2e.core.prefs b/spring-hibernate4/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-hibernate4/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-hibernate4/.settings/org.eclipse.m2e.wtp.prefs b/spring-hibernate4/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-hibernate4/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-hibernate4/.settings/org.eclipse.wst.common.component b/spring-hibernate4/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 6192602079..0000000000 --- a/spring-hibernate4/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-hibernate4/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-hibernate4/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 9ca0d1c1b7..0000000000 --- a/spring-hibernate4/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/spring-hibernate4/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-hibernate4/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-hibernate4/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-hibernate4/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-hibernate4/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-hibernate4/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-hibernate4/.settings/org.eclipse.wst.validation.prefs b/spring-hibernate4/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-hibernate4/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-hibernate4/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-hibernate4/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-hibernate4/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-hibernate4/.settings/org.hibernate.eclipse.console.prefs b/spring-hibernate4/.settings/org.hibernate.eclipse.console.prefs deleted file mode 100644 index 7505c63770..0000000000 --- a/spring-hibernate4/.settings/org.hibernate.eclipse.console.prefs +++ /dev/null @@ -1,3 +0,0 @@ -default.configuration= -eclipse.preferences.version=1 -hibernate3.enabled=true diff --git a/spring-hibernate4/.springBeans b/spring-hibernate4/.springBeans deleted file mode 100644 index b854542b58..0000000000 --- a/spring-hibernate4/.springBeans +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - - - - - - - - diff --git a/spring-hibernate4/README.md b/spring-hibernate4/README.md index 0d1ac1600e..1f18e1d0e8 100644 --- a/spring-hibernate4/README.md +++ b/spring-hibernate4/README.md @@ -5,7 +5,11 @@ ### Relevant Articles: - [Hibernate 4 with Spring](http://www.baeldung.com/hibernate-4-spring) - [The DAO with Spring 3 and Hibernate](http://www.baeldung.com/2011/12/02/the-persistence-layer-with-spring-3-1-and-hibernate/) - +- [Hibernate Pagination](http://www.baeldung.com/hibernate-pagination) +- [Sorting with Hibernate](http://www.baeldung.com/hibernate-sort) +- [Auditing with JPA, Hibernate, and Spring Data JPA](http://www.baeldung.com/database-auditing-jpa) +- [Stored Procedures with Hibernate](http://www.baeldung.com/stored-procedures-with-hibernate-tutorial) +- [Hibernate: save, persist, update, merge, saveOrUpdate](http://www.baeldung.com/hibernate-save-persist-update-merge-saveorupdate/) ### Quick Start diff --git a/spring-hibernate4/pom.xml b/spring-hibernate4/pom.xml index 652636b7cc..4f5cd0c290 100644 --- a/spring-hibernate4/pom.xml +++ b/spring-hibernate4/pom.xml @@ -149,6 +149,13 @@ test + + org.hsqldb + hsqldb + 2.3.4 + test + + @@ -213,15 +220,15 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 1.9.2.RELEASE 3.20.0-GA 4.3.11.Final ${hibernate.version} - 5.1.37 + 5.1.38 8.0.30 1.1 2.2.4 @@ -245,13 +252,13 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 - 2.18.1 + 3.5.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/model/Item.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/model/Item.java new file mode 100644 index 0000000000..b8b012c061 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/model/Item.java @@ -0,0 +1,81 @@ +package com.baeldung.hibernate.criteria.model; + +import java.io.Serializable; + +public class Item implements Serializable { + + private static final long serialVersionUID = 1L; + private Integer itemId; + private String itemName; + private String itemDescription; + private Integer itemPrice; + + // constructors + public Item() { + + } + + public Item(final Integer itemId, final String itemName, final String itemDescription) { + super(); + this.itemId = itemId; + this.itemName = itemName; + this.itemDescription = itemDescription; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((itemId == null) ? 0 : itemId.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Item other = (Item) obj; + if (itemId == null) { + if (other.itemId != null) + return false; + } else if (!itemId.equals(other.itemId)) + return false; + return true; + } + + public Integer getItemId() { + return itemId; + } + + public void setItemId(final Integer itemId) { + this.itemId = itemId; + } + + public String getItemName() { + return itemName; + } + + public void setItemName(final String itemName) { + this.itemName = itemName; + } + + public String getItemDescription() { + return itemDescription; + } + + public Integer getItemPrice() { + return itemPrice; + } + + public void setItemPrice(final Integer itemPrice) { + this.itemPrice = itemPrice; + } + + public void setItemDescription(final String itemDescription) { + this.itemDescription = itemDescription; + } +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java new file mode 100644 index 0000000000..57f32cfe50 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java @@ -0,0 +1,20 @@ +package com.baeldung.hibernate.criteria.util; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.cfg.Configuration; + +public class HibernateUtil { + + @SuppressWarnings("deprecation") + public static Session getHibernateSession() { + + final SessionFactory sf = new Configuration() + .configure("criteria.cfg.xml").buildSessionFactory(); + + // factory = new Configuration().configure().buildSessionFactory(); + final Session session = sf.openSession(); + return session; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java new file mode 100644 index 0000000000..4db94f2ad7 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java @@ -0,0 +1,253 @@ +/** + * ApplicationViewer is the class that starts the application + * First it creates the session object and then creates the + * criteria query. + * + * @author Pritam Banerjee + * @version 1.0 + * @since 07/20/2016 + */ + +package com.baeldung.hibernate.criteria.view; + +import java.util.List; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.LogicalExpression; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Restrictions; + +import com.baeldung.hibernate.criteria.model.Item; +import com.baeldung.hibernate.criteria.util.HibernateUtil; + +public class ApplicationView { + + // default Constructor + public ApplicationView() { + + } + + public boolean checkIfCriteriaTimeLower() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + Transaction tx = null; + + // calculate the time taken by criteria + final long startTimeCriteria = System.nanoTime(); + cr.add(Restrictions.like("itemName", "%item One%")); + final List results = cr.list(); + final long endTimeCriteria = System.nanoTime(); + final long durationCriteria = (endTimeCriteria - startTimeCriteria) / 1000; + + // calculate the time taken by HQL + final long startTimeHQL = System.nanoTime(); + tx = session.beginTransaction(); + final List items = session.createQuery("FROM Item where itemName like '%item One%'").list(); + final long endTimeHQL = System.nanoTime(); + final long durationHQL = (endTimeHQL - startTimeHQL) / 1000; + + if (durationCriteria > durationHQL) { + return false; + } else { + return true; + } + } + + // To get items having price more than 1000 + public String[] greaterThanCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + cr.add(Restrictions.gt("itemPrice", 1000)); + final List greaterThanItemsList = cr.list(); + final String greaterThanItems[] = new String[greaterThanItemsList.size()]; + for (int i = 0; i < greaterThanItemsList.size(); i++) { + greaterThanItems[i] = greaterThanItemsList.get(i).getItemName(); + } + session.close(); + return greaterThanItems; + } + + // To get items having price less than 1000 + public String[] lessThanCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + cr.add(Restrictions.lt("itemPrice", 1000)); + final List lessThanItemsList = cr.list(); + final String lessThanItems[] = new String[lessThanItemsList.size()]; + for (int i = 0; i < lessThanItemsList.size(); i++) { + lessThanItems[i] = lessThanItemsList.get(i).getItemName(); + } + session.close(); + return lessThanItems; + } + + // To get items whose Name start with Chair + public String[] likeCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + + final Criteria cr = session.createCriteria(Item.class); + cr.add(Restrictions.like("itemName", "%chair%")); + final List likeItemsList = cr.list(); + final String likeItems[] = new String[likeItemsList.size()]; + for (int i = 0; i < likeItemsList.size(); i++) { + likeItems[i] = likeItemsList.get(i).getItemName(); + } + session.close(); + return likeItems; + } + + // Case sensitive search + public String[] likeCaseCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + cr.add(Restrictions.ilike("itemName", "%Chair%")); + final List ilikeItemsList = cr.list(); + final String ilikeItems[] = new String[ilikeItemsList.size()]; + for (int i = 0; i < ilikeItemsList.size(); i++) { + ilikeItems[i] = ilikeItemsList.get(i).getItemName(); + } + session.close(); + return ilikeItems; + } + + // To get records having itemPrice in between 100 and 200 + public String[] betweenCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + // To get items having price more than 1000 + cr.add(Restrictions.between("itemPrice", 100, 200)); + final List betweenItemsList = cr.list(); + final String betweenItems[] = new String[betweenItemsList.size()]; + for (int i = 0; i < betweenItemsList.size(); i++) { + betweenItems[i] = betweenItemsList.get(i).getItemName(); + } + session.close(); + return betweenItems; + } + + // To check if the given property is null + public String[] nullCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + cr.add(Restrictions.isNull("itemDescription")); + final List nullItemsList = cr.list(); + final String nullDescItems[] = new String[nullItemsList.size()]; + for (int i = 0; i < nullItemsList.size(); i++) { + nullDescItems[i] = nullItemsList.get(i).getItemName(); + } + session.close(); + return nullDescItems; + } + + // To check if the given property is not null + public String[] notNullCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + cr.add(Restrictions.isNotNull("itemDescription")); + final List notNullItemsList = cr.list(); + final String notNullDescItems[] = new String[notNullItemsList.size()]; + for (int i = 0; i < notNullItemsList.size(); i++) { + notNullDescItems[i] = notNullItemsList.get(i).getItemName(); + } + session.close(); + return notNullDescItems; + } + + // Adding more than one expression in one cr + public String[] twoCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + cr.add(Restrictions.isNull("itemDescription")); + cr.add(Restrictions.like("itemName", "chair%")); + final List notNullItemsList = cr.list(); + final String notNullDescItems[] = new String[notNullItemsList.size()]; + for (int i = 0; i < notNullItemsList.size(); i++) { + notNullDescItems[i] = notNullItemsList.get(i).getItemName(); + } + session.close(); + return notNullDescItems; + } + + // To get items matching with the above defined conditions joined + // with Logical AND + public String[] andLogicalCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + final Criterion greaterThanPrice = Restrictions.gt("itemPrice", 1000); + final Criterion chairItems = Restrictions.like("itemName", "Chair%"); + final LogicalExpression andExample = Restrictions.and(greaterThanPrice, chairItems); + cr.add(andExample); + final List andItemsList = cr.list(); + final String andItems[] = new String[andItemsList.size()]; + for (int i = 0; i < andItemsList.size(); i++) { + andItems[i] = andItemsList.get(i).getItemName(); + } + session.close(); + return andItems; + } + + // To get items matching with the above defined conditions joined + // with Logical OR + public String[] orLogicalCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + final Criterion greaterThanPrice = Restrictions.gt("itemPrice", 1000); + final Criterion chairItems = Restrictions.like("itemName", "Chair%"); + final LogicalExpression orExample = Restrictions.or(greaterThanPrice, chairItems); + cr.add(orExample); + final List orItemsList = cr.list(); + final String orItems[] = new String[orItemsList.size()]; + for (int i = 0; i < orItemsList.size(); i++) { + orItems[i] = orItemsList.get(i).getItemName(); + } + session.close(); + return orItems; + } + + // Sorting example + public String[] sortingCriteria() { + final Session session = HibernateUtil.getHibernateSession(); + final Criteria cr = session.createCriteria(Item.class); + cr.addOrder(Order.asc("itemName")); + cr.addOrder(Order.desc("itemPrice")).list(); + final List sortedItemsList = cr.list(); + final String sortedItems[] = new String[sortedItemsList.size()]; + for (int i = 0; i < sortedItemsList.size(); i++) { + sortedItems[i] = sortedItemsList.get(i).getItemName(); + } + session.close(); + return sortedItems; + } + + // Set projections Row Count + public Long[] projectionRowCount() { + final Session session = HibernateUtil.getHibernateSession(); + final List itemProjected = session.createCriteria(Item.class).setProjection(Projections.rowCount()) + .list(); + final Long projectedRowCount[] = new Long[itemProjected.size()]; + for (int i = 0; i < itemProjected.size(); i++) { + projectedRowCount[i] = itemProjected.get(i); + } + session.close(); + return projectedRowCount; + } + + // Set projections average of itemPrice + public Double[] projectionAverage() { + final Session session = HibernateUtil.getHibernateSession(); + final List avgItemPriceList = session.createCriteria(Item.class) + .setProjection(Projections.projectionList().add(Projections.avg("itemPrice"))).list(); + + final Double avgItemPrice[] = new Double[avgItemPriceList.size()]; + for (int i = 0; i < avgItemPriceList.size(); i++) { + avgItemPrice[i] = (Double) avgItemPriceList.get(i); + } + session.close(); + return avgItemPrice; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java new file mode 100644 index 0000000000..ec8dc32200 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java @@ -0,0 +1,58 @@ +package com.baeldung.hibernate.fetching.model; + +import javax.persistence.*; +import java.io.Serializable; +import java.sql.Date; + +@Entity +@Table (name = "USER_ORDER") +public class OrderDetail implements Serializable{ + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue + @Column(name="ORDER_ID") + private Long orderId; + + public OrderDetail(){ + } + + public OrderDetail(Date orderDate, String orderDesc) { + super(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((orderId == null) ? 0 : orderId.hashCode()); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + OrderDetail other = (OrderDetail) obj; + if (orderId == null) { + if (other.orderId != null) + return false; + } else if (!orderId.equals(other.orderId)) + return false; + + return true; + } + + public Long getOrderId() { + return orderId; + } + public void setOrderId(Long orderId) { + this.orderId = orderId; + } +} + + diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java new file mode 100644 index 0000000000..22b4fdc76c --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java @@ -0,0 +1,71 @@ +package com.baeldung.hibernate.fetching.model; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +@Entity +@Table (name = "USER") +public class UserEager implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue + @Column(name="USER_ID") + private Long userId; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "user") + private Set orderDetail = new HashSet(); + + public UserEager() { + } + + public UserEager(final Long userId) { + super(); + this.userId = userId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((userId == null) ? 0 : userId.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final UserEager other = (UserEager) obj; + if (userId == null) { + if (other.userId != null) + return false; + } else if (!userId.equals(other.userId)) + return false; + return true; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(final Long userId) { + this.userId = userId; + } + + public Set getOrderDetail() { + return orderDetail; + } + + public void setOrderDetail(Set orderDetail) { + this.orderDetail = orderDetail; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java new file mode 100644 index 0000000000..5038fb90ef --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java @@ -0,0 +1,72 @@ +package com.baeldung.hibernate.fetching.model; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +@Entity +@Table (name = "USER") +public class UserLazy implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue + @Column(name="USER_ID") + private Long userId; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "user") + private Set orderDetail = new HashSet(); + + public UserLazy() { + } + + public UserLazy(final Long userId) { + super(); + this.userId = userId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((userId == null) ? 0 : userId.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final UserLazy other = (UserLazy) obj; + if (userId == null) { + if (other.userId != null) + return false; + } else if (!userId.equals(other.userId)) + return false; + return true; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(final Long userId) { + this.userId = userId; + } + + + public Set getOrderDetail() { + return orderDetail; + } + + public void setOrderDetail(Set orderDetail) { + this.orderDetail = orderDetail; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java new file mode 100644 index 0000000000..bbd7729232 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java @@ -0,0 +1,32 @@ +package com.baeldung.hibernate.fetching.util; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.cfg.Configuration; + +public class HibernateUtil { + + @SuppressWarnings("deprecation") + public static Session getHibernateSession(String fetchMethod) { + //two config files are there + //one with lazy loading enabled + //another lazy = false + SessionFactory sf; + if ("lazy".equals(fetchMethod)) { + sf = new Configuration().configure("fetchingLazy.cfg.xml").buildSessionFactory(); + } else { + sf = new Configuration().configure("fetching.cfg.xml").buildSessionFactory(); + } + + // fetching.cfg.xml is used for this example + return sf.openSession(); + } + + public static Session getHibernateSession() { + return new Configuration() + .configure("fetching.cfg.xml") + .buildSessionFactory() + .openSession(); + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java new file mode 100644 index 0000000000..1a5142c5c2 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java @@ -0,0 +1,68 @@ +package com.baeldung.hibernate.fetching.view; + +import com.baeldung.hibernate.fetching.model.OrderDetail; +import com.baeldung.hibernate.fetching.model.UserEager; +import com.baeldung.hibernate.fetching.model.UserLazy; +import com.baeldung.hibernate.fetching.util.HibernateUtil; +import org.hibernate.Session; +import org.hibernate.Transaction; + +import java.util.List; +import java.util.Set; + +public class FetchingAppView { + + public FetchingAppView() { + + } + + // lazily loaded + public Set lazyLoaded() { + final Session sessionLazy = HibernateUtil.getHibernateSession("lazy"); + List users = sessionLazy.createQuery("From UserLazy").list(); + UserLazy userLazyLoaded = users.get(3); + // since data is lazyloaded so data won't be initialized + return (userLazyLoaded.getOrderDetail()); + } + + // eagerly loaded + public Set eagerLoaded() { + final Session sessionEager = HibernateUtil.getHibernateSession(); + // data should be loaded in the following line + // also note the queries generated + List user = sessionEager.createQuery("From UserEager").list(); + UserEager userEagerLoaded = user.get(3); + return userEagerLoaded.getOrderDetail(); + } + + // creates test data + // call this method to create the data in the database + public void createTestData() { + + final Session session = HibernateUtil.getHibernateSession("lazy"); + Transaction tx = session.beginTransaction(); + final UserLazy user1 = new UserLazy(); + final UserLazy user2 = new UserLazy(); + final UserLazy user3 = new UserLazy(); + + session.save(user1); + session.save(user2); + session.save(user3); + + final OrderDetail order1 = new OrderDetail(); + final OrderDetail order2 = new OrderDetail(); + final OrderDetail order3 = new OrderDetail(); + final OrderDetail order4 = new OrderDetail(); + final OrderDetail order5 = new OrderDetail(); + + session.saveOrUpdate(order1); + session.saveOrUpdate(order2); + session.saveOrUpdate(order3); + session.saveOrUpdate(order4); + session.saveOrUpdate(order5); + + tx.commit(); + session.close(); + + } +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java index 6b48c1fa66..bdd48d6aa6 100644 --- a/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java @@ -11,93 +11,97 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import javax.persistence.NamedNativeQueries; +import javax.persistence.NamedNativeQuery; import org.hibernate.envers.Audited; +@NamedNativeQueries({ + @NamedNativeQuery(name = "callGetAllFoos", query = "CALL GetAllFoos()", resultClass = Foo.class), + @NamedNativeQuery(name = "callGetFoosByName", query = "CALL GetFoosByName(:fooName)", resultClass = Foo.class) }) @Entity @Audited // @Proxy(lazy = false) public class Foo implements Serializable { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - @Column(name = "id") - private long id; + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "id") + private long id; - @Column(name = "name") - private String name; + @Column(name = "name") + private String name; - @ManyToOne(targetEntity = Bar.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JoinColumn(name = "BAR_ID") - private Bar bar = new Bar(); + @ManyToOne(targetEntity = Bar.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "BAR_ID") + private Bar bar = new Bar(); - public Foo() { - super(); - } + public Foo() { + super(); + } - public Foo(final String name) { - super(); - this.name = name; - } + public Foo(final String name) { + super(); + this.name = name; + } - // + // - public Bar getBar() { - return bar; - } + public Bar getBar() { + return bar; + } - public void setBar(final Bar bar) { - this.bar = bar; - } + public void setBar(final Bar bar) { + this.bar = bar; + } - public long getId() { - return id; - } + public long getId() { + return id; + } - public void setId(final long id) { - this.id = id; - } + public void setId(final long id) { + this.id = id; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(final String name) { - this.name = name; - } + public void setName(final String name) { + this.name = name; + } - // + // - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final Foo other = (Foo) obj; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Foo [name=").append(name).append("]"); - return builder.toString(); - } + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [name=").append(name).append("]"); + return builder.toString(); + } } diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Person.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Person.java new file mode 100644 index 0000000000..6a95a7acf5 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Person.java @@ -0,0 +1,31 @@ +package com.baeldung.persistence.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Person { + + @Id + @GeneratedValue + private Long id; + + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/spring-hibernate4/src/main/resources/criteria.cfg.xml b/spring-hibernate4/src/main/resources/criteria.cfg.xml new file mode 100644 index 0000000000..a39a32e151 --- /dev/null +++ b/spring-hibernate4/src/main/resources/criteria.cfg.xml @@ -0,0 +1,17 @@ + + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + iamtheking + org.hibernate.dialect.MySQLDialect + true + + + \ No newline at end of file diff --git a/spring-hibernate4/src/main/resources/criteria_create_queries.sql b/spring-hibernate4/src/main/resources/criteria_create_queries.sql new file mode 100644 index 0000000000..3a627dd38c --- /dev/null +++ b/spring-hibernate4/src/main/resources/criteria_create_queries.sql @@ -0,0 +1,7 @@ +CREATE TABLE `item` ( + `ITEM_ID` int(11) NOT NULL AUTO_INCREMENT, + `ITEM_DESC` varchar(100) DEFAULT NULL, + `ITEM_PRICE` int(11) NOT NULL, + `ITEM_NAME` varchar(255) NOT NULL, + PRIMARY KEY (`ITEM_ID`) +) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=latin1; diff --git a/spring-hibernate4/src/main/resources/fetching.cfg.xml b/spring-hibernate4/src/main/resources/fetching.cfg.xml new file mode 100644 index 0000000000..1b9a4a191c --- /dev/null +++ b/spring-hibernate4/src/main/resources/fetching.cfg.xml @@ -0,0 +1,20 @@ + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + iamtheking + org.hibernate.dialect.MySQLDialect + true + validate + + + + + + \ No newline at end of file diff --git a/spring-hibernate4/src/main/resources/fetchingLazy.cfg.xml b/spring-hibernate4/src/main/resources/fetchingLazy.cfg.xml new file mode 100644 index 0000000000..c5f608e1a7 --- /dev/null +++ b/spring-hibernate4/src/main/resources/fetchingLazy.cfg.xml @@ -0,0 +1,17 @@ + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + iamtheking + org.hibernate.dialect.MySQLDialect + true + + + + \ No newline at end of file diff --git a/spring-hibernate4/src/main/resources/fetching_create_queries.sql b/spring-hibernate4/src/main/resources/fetching_create_queries.sql new file mode 100644 index 0000000000..b36d9828f1 --- /dev/null +++ b/spring-hibernate4/src/main/resources/fetching_create_queries.sql @@ -0,0 +1,14 @@ +CREATE TABLE `user` ( + `user_id` int(10) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`user_id`) +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1 ; + + +CREATE TABLE `user_order` ( + `ORDER_ID` int(10) NOT NULL AUTO_INCREMENT, + `USER_ID` int(10) NOT NULL DEFAULT '0', + PRIMARY KEY (`ORDER_ID`,`USER_ID`), + KEY `USER_ID` (`USER_ID`), + CONSTRAINT `user_order_ibfk_1` FOREIGN KEY (`USER_ID`) REFERENCES `USER` (`user_id`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1; + diff --git a/spring-hibernate4/src/main/resources/insert_statements.sql b/spring-hibernate4/src/main/resources/insert_statements.sql new file mode 100644 index 0000000000..ae008f29bc --- /dev/null +++ b/spring-hibernate4/src/main/resources/insert_statements.sql @@ -0,0 +1,31 @@ +insert into item (item_id, item_name, item_desc, item_price) +values(1,'item One', 'test 1', 35.12); + +insert into item (item_id, item_name, item_desc, item_price) +values(2,'Pogo stick', 'Pogo stick', 466.12); +insert into item (item_id, item_name, item_desc, item_price) +values(3,'Raft', 'Raft', 345.12); + +insert into item (item_id, item_name, item_desc, item_price) +values(4,'Skate Board', 'Skating', 135.71); + +insert into item (item_id, item_name, item_desc, item_price) +values(5,'Umbrella', 'Umbrella for Rain', 619.25); + +insert into item (item_id, item_name, item_desc, item_price) +values(6,'Glue', 'Glue for home', 432.73); + +insert into item (item_id, item_name, item_desc, item_price) +values(7,'Paint', 'Paint for Room', 1311.40); + +insert into item (item_id, item_name, item_desc, item_price) +values(8,'Red paint', 'Red paint for room', 1135.71); + +insert into item (item_id, item_name, item_desc, item_price) +values(9,'Household Chairs', 'Chairs for house', 25.71); + +insert into item (item_id, item_name, item_desc, item_price) +values(10,'Office Chairs', 'Chairs for office', 395.98); + +insert into item (item_id, item_name, item_desc, item_price) +values(11,'Outdoor Chairs', 'Chairs for outdoor activities', 1234.36); diff --git a/spring-hibernate4/src/main/resources/stored_procedure.sql b/spring-hibernate4/src/main/resources/stored_procedure.sql new file mode 100644 index 0000000000..8e1bdf57dd --- /dev/null +++ b/spring-hibernate4/src/main/resources/stored_procedure.sql @@ -0,0 +1,20 @@ +DELIMITER // + CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255)) + LANGUAGE SQL + DETERMINISTIC + SQL SECURITY DEFINER + BEGIN + SELECT * FROM foo WHERE name = fooName; + END // +DELIMITER ; + + +DELIMITER // + CREATE PROCEDURE GetAllFoos() + LANGUAGE SQL + DETERMINISTIC + SQL SECURITY DEFINER + BEGIN + SELECT * FROM foo; + END // +DELIMITER ; \ No newline at end of file diff --git a/spring-hibernate4/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTest.java b/spring-hibernate4/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTest.java new file mode 100644 index 0000000000..3bd8c5ee00 --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTest.java @@ -0,0 +1,191 @@ +package com.baeldung.hibernate.criteria; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.hibernate.Session; +import org.junit.Test; + +import com.baeldung.hibernate.criteria.model.Item; +import com.baeldung.hibernate.criteria.util.HibernateUtil; +import com.baeldung.hibernate.criteria.view.ApplicationView; + +public class HibernateCriteriaTest { + + final private ApplicationView av = new ApplicationView(); + + @Test + public void testPerformanceOfCriteria() { + assertTrue(av.checkIfCriteriaTimeLower()); + } + + @Test + public void testLikeCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedLikeList = session.createQuery("From Item where itemName like '%chair%'").list(); + final String expectedLikeItems[] = new String[expectedLikeList.size()]; + for (int i = 0; i < expectedLikeList.size(); i++) { + expectedLikeItems[i] = expectedLikeList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedLikeItems, av.likeCriteria()); + } + + @Test + public void testILikeCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedChairCaseList = session.createQuery("From Item where itemName like '%Chair%'").list(); + final String expectedChairCaseItems[] = new String[expectedChairCaseList.size()]; + for (int i = 0; i < expectedChairCaseList.size(); i++) { + expectedChairCaseItems[i] = expectedChairCaseList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedChairCaseItems, av.likeCaseCriteria()); + + } + + @Test + public void testNullCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedIsNullDescItemsList = session.createQuery("From Item where itemDescription is null") + .list(); + final String expectedIsNullDescItems[] = new String[expectedIsNullDescItemsList.size()]; + for (int i = 0; i < expectedIsNullDescItemsList.size(); i++) { + expectedIsNullDescItems[i] = expectedIsNullDescItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedIsNullDescItems, av.nullCriteria()); + } + + @Test + public void testIsNotNullCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedIsNotNullDescItemsList = session + .createQuery("From Item where itemDescription is not null").list(); + final String expectedIsNotNullDescItems[] = new String[expectedIsNotNullDescItemsList.size()]; + for (int i = 0; i < expectedIsNotNullDescItemsList.size(); i++) { + expectedIsNotNullDescItems[i] = expectedIsNotNullDescItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedIsNotNullDescItems, av.notNullCriteria()); + + } + + @Test + public void testAverageProjection() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedAvgProjItemsList = session.createQuery("Select avg(itemPrice) from Item item") + .list(); + + final Double expectedAvgProjItems[] = new Double[expectedAvgProjItemsList.size()]; + for (int i = 0; i < expectedAvgProjItemsList.size(); i++) { + expectedAvgProjItems[i] = expectedAvgProjItemsList.get(i); + } + session.close(); + assertArrayEquals(expectedAvgProjItems, av.projectionAverage()); + + } + + @Test + public void testRowCountProjection() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedCountProjItemsList = session.createQuery("Select count(*) from Item").list(); + final Long expectedCountProjItems[] = new Long[expectedCountProjItemsList.size()]; + for (int i = 0; i < expectedCountProjItemsList.size(); i++) { + expectedCountProjItems[i] = expectedCountProjItemsList.get(i); + } + session.close(); + assertArrayEquals(expectedCountProjItems, av.projectionRowCount()); + } + + @Test + public void testOrCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedOrCritItemsList = session + .createQuery("From Item where itemPrice>1000 or itemName like 'Chair%'").list(); + final String expectedOrCritItems[] = new String[expectedOrCritItemsList.size()]; + for (int i = 0; i < expectedOrCritItemsList.size(); i++) { + expectedOrCritItems[i] = expectedOrCritItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedOrCritItems, av.orLogicalCriteria()); + } + + @Test + public void testAndCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedAndCritItemsList = session + .createQuery("From Item where itemPrice>1000 and itemName like 'Chair%'").list(); + final String expectedAndCritItems[] = new String[expectedAndCritItemsList.size()]; + for (int i = 0; i < expectedAndCritItemsList.size(); i++) { + expectedAndCritItems[i] = expectedAndCritItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedAndCritItems, av.andLogicalCriteria()); + } + + @Test + public void testMultiCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedMultiCritItemsList = session + .createQuery("From Item where itemDescription is null and itemName like'chair%'").list(); + final String expectedMultiCritItems[] = new String[expectedMultiCritItemsList.size()]; + for (int i = 0; i < expectedMultiCritItemsList.size(); i++) { + expectedMultiCritItems[i] = expectedMultiCritItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedMultiCritItems, av.twoCriteria()); + } + + @Test + public void testSortCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedSortCritItemsList = session + .createQuery("From Item order by itemName asc, itemPrice desc").list(); + final String expectedSortCritItems[] = new String[expectedSortCritItemsList.size()]; + for (int i = 0; i < expectedSortCritItemsList.size(); i++) { + expectedSortCritItems[i] = expectedSortCritItemsList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedSortCritItems, av.sortingCriteria()); + } + + @Test + public void testGreaterThanCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedGreaterThanList = session.createQuery("From Item where itemPrice>1000").list(); + final String expectedGreaterThanItems[] = new String[expectedGreaterThanList.size()]; + for (int i = 0; i < expectedGreaterThanList.size(); i++) { + expectedGreaterThanItems[i] = expectedGreaterThanList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedGreaterThanItems, av.greaterThanCriteria()); + } + + @Test + public void testLessThanCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedLessList = session.createQuery("From Item where itemPrice<1000").list(); + final String expectedLessThanItems[] = new String[expectedLessList.size()]; + for (int i = 0; i < expectedLessList.size(); i++) { + expectedLessThanItems[i] = expectedLessList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedLessThanItems, av.lessThanCriteria()); + } + + @Test + public void betweenCriteriaQuery() { + final Session session = HibernateUtil.getHibernateSession(); + final List expectedBetweenList = session.createQuery("From Item where itemPrice between 100 and 200") + .list(); + final String expectedPriceBetweenItems[] = new String[expectedBetweenList.size()]; + for (int i = 0; i < expectedBetweenList.size(); i++) { + expectedPriceBetweenItems[i] = expectedBetweenList.get(i).getItemName(); + } + session.close(); + assertArrayEquals(expectedPriceBetweenItems, av.betweenCriteria()); + } +} diff --git a/spring-hibernate4/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java b/spring-hibernate4/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java new file mode 100644 index 0000000000..8341df9fcb --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java @@ -0,0 +1,15 @@ +package com.baeldung.hibernate.criteria; + +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; + +public class HibernateCriteriaTestRunner { + + public static void main(final String[] args) { + Result result = JUnitCore.runClasses(HibernateCriteriaTestSuite.class); + for (Failure failure : result.getFailures()) { + + } + } +} diff --git a/spring-hibernate4/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java b/spring-hibernate4/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java new file mode 100644 index 0000000000..ab27a6ba82 --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java @@ -0,0 +1,11 @@ +package com.baeldung.hibernate.criteria; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ HibernateCriteriaTest.class }) + +public class HibernateCriteriaTestSuite { + +} diff --git a/spring-hibernate4/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingTest.java b/spring-hibernate4/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingTest.java new file mode 100644 index 0000000000..a650f8eb37 --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingTest.java @@ -0,0 +1,43 @@ +package com.baeldung.hibernate.fetching; + +import com.baeldung.hibernate.fetching.model.OrderDetail; +import com.baeldung.hibernate.fetching.view.FetchingAppView; +import org.hibernate.Hibernate; +import org.junit.Before; +import org.junit.Test; + +import java.util.Set; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class HibernateFetchingTest { + + + //this loads sample data in the database + @Before + public void addFecthingTestData(){ + FetchingAppView fav = new FetchingAppView(); + fav.createTestData(); + } + + //testLazyFetching() tests the lazy loading + //Since it lazily loaded so orderDetalSetLazy won't + //be initialized + @Test + public void testLazyFetching() { + FetchingAppView fav = new FetchingAppView(); + Set orderDetalSetLazy = fav.lazyLoaded(); + assertFalse(Hibernate.isInitialized(orderDetalSetLazy)); + } + + //testEagerFetching() tests the eager loading + //Since it eagerly loaded so orderDetalSetLazy would + //be initialized + @Test + public void testEagerFetching() { + FetchingAppView fav = new FetchingAppView(); + Set orderDetalSetEager = fav.eagerLoaded(); + assertTrue(Hibernate.isInitialized(orderDetalSetEager)); + } +} diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java index c107a221d6..f5c45a5d6f 100644 --- a/spring-hibernate4/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java @@ -1,20 +1,24 @@ package com.baeldung.persistence; -import com.baeldung.persistence.hibernate.FooPaginationPersistenceIntegrationTest; -import com.baeldung.persistence.hibernate.FooSortingPersistenceServiceTest; -import com.baeldung.persistence.service.FooServicePersistenceIntegrationTest; -import com.baeldung.persistence.service.FooServiceBasicPersistenceIntegrationTest; -import com.baeldung.persistence.service.ParentServicePersistenceIntegrationTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; +import com.baeldung.persistence.audit.AuditTestSuite; +import com.baeldung.persistence.hibernate.FooPaginationPersistenceIntegrationTest; +import com.baeldung.persistence.hibernate.FooSortingPersistenceIntegrationTest; +import com.baeldung.persistence.service.FooServiceBasicPersistenceIntegrationTest; +import com.baeldung.persistence.service.FooServicePersistenceIntegrationTest; +import com.baeldung.persistence.service.ParentServicePersistenceIntegrationTest; + @RunWith(Suite.class) @Suite.SuiteClasses({ // @formatter:off - FooServiceBasicPersistenceIntegrationTest.class + AuditTestSuite.class + ,FooServiceBasicPersistenceIntegrationTest.class ,FooPaginationPersistenceIntegrationTest.class ,FooServicePersistenceIntegrationTest.class ,ParentServicePersistenceIntegrationTest.class - ,FooSortingPersistenceServiceTest.class + ,FooSortingPersistenceIntegrationTest.class + }) // @formatter:on public class IntegrationTestSuite { // diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java new file mode 100644 index 0000000000..0f76526960 --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java @@ -0,0 +1,173 @@ +package com.baeldung.persistence.hibernate; + +import static org.junit.Assert.assertNull; + +import java.util.List; +import java.util.Set; + +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.PersistenceConfig; +import org.hibernate.Criteria; +import org.hibernate.NullPrecedence; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.Order; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@SuppressWarnings("unchecked") +public class FooSortingPersistenceIntegrationTest { + + @Autowired + private SessionFactory sessionFactory; + + private Session session; + + @Before + public void before() { + session = sessionFactory.openSession(); + + session.beginTransaction(); + + final FooFixtures fooData = new FooFixtures(sessionFactory); + fooData.createBars(); + } + + @After + public void after() { + session.getTransaction().commit(); + session.close(); + } + + @Test + public final void whenHQlSortingByOneAttribute_thenPrintSortedResults() { + final String hql = "FROM Foo f ORDER BY f.name"; + final Query query = session.createQuery(hql); + final List fooList = query.list(); + for (final Foo foo : fooList) { + System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + } + } + + @Test + public final void whenHQlSortingByStringNullLast_thenLastNull() { + final String hql = "FROM Foo f ORDER BY f.name NULLS LAST"; + final Query query = session.createQuery(hql); + final List fooList = query.list(); + + assertNull(fooList.get(fooList.toArray().length - 1).getName()); + for (final Foo foo : fooList) { + System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + } + } + + @Test + public final void whenSortingByStringNullsFirst_thenReturnNullsFirst() { + final String hql = "FROM Foo f ORDER BY f.name NULLS FIRST"; + final Query query = session.createQuery(hql); + final List fooList = query.list(); + assertNull(fooList.get(0).getName()); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + + } + } + + @Test + public final void whenHQlSortingByOneAttribute_andOrderDirection_thenPrintSortedResults() { + final String hql = "FROM Foo f ORDER BY f.name ASC"; + final Query query = session.createQuery(hql); + final List fooList = query.list(); + for (final Foo foo : fooList) { + System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + } + } + + @Test + public final void whenHQlSortingByMultipleAttributes_thenSortedResults() { + final String hql = "FROM Foo f ORDER BY f.name, f.id"; + final Query query = session.createQuery(hql); + final List fooList = query.list(); + for (final Foo foo : fooList) { + System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + } + } + + @Test + public final void whenHQlSortingByMultipleAttributes_andOrderDirection_thenPrintSortedResults() { + final String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC"; + final Query query = session.createQuery(hql); + final List fooList = query.list(); + for (final Foo foo : fooList) { + System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); + } + } + + @Test + public final void whenHQLCriteriaSortingByOneAttr_thenPrintSortedResults() { + final Criteria criteria = session.createCriteria(Foo.class, "FOO"); + criteria.addOrder(Order.asc("id")); + final List fooList = criteria.list(); + for (final Foo foo : fooList) { + System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + } + } + + @Test + public final void whenHQLCriteriaSortingByMultipAttr_thenSortedResults() { + final Criteria criteria = session.createCriteria(Foo.class, "FOO"); + criteria.addOrder(Order.asc("name")); + criteria.addOrder(Order.asc("id")); + final List fooList = criteria.list(); + for (final Foo foo : fooList) { + System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + } + } + + @Test + public final void whenCriteriaSortingStringNullsLastAsc_thenNullsLast() { + final Criteria criteria = session.createCriteria(Foo.class, "FOO"); + criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST)); + final List fooList = criteria.list(); + assertNull(fooList.get(fooList.toArray().length - 1).getName()); + for (final Foo foo : fooList) { + System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + } + } + + @Test + public final void whenCriteriaSortingStringNullsFirstDesc_thenNullsFirst() { + final Criteria criteria = session.createCriteria(Foo.class, "FOO"); + criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST)); + final List fooList = criteria.list(); + assertNull(fooList.get(0).getName()); + for (final Foo foo : fooList) { + System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); + } + } + + @Test + public final void whenSortingBars_thenBarsWithSortedFoos() { + final String hql = "FROM Bar b ORDER BY b.id"; + final Query query = session.createQuery(hql); + final List barList = query.list(); + for (final Bar bar : barList) { + final Set fooSet = bar.getFooSet(); + System.out.println("Bar Id:" + bar.getId()); + for (final Foo foo : fooSet) { + System.out.println("FooName:" + foo.getName()); + } + } + } + +} diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceServiceTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceServiceTest.java deleted file mode 100644 index c890e08d15..0000000000 --- a/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceServiceTest.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.baeldung.persistence.hibernate; - -import static org.junit.Assert.assertNull; - -import java.util.List; -import java.util.Set; - -import com.baeldung.persistence.model.Bar; -import com.baeldung.persistence.model.Foo; -import com.baeldung.spring.PersistenceConfig; -import org.hibernate.Criteria; -import org.hibernate.NullPrecedence; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.criterion.Order; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.AnnotationConfigContextLoader; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) -@SuppressWarnings("unchecked") -public class FooSortingPersistenceServiceTest { - - @Autowired - private SessionFactory sessionFactory; - - private Session session; - - @Before - public void before() { - session = sessionFactory.openSession(); - - session.beginTransaction(); - - final FooFixtures fooData = new FooFixtures(sessionFactory); - fooData.createBars(); - } - - @After - public void after() { - session.getTransaction().commit(); - session.close(); - } - - @Test - public final void whenHQlSortingByOneAttribute_thenPrintSortedResults() { - final String hql = "FROM Foo f ORDER BY f.name"; - final Query query = session.createQuery(hql); - final List fooList = query.list(); - for (final Foo foo : fooList) { - System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); - } - } - - @Test - public final void whenHQlSortingByStringNullLast_thenLastNull() { - final String hql = "FROM Foo f ORDER BY f.name NULLS LAST"; - final Query query = session.createQuery(hql); - final List fooList = query.list(); - - assertNull(fooList.get(fooList.toArray().length - 1).getName()); - for (final Foo foo : fooList) { - System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); - } - } - - @Test - public final void whenSortingByStringNullsFirst_thenReturnNullsFirst() { - final String hql = "FROM Foo f ORDER BY f.name NULLS FIRST"; - final Query query = session.createQuery(hql); - final List fooList = query.list(); - assertNull(fooList.get(0).getName()); - for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName()); - - } - } - - @Test - public final void whenHQlSortingByOneAttribute_andOrderDirection_thenPrintSortedResults() { - final String hql = "FROM Foo f ORDER BY f.name ASC"; - final Query query = session.createQuery(hql); - final List fooList = query.list(); - for (final Foo foo : fooList) { - System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); - } - } - - @Test - public final void whenHQlSortingByMultipleAttributes_thenSortedResults() { - final String hql = "FROM Foo f ORDER BY f.name, f.id"; - final Query query = session.createQuery(hql); - final List fooList = query.list(); - for (final Foo foo : fooList) { - System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); - } - } - - @Test - public final void whenHQlSortingByMultipleAttributes_andOrderDirection_thenPrintSortedResults() { - final String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC"; - final Query query = session.createQuery(hql); - final List fooList = query.list(); - for (final Foo foo : fooList) { - System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId()); - } - } - - @Test - public final void whenHQLCriteriaSortingByOneAttr_thenPrintSortedResults() { - final Criteria criteria = session.createCriteria(Foo.class, "FOO"); - criteria.addOrder(Order.asc("id")); - final List fooList = criteria.list(); - for (final Foo foo : fooList) { - System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); - } - } - - @Test - public final void whenHQLCriteriaSortingByMultipAttr_thenSortedResults() { - final Criteria criteria = session.createCriteria(Foo.class, "FOO"); - criteria.addOrder(Order.asc("name")); - criteria.addOrder(Order.asc("id")); - final List fooList = criteria.list(); - for (final Foo foo : fooList) { - System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); - } - } - - @Test - public final void whenCriteriaSortingStringNullsLastAsc_thenNullsLast() { - final Criteria criteria = session.createCriteria(Foo.class, "FOO"); - criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST)); - final List fooList = criteria.list(); - assertNull(fooList.get(fooList.toArray().length - 1).getName()); - for (final Foo foo : fooList) { - System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); - } - } - - @Test - public final void whenCriteriaSortingStringNullsFirstDesc_thenNullsFirst() { - final Criteria criteria = session.createCriteria(Foo.class, "FOO"); - criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST)); - final List fooList = criteria.list(); - assertNull(fooList.get(0).getName()); - for (final Foo foo : fooList) { - System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); - } - } - - @Test - public final void whenSortingBars_thenBarsWithSortedFoos() { - final String hql = "FROM Bar b ORDER BY b.id"; - final Query query = session.createQuery(hql); - final List barList = query.list(); - for (final Bar bar : barList) { - final Set fooSet = bar.getFooSet(); - System.out.println("Bar Id:" + bar.getId()); - for (final Foo foo : fooSet) { - System.out.println("FooName:" + foo.getName()); - } - } - } - -} diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java new file mode 100644 index 0000000000..aadaefbe44 --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java @@ -0,0 +1,272 @@ +package com.baeldung.persistence.save; + + +import com.baeldung.persistence.model.Person; +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.dialect.HSQLDialect; +import org.hibernate.service.ServiceRegistry; +import org.junit.*; + +import static org.junit.Assert.*; + +/** + * Testing specific implementation details for different methods: + * persist, save, merge, update, saveOrUpdate. + */ +public class SaveMethodsTest { + + private static SessionFactory sessionFactory; + + private Session session; + + @BeforeClass + public static void beforeTests() { + Configuration configuration = new Configuration() + .addAnnotatedClass(Person.class) + .setProperty("hibernate.dialect", HSQLDialect.class.getName()) + .setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName()) + .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test") + .setProperty("hibernate.connection.username", "sa") + .setProperty("hibernate.connection.password", "") + .setProperty("hibernate.hbm2ddl.auto", "update"); + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings( + configuration.getProperties()).build(); + sessionFactory = configuration.buildSessionFactory(serviceRegistry); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + + @Test + public void whenPersistTransient_thenSavedToDatabaseOnCommit() { + + Person person = new Person(); + person.setName("John"); + session.persist(person); + + session.getTransaction().commit(); + session.close(); + + session = sessionFactory.openSession(); + session.beginTransaction(); + + assertNotNull(session.get(Person.class, person.getId())); + + } + + @Test + public void whenPersistPersistent_thenNothingHappens() { + + Person person = new Person(); + person.setName("John"); + + session.persist(person); + Long id1 = person.getId(); + + session.persist(person); + Long id2 = person.getId(); + + assertEquals(id1, id2); + } + + @Test(expected = HibernateException.class) + public void whenPersistDetached_thenThrowsException() { + + Person person = new Person(); + person.setName("John"); + session.persist(person); + session.evict(person); + + session.persist(person); + + } + + @Test + public void whenSaveTransient_thenIdGeneratedImmediately() { + + Person person = new Person(); + person.setName("John"); + + assertNull(person.getId()); + + Long id = (Long) session.save(person); + + assertNotNull(id); + + session.getTransaction().commit(); + session.close(); + + assertEquals(id, person.getId()); + + session = sessionFactory.openSession(); + session.beginTransaction(); + + assertNotNull(session.get(Person.class, person.getId())); + + } + + @Test + public void whenSavePersistent_thenNothingHappens() { + + Person person = new Person(); + person.setName("John"); + Long id1 = (Long) session.save(person); + Long id2 = (Long) session.save(person); + assertEquals(id1, id2); + + } + + @Test + public void whenSaveDetached_thenNewInstancePersisted() { + + Person person = new Person(); + person.setName("John"); + Long id1 = (Long) session.save(person); + session.evict(person); + + Long id2 = (Long) session.save(person); + assertNotEquals(id1, id2); + + } + + @Test + public void whenMergeDetached_thenEntityUpdatedFromDatabase() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + session.evict(person); + + person.setName("Mary"); + Person mergedPerson = (Person) session.merge(person); + + assertNotSame(person, mergedPerson); + assertEquals("Mary", mergedPerson.getName()); + + } + + @Test + public void whenMergeTransient_thenNewEntitySavedToDatabase() { + + Person person = new Person(); + person.setName("John"); + Person mergedPerson = (Person) session.merge(person); + + session.getTransaction().commit(); + session.beginTransaction(); + + assertNull(person.getId()); + assertNotNull(mergedPerson.getId()); + + } + + @Test + public void whenMergePersistent_thenReturnsSameObject() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + + Person mergedPerson = (Person) session.merge(person); + + assertSame(person, mergedPerson); + + } + + @Test + public void whenUpdateDetached_thenEntityUpdatedFromDatabase() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + session.evict(person); + + person.setName("Mary"); + session.update(person); + assertEquals("Mary", person.getName()); + + } + + @Test(expected = HibernateException.class) + public void whenUpdateTransient_thenThrowsException() { + + Person person = new Person(); + person.setName("John"); + session.update(person); + + } + + @Test + public void whenUpdatePersistent_thenNothingHappens() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + + session.update(person); + + } + + @Test + public void whenSaveOrUpdateDetached_thenEntityUpdatedFromDatabase() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + session.evict(person); + + person.setName("Mary"); + session.saveOrUpdate(person); + assertEquals("Mary", person.getName()); + + } + + @Test + public void whenSaveOrUpdateTransient_thenSavedToDatabaseOnCommit() { + + Person person = new Person(); + person.setName("John"); + session.saveOrUpdate(person); + + session.getTransaction().commit(); + session.close(); + + session = sessionFactory.openSession(); + session.beginTransaction(); + + assertNotNull(session.get(Person.class, person.getId())); + + + } + + @Test + public void whenSaveOrUpdatePersistent_thenNothingHappens() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + + session.saveOrUpdate(person); + + } + + @After + public void tearDown() { + session.getTransaction().commit(); + session.close(); + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } + +} diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java new file mode 100644 index 0000000000..238b228101 --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java @@ -0,0 +1,126 @@ +package com.baeldung.persistence.service; + +import java.util.List; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.junit.Assert.assertEquals; + +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.exception.SQLGrammarException; +import org.junit.After; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.PersistenceConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class) +public class FooStoredProceduresIntegrationTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(FooStoredProceduresIntegrationTest.class); + + @Autowired + private SessionFactory sessionFactory; + + @Autowired + private IFooService fooService; + + private Session session; + + @Before + public final void before() { + session = sessionFactory.openSession(); + Assume.assumeTrue(getAllFoosExists()); + Assume.assumeTrue(getFoosByNameExists()); + } + + private boolean getFoosByNameExists() { + try { + Query sqlQuery = session.createSQLQuery("CALL GetAllFoos()") + .addEntity(Foo.class); + sqlQuery.list(); + return true; + } catch (SQLGrammarException e) { + LOGGER.error("WARNING : GetFoosByName() Procedure is may be missing ", e); + return false; + } + } + + private boolean getAllFoosExists() { + try { + Query sqlQuery = session.createSQLQuery("CALL GetAllFoos()") + .addEntity(Foo.class); + sqlQuery.list(); + return true; + } catch (SQLGrammarException e) { + LOGGER.error("WARNING : GetAllFoos() Procedure is may be missing ", e); + return false; + } + } + + @After + public final void after() { + session.close(); + } + + @Test + public final void getAllFoosUsingStoredProcedures() { + + fooService.create(new Foo(randomAlphabetic(6))); + + // Stored procedure getAllFoos using createSQLQuery + Query sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity( + Foo.class); + @SuppressWarnings("unchecked") + List allFoos = sqlQuery.list(); + for (Foo foo : allFoos) { + LOGGER.info("getAllFoos() SQL Query result : {}", foo.getName()); + } + assertEquals(allFoos.size(), fooService.findAll().size()); + + // Stored procedure getAllFoos using a Named Query + Query namedQuery = session.getNamedQuery("callGetAllFoos"); + @SuppressWarnings("unchecked") + List allFoos2 = namedQuery.list(); + for (Foo foo : allFoos2) { + LOGGER.info("getAllFoos() NamedQuery result : {}", foo.getName()); + } + assertEquals(allFoos2.size(), fooService.findAll().size()); + } + + @Test + public final void getFoosByNameUsingStoredProcedures() { + + fooService.create(new Foo("NewFooName")); + + // Stored procedure getFoosByName using createSQLQuery() + Query sqlQuery = session.createSQLQuery("CALL GetFoosByName(:fooName)") + .addEntity(Foo.class).setParameter("fooName", "NewFooName"); + @SuppressWarnings("unchecked") + List allFoosByName = sqlQuery.list(); + for (Foo foo : allFoosByName) { + LOGGER.info("getFoosByName() using SQL Query : found => {}", foo.toString()); + } + + // Stored procedure getFoosByName using getNamedQuery() + Query namedQuery = session.getNamedQuery("callGetFoosByName") + .setParameter("fooName", "NewFooName"); + @SuppressWarnings("unchecked") + List allFoosByName2 = namedQuery.list(); + for (Foo foo : allFoosByName2) { + LOGGER.info("getFoosByName() using Native Query : found => {}", foo.toString()); + } + + } +} diff --git a/spring-hibernate4/src/test/java/hibernate.cfg.xml b/spring-hibernate4/src/test/java/hibernate.cfg.xml deleted file mode 100644 index 2167eada16..0000000000 --- a/spring-hibernate4/src/test/java/hibernate.cfg.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - -com.mysql.jdbc.Driver -jdbc:mysql://localhost:3306/HIBERTEST2_TEST -root - - - -1 - - -org.hibernate.dialect.MySQLDialect - - -thread - - -org.hibernate.cache.internal.NoCacheProvider - - -true - - - - - - - diff --git a/spring-hibernate4/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml b/spring-hibernate4/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml new file mode 100644 index 0000000000..9e0109aae2 --- /dev/null +++ b/spring-hibernate4/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-hibernate4/src/test/resources/criteria.cfg.xml b/spring-hibernate4/src/test/resources/criteria.cfg.xml new file mode 100644 index 0000000000..653b5a188a --- /dev/null +++ b/spring-hibernate4/src/test/resources/criteria.cfg.xml @@ -0,0 +1,16 @@ + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + iamtheking + org.hibernate.dialect.MySQLDialect + true + + + \ No newline at end of file diff --git a/spring-hibernate4/src/test/resources/fetching.cfg.xml b/spring-hibernate4/src/test/resources/fetching.cfg.xml new file mode 100644 index 0000000000..acee7008ba --- /dev/null +++ b/spring-hibernate4/src/test/resources/fetching.cfg.xml @@ -0,0 +1,18 @@ + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + iamtheking + org.hibernate.dialect.MySQLDialect + true + + + + + \ No newline at end of file diff --git a/spring-hibernate4/src/test/resources/fetchingLazy.cfg.xml b/spring-hibernate4/src/test/resources/fetchingLazy.cfg.xml new file mode 100644 index 0000000000..1dc37d0cf8 --- /dev/null +++ b/spring-hibernate4/src/test/resources/fetchingLazy.cfg.xml @@ -0,0 +1,18 @@ + + + + + + com.mysql.jdbc.Driver + jdbc:mysql://localhost:3306/test + root + iamtheking + org.hibernate.dialect.MySQLDialect + true + + + + + \ No newline at end of file diff --git a/spring-jms/pom.xml b/spring-jms/pom.xml new file mode 100644 index 0000000000..8f78469989 --- /dev/null +++ b/spring-jms/pom.xml @@ -0,0 +1,57 @@ + + 4.0.0 + com.baeldung + spring-jms + 0.0.1-SNAPSHOT + war + spring-jms + Introduction to Spring JMS + + + 4.3.2.RELEASE + 5.12.0 + + + + + + org.springframework + spring-jms + ${springframework.version} + + + + org.apache.activemq + activemq-all + ${activemq.version} + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.2 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-war-plugin + 2.4 + + src/main/webapp + spring-jms + false + + + + + spring-jms + + \ No newline at end of file diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/Employee.java b/spring-jms/src/main/java/com/baeldung/spring/jms/Employee.java new file mode 100644 index 0000000000..4da02907a9 --- /dev/null +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/Employee.java @@ -0,0 +1,23 @@ +package com.baeldung.spring.jms; + +public class Employee { + private String name; + private Integer age; + + public Employee(String name, Integer age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public Integer getAge() { + return age; + } + + public String toString() { + return "Person: name(" + name + "), age(" + age + ")"; + } +} diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJMSExample.java b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJMSExample.java new file mode 100644 index 0000000000..a243bc1390 --- /dev/null +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJMSExample.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.jms; + +import org.apache.activemq.broker.BrokerFactory; +import org.apache.activemq.broker.BrokerService; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.net.URI; + +public class SampleJMSExample { + public static void main(String[] args) throws Exception { + BrokerService broker = BrokerFactory.createBroker(new URI("broker:(tcp://localhost:61616)")); + broker.start(); + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); + + } +} diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java new file mode 100644 index 0000000000..865a1d4747 --- /dev/null +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java @@ -0,0 +1,28 @@ +package com.baeldung.spring.jms; + +import org.springframework.jms.core.JmsTemplate; +import org.springframework.jms.core.MessageCreator; + +import javax.jms.*; + +public class SampleJmsMessageSender { + + private JmsTemplate jmsTemplate; + private Queue queue; + + public void createJmsTemplate(ConnectionFactory cf) { + this.jmsTemplate = new JmsTemplate(cf); + } + + public void setQueue(Queue queue) { + this.queue = queue; + } + + public void simpleSend() { + this.jmsTemplate.send(this.queue, new MessageCreator() { + public Message createMessage(Session session) throws JMSException { + return session.createTextMessage("hello queue world"); + } + }); + } +} \ No newline at end of file diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java new file mode 100644 index 0000000000..0320870d88 --- /dev/null +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java @@ -0,0 +1,23 @@ +package com.baeldung.spring.jms; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.TextMessage; + +public class SampleListener implements MessageListener { + + private String textMessage; + + public void onMessage(Message message) { + if (message instanceof TextMessage) { + try { + textMessage = ((TextMessage) message).getText(); + } catch (JMSException ex) { + throw new RuntimeException(ex); + } + } else { + throw new IllegalArgumentException("Message Error"); + } + } +} \ No newline at end of file diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleMessageConverter.java b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleMessageConverter.java new file mode 100644 index 0000000000..6cfc588f13 --- /dev/null +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleMessageConverter.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.jms; + +import org.springframework.jms.support.converter.MessageConversionException; +import org.springframework.jms.support.converter.MessageConverter; + +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.Message; +import javax.jms.Session; + +public class SampleMessageConverter implements MessageConverter { + + public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException { + Employee person = (Employee) object; + MapMessage message = session.createMapMessage(); + message.setString("name", person.getName()); + message.setInt("age", person.getAge()); + return message; + } + + public Object fromMessage(Message message) throws JMSException, MessageConversionException { + MapMessage mapMessage = (MapMessage) message; + return new Employee(mapMessage.getString("name"), mapMessage.getInt("age")); + } + +} diff --git a/spring-jms/src/main/resources/applicationContext.xml b/spring-jms/src/main/resources/applicationContext.xml new file mode 100644 index 0000000000..c15289763f --- /dev/null +++ b/spring-jms/src/main/resources/applicationContext.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-jpa/.classpath b/spring-jpa/.classpath deleted file mode 100644 index fa5dbd4c0e..0000000000 --- a/spring-jpa/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-jpa/.project b/spring-jpa/.project deleted file mode 100644 index 235ae29ecf..0000000000 --- a/spring-jpa/.project +++ /dev/null @@ -1,43 +0,0 @@ - - - spring-jpa - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-jpa/.settings/.jsdtscope b/spring-jpa/.settings/.jsdtscope deleted file mode 100644 index b46b9207a8..0000000000 --- a/spring-jpa/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-jpa/.settings/org.eclipse.jdt.core.prefs b/spring-jpa/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 4561074422..0000000000 --- a/spring-jpa/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-jpa/.settings/org.eclipse.jdt.ui.prefs b/spring-jpa/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-jpa/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-jpa/.settings/org.eclipse.m2e.core.prefs b/spring-jpa/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-jpa/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-jpa/.settings/org.eclipse.m2e.wtp.prefs b/spring-jpa/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-jpa/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-jpa/.settings/org.eclipse.wst.common.component b/spring-jpa/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 0327e45de6..0000000000 --- a/spring-jpa/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-jpa/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-jpa/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 9ca0d1c1b7..0000000000 --- a/spring-jpa/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/spring-jpa/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-jpa/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-jpa/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-jpa/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-jpa/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-jpa/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-jpa/.settings/org.eclipse.wst.validation.prefs b/spring-jpa/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-jpa/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-jpa/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-jpa/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-jpa/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-jpa/.settings/org.hibernate.eclipse.console.prefs b/spring-jpa/.settings/org.hibernate.eclipse.console.prefs deleted file mode 100644 index 7505c63770..0000000000 --- a/spring-jpa/.settings/org.hibernate.eclipse.console.prefs +++ /dev/null @@ -1,3 +0,0 @@ -default.configuration= -eclipse.preferences.version=1 -hibernate3.enabled=true diff --git a/spring-jpa/.springBeans b/spring-jpa/.springBeans deleted file mode 100644 index fc808d21d4..0000000000 --- a/spring-jpa/.springBeans +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - - - - - - - - - diff --git a/spring-jpa/README.md b/spring-jpa/README.md index 11df42ac52..f974c6e22c 100644 --- a/spring-jpa/README.md +++ b/spring-jpa/README.md @@ -7,3 +7,6 @@ - [Spring 3 and JPA with Hibernate](http://www.baeldung.com/2011/12/13/the-persistence-layer-with-spring-3-1-and-jpa/) - [Transactions with Spring 3 and JPA](http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/) - [The DAO with JPA and Spring](http://www.baeldung.com/spring-dao-jpa) +- [JPA Pagination](http://www.baeldung.com/jpa-pagination) +- [Sorting with JPA](http://www.baeldung.com/jpa-sort) +- [Spring JPA – Multiple Databases](http://www.baeldung.com/spring-data-jpa-multiple-databases) diff --git a/spring-jpa/pom.xml b/spring-jpa/pom.xml index 2e8f818776..ebb9c5bc83 100644 --- a/spring-jpa/pom.xml +++ b/spring-jpa/pom.xml @@ -1,9 +1,10 @@ 4.0.0 - org.baeldung + com.baeldung spring-jpa 0.1-SNAPSHOT + war spring-jpa @@ -21,6 +22,11 @@ spring-context ${org.springframework.version} + + org.springframework + spring-webmvc + ${org.springframework.version} + @@ -29,6 +35,11 @@ hibernate-entitymanager ${hibernate.version} + + org.hibernate + hibernate-ehcache + ${hibernate.version} + xml-apis xml-apis @@ -50,6 +61,11 @@ spring-data-jpa ${spring-data-jpa.version} + + com.h2database + h2 + ${h2.version} + @@ -63,6 +79,18 @@ javax.el-api 2.2.5 + + + + javax.servlet + jstl + ${javax.servlet.jstl.version} + + + javax.servlet + servlet-api + ${javax.servlet.servlet-api.version} + @@ -137,6 +165,16 @@ 1.8 + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + src/main/webapp + false + + org.apache.maven.plugins @@ -179,14 +217,18 @@ - 4.2.4.RELEASE - 4.0.2.RELEASE + 4.3.2.RELEASE 3.20.0-GA - 4.3.11.Final - 5.1.37 - 1.8.2.RELEASE + 5.2.2.Final + 5.1.38 + 1.10.2.RELEASE + 1.4.192 + + + 1.2 + 2.5 1.7.13 @@ -207,13 +249,14 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 - 2.18.1 + 3.5.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 + 2.4 diff --git a/spring-jpa/src/main/java/org/baeldung/config/PersistenceJNDIConfig.java b/spring-jpa/src/main/java/org/baeldung/config/PersistenceJNDIConfig.java new file mode 100644 index 0000000000..7f28c958f1 --- /dev/null +++ b/spring-jpa/src/main/java/org/baeldung/config/PersistenceJNDIConfig.java @@ -0,0 +1,72 @@ +package org.baeldung.config; + +import java.util.Properties; + +import javax.naming.NamingException; +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jndi.JndiTemplate; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-jndi.properties" }) +@ComponentScan({ "org.baeldung.persistence" }) +@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao") +public class PersistenceJNDIConfig { + + @Autowired + private Environment env; + + public PersistenceJNDIConfig() { + super(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); + em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + em.setJpaProperties(additionalProperties()); + return em; + } + + @Bean + public DataSource dataSource() throws NamingException { + return (DataSource) new JndiTemplate().lookup(env.getProperty("jdbc.url")); + } + + @Bean + public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(emf); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "false"); + return hibernateProperties; + } +} \ No newline at end of file diff --git a/spring-jpa/src/main/java/org/baeldung/config/PersistenceJPAConfig.java b/spring-jpa/src/main/java/org/baeldung/config/PersistenceJPAConfig.java index c9358190e7..010eb5b8a1 100644 --- a/spring-jpa/src/main/java/org/baeldung/config/PersistenceJPAConfig.java +++ b/spring-jpa/src/main/java/org/baeldung/config/PersistenceJPAConfig.java @@ -78,6 +78,8 @@ public class PersistenceJPAConfig { final Properties hibernateProperties = new Properties(); hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache")); + hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache")); // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); return hibernateProperties; } diff --git a/spring-jpa/src/main/java/org/baeldung/config/PersistenceJPAConfigL2Cache.java b/spring-jpa/src/main/java/org/baeldung/config/PersistenceJPAConfigL2Cache.java new file mode 100644 index 0000000000..3ca0dbf5e4 --- /dev/null +++ b/spring-jpa/src/main/java/org/baeldung/config/PersistenceJPAConfigL2Cache.java @@ -0,0 +1,84 @@ +package org.baeldung.config; + +import com.google.common.base.Preconditions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-h2.properties" }) +@ComponentScan({ "org.baeldung.persistence" }) +@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao") +public class PersistenceJPAConfigL2Cache { + + @Autowired + private Environment env; + + public PersistenceJPAConfigL2Cache() { + super(); + } + + // beans + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + + return em; + } + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(emf); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache")); + hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache")); + hibernateProperties.setProperty("hibernate.cache.region.factory_class", env.getProperty("hibernate.cache.region.factory_class")); + return hibernateProperties; + } + +} \ No newline at end of file diff --git a/spring-jpa/src/main/java/org/baeldung/config/SpringWebConfig.java b/spring-jpa/src/main/java/org/baeldung/config/SpringWebConfig.java new file mode 100644 index 0000000000..6afb271b10 --- /dev/null +++ b/spring-jpa/src/main/java/org/baeldung/config/SpringWebConfig.java @@ -0,0 +1,24 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; + +@EnableWebMvc +@Configuration +@ComponentScan({ "org.baeldung.web" }) +public class SpringWebConfig extends WebMvcConfigurerAdapter { + + @Bean + public InternalResourceViewResolver viewResolver() { + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setViewClass(JstlView.class); + viewResolver.setPrefix("/WEB-INF/views/jsp/"); + viewResolver.setSuffix(".jsp"); + return viewResolver; + } +} diff --git a/spring-jpa/src/main/java/org/baeldung/config/WebInitializer.java b/spring-jpa/src/main/java/org/baeldung/config/WebInitializer.java new file mode 100644 index 0000000000..1c8ce5400f --- /dev/null +++ b/spring-jpa/src/main/java/org/baeldung/config/WebInitializer.java @@ -0,0 +1,20 @@ +package org.baeldung.config; + +import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; + +public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { + @Override + protected Class[] getRootConfigClasses() { + return new Class[] { PersistenceJNDIConfig.class }; + } + + @Override + protected Class[] getServletConfigClasses() { + return new Class[] { SpringWebConfig.class }; + } + + @Override + protected String[] getServletMappings() { + return new String[] { "/" }; + } +} diff --git a/spring-jpa/src/main/java/org/baeldung/persistence/model/Foo.java b/spring-jpa/src/main/java/org/baeldung/persistence/model/Foo.java index 585cefb159..209ab081de 100644 --- a/spring-jpa/src/main/java/org/baeldung/persistence/model/Foo.java +++ b/spring-jpa/src/main/java/org/baeldung/persistence/model/Foo.java @@ -1,17 +1,13 @@ package org.baeldung.persistence.model; +import org.hibernate.annotations.CacheConcurrencyStrategy; + +import javax.persistence.*; import java.io.Serializable; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; - @Entity +@Cacheable +@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class Foo implements Serializable { private static final long serialVersionUID = 1L; diff --git a/spring-jpa/src/main/java/org/baeldung/persistence/multiple/dao/user/PossessionRepository.java b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/dao/user/PossessionRepository.java new file mode 100644 index 0000000000..34913632d8 --- /dev/null +++ b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/dao/user/PossessionRepository.java @@ -0,0 +1,8 @@ +package org.baeldung.persistence.multiple.dao.user; + +import org.baeldung.persistence.multiple.model.user.Possession; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PossessionRepository extends JpaRepository { + +} diff --git a/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/Possession.java b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/Possession.java new file mode 100644 index 0000000000..97b5803d73 --- /dev/null +++ b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/Possession.java @@ -0,0 +1,86 @@ +package org.baeldung.persistence.multiple.model.user; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(schema = "spring_jpa_user") +public class Possession { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + + public Possession() { + super(); + } + + public Possession(final String name) { + super(); + + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + (int) (id ^ (id >>> 32)); + result = (prime * result) + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Possession other = (Possession) obj; + if (id != other.id) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Possesion [id=").append(id).append(", name=").append(name).append("]"); + return builder.toString(); + } + +} diff --git a/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/User.java b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/User.java index 305568bad8..1c6399dc44 100644 --- a/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/User.java +++ b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/User.java @@ -1,10 +1,13 @@ package org.baeldung.persistence.multiple.model.user; +import java.util.List; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @@ -22,6 +25,9 @@ public class User { private int age; + @OneToMany + List possessionList; + public User() { super(); } @@ -58,6 +64,14 @@ public class User { this.age = age; } + public List getPossessionList() { + return possessionList; + } + + public void setPossessionList(List possessionList) { + this.possessionList = possessionList; + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff --git a/spring-jpa/src/main/java/org/baeldung/web/MainController.java b/spring-jpa/src/main/java/org/baeldung/web/MainController.java new file mode 100644 index 0000000000..6900482de8 --- /dev/null +++ b/spring-jpa/src/main/java/org/baeldung/web/MainController.java @@ -0,0 +1,21 @@ +package org.baeldung.web; + +import org.baeldung.persistence.service.FooService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class MainController { + + @Autowired + private FooService fooService; + + @GetMapping("/") + public String main(Model model) { + model.addAttribute("foos", fooService.findAll()); + return "index"; + } + +} diff --git a/spring-jpa/src/main/resources/context.xml b/spring-jpa/src/main/resources/context.xml new file mode 100644 index 0000000000..a64dfe9a61 --- /dev/null +++ b/spring-jpa/src/main/resources/context.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/spring-jpa/src/main/resources/jpaConfig.xml b/spring-jpa/src/main/resources/jpaConfig.xml index 1f0b8d899f..5afc0af94d 100644 --- a/spring-jpa/src/main/resources/jpaConfig.xml +++ b/spring-jpa/src/main/resources/jpaConfig.xml @@ -21,6 +21,8 @@ ${hibernate.hbm2ddl.auto} ${hibernate.dialect} + ${hibernate.cache.use_second_level_cache} + ${hibernate.cache.use_query_cache} diff --git a/spring-jpa/src/main/resources/persistence-h2.properties b/spring-jpa/src/main/resources/persistence-h2.properties new file mode 100644 index 0000000000..d195af5ec9 --- /dev/null +++ b/spring-jpa/src/main/resources/persistence-h2.properties @@ -0,0 +1,13 @@ +# jdbc.X +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +jdbc.user=sa +# jdbc.pass= + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop +hibernate.cache.use_second_level_cache=true +hibernate.cache.use_query_cache=true +hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory \ No newline at end of file diff --git a/spring-jpa/src/main/resources/persistence-jndi.properties b/spring-jpa/src/main/resources/persistence-jndi.properties new file mode 100644 index 0000000000..16d750d7f8 --- /dev/null +++ b/spring-jpa/src/main/resources/persistence-jndi.properties @@ -0,0 +1,8 @@ +# jdbc.X +jdbc.url=java:comp/env/jdbc/BaeldungDatabase + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect +hibernate.show_sql=false +#hibernate.hbm2ddl.auto=create +hibernate.hbm2ddl.auto=update \ No newline at end of file diff --git a/spring-jpa/src/main/resources/persistence-multiple-db.properties b/spring-jpa/src/main/resources/persistence-multiple-db.properties index d59956ba03..1a0d99c704 100644 --- a/spring-jpa/src/main/resources/persistence-multiple-db.properties +++ b/spring-jpa/src/main/resources/persistence-multiple-db.properties @@ -9,3 +9,5 @@ jdbc.pass=tutorialmy5ql hibernate.dialect=org.hibernate.dialect.MySQL5Dialect hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop +hibernate.cache.use_second_level_cache=false +hibernate.cache.use_query_cache=false \ No newline at end of file diff --git a/spring-jpa/src/main/resources/persistence-mysql.properties b/spring-jpa/src/main/resources/persistence-mysql.properties index c4de4ceb80..12b4c93d80 100644 --- a/spring-jpa/src/main/resources/persistence-mysql.properties +++ b/spring-jpa/src/main/resources/persistence-mysql.properties @@ -8,3 +8,5 @@ jdbc.pass=tutorialmy5ql hibernate.dialect=org.hibernate.dialect.MySQL5Dialect hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop +hibernate.cache.use_second_level_cache=false +hibernate.cache.use_query_cache=false \ No newline at end of file diff --git a/spring-jpa/src/main/resources/server.xml b/spring-jpa/src/main/resources/server.xml new file mode 100644 index 0000000000..5c61659018 --- /dev/null +++ b/spring-jpa/src/main/resources/server.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/spring-jpa/src/main/resources/webSecurityConfig.xml b/spring-jpa/src/main/resources/webSecurityConfig.xml deleted file mode 100644 index 88af78dabc..0000000000 --- a/spring-jpa/src/main/resources/webSecurityConfig.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-jpa/src/main/webapp/WEB-INF/views/jsp/index.jsp b/spring-jpa/src/main/webapp/WEB-INF/views/jsp/index.jsp new file mode 100644 index 0000000000..f2ec8e2bec --- /dev/null +++ b/spring-jpa/src/main/webapp/WEB-INF/views/jsp/index.jsp @@ -0,0 +1,14 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + + + +Baeldung - Spring JNA JNDI + + + +

    + +

    +
    + + \ No newline at end of file diff --git a/spring-jpa/src/test/java/META-INF/persistence.xml b/spring-jpa/src/test/java/META-INF/persistence.xml index e528491795..922aedbc39 100644 --- a/spring-jpa/src/test/java/META-INF/persistence.xml +++ b/spring-jpa/src/test/java/META-INF/persistence.xml @@ -1,16 +1,20 @@ - - - org.baeldung.persistence.model.Foo - org.baeldung.persistence.model.Bar - - - - - - - - - - + + + org.baeldung.persistence.model.Foo + org.baeldung.persistence.model.Bar + + + + + + + + + + + + diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java index 73c36190f9..091bec0ba0 100644 --- a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java @@ -88,11 +88,12 @@ public class FooPaginationPersistenceIntegrationTest { public final void givenEntitiesExist_whenRetrievingPage_thenCorrect() { final int pageSize = 10; - final Query queryIds = entityManager.createQuery("Select f.id from Foo f order by f.lastName"); + final Query queryIds = entityManager.createQuery("Select f.id from Foo f order by f.name"); final List fooIds = queryIds.getResultList(); - final Query query = entityManager.createQuery("Select f from Foo e whet f.id in :ids"); + final Query query = entityManager.createQuery("Select f from Foo as f where f.id in :ids"); query.setParameter("ids", fooIds.subList(0, pageSize)); + final List fooList = query.getResultList(); // Then @@ -129,13 +130,15 @@ public class FooPaginationPersistenceIntegrationTest { final Root from = criteriaQuery.from(Foo.class); final CriteriaQuery select = criteriaQuery.select(from); - final TypedQuery typedQuery = entityManager.createQuery(select); + TypedQuery typedQuery; while (pageNumber < count.intValue()) { + typedQuery = entityManager.createQuery(select); typedQuery.setFirstResult(pageNumber - 1); typedQuery.setMaxResults(pageSize); System.out.println("Current page: " + typedQuery.getResultList()); pageNumber += pageSize; } + } // UTIL diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java index 96b3235f64..4c57865f74 100644 --- a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java @@ -36,7 +36,7 @@ public class FooServicePersistenceIntegrationTest { @Test(expected = DataIntegrityViolationException.class) public final void whenInvalidEntityIsCreated_thenDataException() { - service.create(new Foo()); + service.create(new Foo(randomAlphabetic(2048))); } @Test(expected = DataIntegrityViolationException.class) @@ -53,7 +53,7 @@ public class FooServicePersistenceIntegrationTest { @Test(expected = DataAccessException.class) public final void temp_whenInvalidEntityIsCreated_thenDataException() { - service.create(new Foo()); + service.create(new Foo(randomAlphabetic(2048))); } @Test diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java new file mode 100644 index 0000000000..3c9f509da5 --- /dev/null +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java @@ -0,0 +1,116 @@ +package org.baeldung.persistence.service; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +import org.baeldung.config.PersistenceJPAConfig; +import org.baeldung.persistence.model.Bar; +import org.baeldung.persistence.model.Foo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) +@SuppressWarnings("unchecked") +public class FooServiceSortingIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + // tests + + @Test + public final void whenSortingByOneAttributeDefaultOrder_thenPrintSortedResult() { + final String jql = "Select f from Foo as f order by f.id"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingByOneAttributeSetOrder_thenSortedPrintResult() { + final String jql = "Select f from Foo as f order by f.id desc"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingByTwoAttributes_thenPrintSortedResult() { + final String jql = "Select f from Foo as f order by f.name asc, f.id desc"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingFooByBar_thenBarsSorted() { + final String jql = "Select f from Foo as f order by f.name, f.bar.id"; + final Query barJoinQuery = entityManager.createQuery(jql); + final List fooList = barJoinQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + if (foo.getBar() != null) { + System.out.print("-------BarId:" + foo.getBar().getId()); + } + } + } + + @Test + public final void whenSortinfBar_thenPrintBarsSortedWithFoos() { + final String jql = "Select b from Bar as b order by b.id"; + final Query barQuery = entityManager.createQuery(jql); + final List barList = barQuery.getResultList(); + for (final Bar bar : barList) { + System.out.println("Bar Id:" + bar.getId()); + for (final Foo foo : bar.getFooList()) { + System.out.println("FooName:" + foo.getName()); + } + } + } + + @Test + public final void whenSortingFooWithCriteria_thenPrintSortedFoos() { + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); + final Root from = criteriaQuery.from(Foo.class); + final CriteriaQuery select = criteriaQuery.select(from); + criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name"))); + final TypedQuery typedQuery = entityManager.createQuery(select); + final List fooList = typedQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "--------Id:" + foo.getId()); + } + } + + @Test + public final void whenSortingFooWithCriteriaAndMultipleAttributes_thenPrintSortedFoos() { + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); + final Root from = criteriaQuery.from(Foo.class); + final CriteriaQuery select = criteriaQuery.select(from); + criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")), criteriaBuilder.desc(from.get("id"))); + final TypedQuery typedQuery = entityManager.createQuery(select); + final List fooList = typedQuery.getResultList(); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); + } + } + +} diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingTests.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingTests.java deleted file mode 100644 index 319d36151e..0000000000 --- a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingTests.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.baeldung.persistence.service; - -import java.util.List; - -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import javax.persistence.Query; -import javax.persistence.TypedQuery; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; - -import org.baeldung.config.PersistenceJPAConfig; -import org.baeldung.persistence.model.Bar; -import org.baeldung.persistence.model.Foo; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.AnnotationConfigContextLoader; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) -@SuppressWarnings("unchecked") -public class FooServiceSortingTests { - - @PersistenceContext - private EntityManager entityManager; - - // tests - - @Test - public final void whenSortingByOneAttributeDefaultOrder_thenPrintSortedResult() { - final String jql = "Select f from Foo as f order by f.id"; - final Query sortQuery = entityManager.createQuery(jql); - final List fooList = sortQuery.getResultList(); - for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); - } - } - - @Test - public final void whenSortingByOneAttributeSetOrder_thenSortedPrintResult() { - final String jql = "Select f from Foo as f order by f.id desc"; - final Query sortQuery = entityManager.createQuery(jql); - final List fooList = sortQuery.getResultList(); - for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); - } - } - - @Test - public final void whenSortingByTwoAttributes_thenPrintSortedResult() { - final String jql = "Select f from Foo as f order by f.name asc, f.id desc"; - final Query sortQuery = entityManager.createQuery(jql); - final List fooList = sortQuery.getResultList(); - for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); - } - } - - @Test - public final void whenSortingFooByBar_thenBarsSorted() { - final String jql = "Select f from Foo as f order by f.name, f.bar.id"; - final Query barJoinQuery = entityManager.createQuery(jql); - final List fooList = barJoinQuery.getResultList(); - for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "-------BarId:" + foo.getBar().getId()); - } - } - - @Test - public final void whenSortinfBar_thenPrintBarsSortedWithFoos() { - final String jql = "Select b from Bar as b order by b.id"; - final Query barQuery = entityManager.createQuery(jql); - final List barList = barQuery.getResultList(); - for (final Bar bar : barList) { - System.out.println("Bar Id:" + bar.getId()); - for (final Foo foo : bar.getFooList()) { - System.out.println("FooName:" + foo.getName()); - } - } - } - - @Test - public final void whenSortingFooWithCriteria_thenPrintSortedFoos() { - final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); - final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); - final Root from = criteriaQuery.from(Foo.class); - final CriteriaQuery select = criteriaQuery.select(from); - criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name"))); - final TypedQuery typedQuery = entityManager.createQuery(select); - final List fooList = typedQuery.getResultList(); - for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "--------Id:" + foo.getId()); - } - } - - @Test - public final void whenSortingFooWithCriteriaAndMultipleAttributes_thenPrintSortedFoos() { - final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); - final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class); - final Root from = criteriaQuery.from(Foo.class); - final CriteriaQuery select = criteriaQuery.select(from); - criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")), criteriaBuilder.desc(from.get("id"))); - final TypedQuery typedQuery = entityManager.createQuery(select); - final List fooList = typedQuery.getResultList(); - for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId()); - } - } - -} diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java new file mode 100644 index 0000000000..040eee1c73 --- /dev/null +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java @@ -0,0 +1,62 @@ +package org.baeldung.persistence.service; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.junit.Assert.assertNull; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import org.baeldung.config.PersistenceJPAConfig; +import org.baeldung.persistence.model.Foo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) +public class FooServiceSortingWitNullsManualIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private FooService service; + + // tests + + @SuppressWarnings("unchecked") + @Test + public final void whenSortingByStringNullLast_thenLastNull() { + service.create(new Foo()); + service.create(new Foo(randomAlphabetic(6))); + + final String jql = "Select f from Foo as f order by f.name desc NULLS LAST"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + assertNull(fooList.get(fooList.toArray().length - 1).getName()); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + } + } + + @SuppressWarnings("unchecked") + @Test + public final void whenSortingByStringNullFirst_thenFirstNull() { + service.create(new Foo()); + + final String jql = "Select f from Foo as f order by f.name desc NULLS FIRST"; + final Query sortQuery = entityManager.createQuery(jql); + final List fooList = sortQuery.getResultList(); + assertNull(fooList.get(0).getName()); + for (final Foo foo : fooList) { + System.out.println("Name:" + foo.getName()); + } + } + +} diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualTest.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualTest.java deleted file mode 100644 index 986e4e4a7d..0000000000 --- a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.baeldung.persistence.service; - -import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; -import static org.junit.Assert.assertNull; - -import java.util.List; - -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import javax.persistence.Query; - -import org.baeldung.config.PersistenceJPAConfig; -import org.baeldung.persistence.model.Foo; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.AnnotationConfigContextLoader; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class) -public class FooServiceSortingWitNullsManualTest { - - @PersistenceContext - private EntityManager entityManager; - - @Autowired - private FooService service; - - // tests - - @Test - public final void whenSortingByStringNullLast_thenLastNull() { - service.create(new Foo()); - service.create(new Foo(randomAlphabetic(6))); - - final String jql = "Select f from Foo as f order by f.name desc NULLS LAST"; - final Query sortQuery = entityManager.createQuery(jql); - final List fooList = sortQuery.getResultList(); - assertNull(fooList.get(fooList.toArray().length - 1).getName()); - for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName()); - } - } - - @Test - public final void whenSortingByStringNullFirst_thenFirstNull() { - service.create(new Foo()); - - final String jql = "Select f from Foo as f order by f.name desc NULLS FIRST"; - final Query sortQuery = entityManager.createQuery(jql); - final List fooList = sortQuery.getResultList(); - assertNull(fooList.get(0).getName()); - for (final Foo foo : fooList) { - System.out.println("Name:" + foo.getName()); - } - } - -} diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBIntegrationTest.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBIntegrationTest.java new file mode 100644 index 0000000000..f20af34057 --- /dev/null +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBIntegrationTest.java @@ -0,0 +1,96 @@ +package org.baeldung.persistence.service; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Arrays; + +import org.baeldung.config.ProductConfig; +import org.baeldung.config.UserConfig; +import org.baeldung.persistence.multiple.dao.product.ProductRepository; +import org.baeldung.persistence.multiple.dao.user.PossessionRepository; +import org.baeldung.persistence.multiple.dao.user.UserRepository; +import org.baeldung.persistence.multiple.model.product.Product; +import org.baeldung.persistence.multiple.model.user.Possession; +import org.baeldung.persistence.multiple.model.user.User; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { UserConfig.class, ProductConfig.class }) +@EnableTransactionManagement +public class JpaMultipleDBIntegrationTest { + + @Autowired + private UserRepository userRepository; + + @Autowired + private PossessionRepository possessionRepository; + + @Autowired + private ProductRepository productRepository; + + // tests + + @Test + @Transactional("userTransactionManager") + public void whenCreatingUser_thenCreated() { + User user = new User(); + user.setName("John"); + user.setEmail("john@test.com"); + user.setAge(20); + Possession p = new Possession("sample"); + p = possessionRepository.save(p); + user.setPossessionList(Arrays.asList(p)); + user = userRepository.save(user); + final User result = userRepository.findOne(user.getId()); + assertNotNull(result); + System.out.println(result.getPossessionList()); + assertTrue(result.getPossessionList().size() == 1); + } + + @Test + @Transactional("userTransactionManager") + public void whenCreatingUsersWithSameEmail_thenRollback() { + User user1 = new User(); + user1.setName("John"); + user1.setEmail("john@test.com"); + user1.setAge(20); + user1 = userRepository.save(user1); + assertNotNull(userRepository.findOne(user1.getId())); + + User user2 = new User(); + user2.setName("Tom"); + user2.setEmail("john@test.com"); + user2.setAge(10); + try { + user2 = userRepository.save(user2); + userRepository.flush(); + fail("DataIntegrityViolationException should be thrown!"); + } catch (final DataIntegrityViolationException e) { + // Expected + } catch (final Exception e) { + fail("DataIntegrityViolationException should be thrown, instead got: " + e); + } + } + + @Test + @Transactional("productTransactionManager") + public void whenCreatingProduct_thenCreated() { + Product product = new Product(); + product.setName("Book"); + product.setId(2); + product.setPrice(20); + product = productRepository.save(product); + + assertNotNull(productRepository.findOne(product.getId())); + } + +} diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBTest.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBTest.java deleted file mode 100644 index 427e182d9e..0000000000 --- a/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.baeldung.persistence.service; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import org.baeldung.config.ProductConfig; -import org.baeldung.config.UserConfig; -import org.baeldung.persistence.multiple.dao.product.ProductRepository; -import org.baeldung.persistence.multiple.dao.user.UserRepository; -import org.baeldung.persistence.multiple.model.product.Product; -import org.baeldung.persistence.multiple.model.user.User; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.transaction.TransactionConfiguration; -import org.springframework.transaction.annotation.Transactional; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { UserConfig.class, ProductConfig.class }) -@TransactionConfiguration -public class JpaMultipleDBTest { - - @Autowired - private UserRepository userRepository; - - @Autowired - private ProductRepository productRepository; - - // tests - - @Test - @Transactional("userTransactionManager") - public void whenCreatingUser_thenCreated() { - User user = new User(); - user.setName("John"); - user.setEmail("john@test.com"); - user.setAge(20); - user = userRepository.save(user); - - assertNotNull(userRepository.findOne(user.getId())); - } - - @Test - @Transactional("userTransactionManager") - public void whenCreatingUsersWithSameEmail_thenRollback() { - User user1 = new User(); - user1.setName("John"); - user1.setEmail("john@test.com"); - user1.setAge(20); - user1 = userRepository.save(user1); - assertNotNull(userRepository.findOne(user1.getId())); - - User user2 = new User(); - user2.setName("Tom"); - user2.setEmail("john@test.com"); - user2.setAge(10); - try { - user2 = userRepository.save(user2); - } catch (final DataIntegrityViolationException e) { - } - - assertNull(userRepository.findOne(user2.getId())); - } - - @Test - @Transactional("productTransactionManager") - public void whenCreatingProduct_thenCreated() { - Product product = new Product(); - product.setName("Book"); - product.setId(2); - product.setPrice(20); - product = productRepository.save(product); - - assertNotNull(productRepository.findOne(product.getId())); - } - -} diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/PersistenceTestSuite.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/PersistenceTestSuite.java index 919171de9f..aa2dfb5293 100644 --- a/spring-jpa/src/test/java/org/baeldung/persistence/service/PersistenceTestSuite.java +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/PersistenceTestSuite.java @@ -7,10 +7,9 @@ import org.junit.runners.Suite; @Suite.SuiteClasses({ // @formatter:off FooPaginationPersistenceIntegrationTest.class ,FooServicePersistenceIntegrationTest.class - ,FooServiceSortingTests.class - ,JpaMultipleDBTest.class - // manual only - // ,FooServiceSortingWitNullsManualTest.class + ,FooServiceSortingIntegrationTest.class + ,JpaMultipleDBIntegrationTest.class + ,FooServiceSortingWitNullsManualIntegrationTest.class }) // @formatter:on public class PersistenceTestSuite { // diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/SecondLevelCacheIntegrationTest.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/SecondLevelCacheIntegrationTest.java new file mode 100644 index 0000000000..f97f53b82c --- /dev/null +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/SecondLevelCacheIntegrationTest.java @@ -0,0 +1,84 @@ +package org.baeldung.persistence.service; + +import net.sf.ehcache.CacheManager; +import org.baeldung.config.PersistenceJPAConfigL2Cache; +import org.baeldung.persistence.model.Bar; +import org.baeldung.persistence.model.Foo; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.hamcrest.Matchers.greaterThan; +import static org.junit.Assert.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceJPAConfigL2Cache.class }, loader = AnnotationConfigContextLoader.class) +public class SecondLevelCacheIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + @Autowired + private FooService fooService; + @Autowired + private PlatformTransactionManager platformTransactionManager; + + @Before + public final void before() { + entityManager.getEntityManagerFactory().getCache().evictAll(); + } + + @Test + public final void givenEntityIsLoaded_thenItIsCached() { + final Foo foo = new Foo(randomAlphabetic(6)); + fooService.create(foo); + fooService.findOne(foo.getId()); + final int size = CacheManager.ALL_CACHE_MANAGERS.get(0) + .getCache("org.baeldung.persistence.model.Foo").getSize(); + assertThat(size, greaterThan(0)); + } + + @Test + public final void givenBarIsUpdatedInNativeQuery_thenFoosAreNotEvicted() { + final Foo foo = new Foo(randomAlphabetic(6)); + fooService.create(foo); + fooService.findOne(foo.getId()); + + new TransactionTemplate(platformTransactionManager).execute(status -> { + final Bar bar = new Bar(randomAlphabetic(6)); + entityManager.persist(bar); + final Query nativeQuery = entityManager.createNativeQuery("update BAR set NAME = :updatedName where ID = :id"); + nativeQuery.setParameter("updatedName", "newName"); + nativeQuery.setParameter("id", bar.getId()); + nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Bar.class); + return nativeQuery.executeUpdate(); + }); + + final int size = CacheManager.ALL_CACHE_MANAGERS.get(0) + .getCache("org.baeldung.persistence.model.Foo").getSize(); + assertThat(size, greaterThan(0)); + } + + @Test + public final void givenCacheableQueryIsExecuted_thenItIsCached() { + new TransactionTemplate(platformTransactionManager).execute(status -> { + return entityManager.createQuery("select f from Foo f") + .setHint("org.hibernate.cacheable", true) + .getResultList(); + }); + + final int size = CacheManager.ALL_CACHE_MANAGERS.get(0) + .getCache("org.hibernate.cache.internal.StandardQueryCache").getSize(); + assertThat(size, greaterThan(0)); + } +} diff --git a/spring-katharsis/.classpath b/spring-katharsis/.classpath deleted file mode 100644 index 9ae7bca0fc..0000000000 --- a/spring-katharsis/.classpath +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-katharsis/.project b/spring-katharsis/.project deleted file mode 100644 index 3284dc1199..0000000000 --- a/spring-katharsis/.project +++ /dev/null @@ -1,35 +0,0 @@ - - - spring-katharsis - - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/spring-katharsis/.springBeans b/spring-katharsis/.springBeans deleted file mode 100644 index b854542b58..0000000000 --- a/spring-katharsis/.springBeans +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - - - - - - - - diff --git a/spring-katharsis/README.md b/spring-katharsis/README.md new file mode 100644 index 0000000000..cf2a001760 --- /dev/null +++ b/spring-katharsis/README.md @@ -0,0 +1,9 @@ +========= + +## Java Web Application + +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles: +- [JSON API in a Java Web Application](http://www.baeldung.com/json-api-java-spring-web-app) diff --git a/sandbox/.gitignore b/spring-mockito/.gitignore similarity index 100% rename from sandbox/.gitignore rename to spring-mockito/.gitignore diff --git a/spring-mockito/README.md b/spring-mockito/README.md new file mode 100644 index 0000000000..3ced7161fa --- /dev/null +++ b/spring-mockito/README.md @@ -0,0 +1,7 @@ +========= + +## Mockito Mocks into Spring Beans + + +### Relevant Articles: +- [Injecting Mockito Mocks into Spring Beans](http://www.baeldung.com/injecting-mocks-in-spring) diff --git a/spring-mockito/pom.xml b/spring-mockito/pom.xml new file mode 100644 index 0000000000..3dcca7aab7 --- /dev/null +++ b/spring-mockito/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + com.baeldung + spring-mockito + 0.0.1-SNAPSHOT + jar + + spring-mockito + Injecting Mockito Mocks into Spring Beans + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + org.mockito + mockito-all + 1.10.19 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + + + diff --git a/mockito-mocks-spring-beans/src/main/java/com/baeldung/MocksApplication.java b/spring-mockito/src/main/java/com/baeldung/MocksApplication.java similarity index 100% rename from mockito-mocks-spring-beans/src/main/java/com/baeldung/MocksApplication.java rename to spring-mockito/src/main/java/com/baeldung/MocksApplication.java diff --git a/mockito-mocks-spring-beans/src/main/java/com/baeldung/NameService.java b/spring-mockito/src/main/java/com/baeldung/NameService.java similarity index 100% rename from mockito-mocks-spring-beans/src/main/java/com/baeldung/NameService.java rename to spring-mockito/src/main/java/com/baeldung/NameService.java diff --git a/mockito-mocks-spring-beans/src/main/java/com/baeldung/UserService.java b/spring-mockito/src/main/java/com/baeldung/UserService.java similarity index 100% rename from mockito-mocks-spring-beans/src/main/java/com/baeldung/UserService.java rename to spring-mockito/src/main/java/com/baeldung/UserService.java diff --git a/spring-mockito/src/main/resources/application.properties b/spring-mockito/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mockito-mocks-spring-beans/src/test/java/com/baeldung/NameServiceTestConfiguration.java b/spring-mockito/src/test/java/com/baeldung/NameServiceTestConfiguration.java similarity index 100% rename from mockito-mocks-spring-beans/src/test/java/com/baeldung/NameServiceTestConfiguration.java rename to spring-mockito/src/test/java/com/baeldung/NameServiceTestConfiguration.java diff --git a/mockito-mocks-spring-beans/src/test/java/com/baeldung/UserServiceTest.java b/spring-mockito/src/test/java/com/baeldung/UserServiceTest.java similarity index 100% rename from mockito-mocks-spring-beans/src/test/java/com/baeldung/UserServiceTest.java rename to spring-mockito/src/test/java/com/baeldung/UserServiceTest.java diff --git a/spring-mvc-java/.classpath b/spring-mvc-java/.classpath deleted file mode 100644 index a642d37ceb..0000000000 --- a/spring-mvc-java/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-mvc-java/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-mvc-java/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-mvc-java/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-mvc-java/.project b/spring-mvc-java/.project deleted file mode 100644 index 21aa8efe0f..0000000000 --- a/spring-mvc-java/.project +++ /dev/null @@ -1,43 +0,0 @@ - - - spring-mvc-java - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-mvc-java/.settings/.jsdtscope b/spring-mvc-java/.settings/.jsdtscope deleted file mode 100644 index b46b9207a8..0000000000 --- a/spring-mvc-java/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-mvc-java/.settings/org.eclipse.jdt.core.prefs b/spring-mvc-java/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 5ff04b9f96..0000000000 --- a/spring-mvc-java/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,91 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-mvc-java/.settings/org.eclipse.jdt.ui.prefs b/spring-mvc-java/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-mvc-java/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-mvc-java/.settings/org.eclipse.m2e.core.prefs b/spring-mvc-java/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-mvc-java/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-mvc-java/.settings/org.eclipse.m2e.wtp.prefs b/spring-mvc-java/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-mvc-java/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-mvc-java/.settings/org.eclipse.wst.common.component b/spring-mvc-java/.settings/org.eclipse.wst.common.component deleted file mode 100644 index b23283ab37..0000000000 --- a/spring-mvc-java/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-mvc-java/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-mvc-java/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 9ca0d1c1b7..0000000000 --- a/spring-mvc-java/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/spring-mvc-java/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-mvc-java/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-mvc-java/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-mvc-java/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-mvc-java/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-mvc-java/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-mvc-java/.settings/org.eclipse.wst.validation.prefs b/spring-mvc-java/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-mvc-java/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-mvc-java/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-mvc-java/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-mvc-java/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-mvc-java/.springBeans b/spring-mvc-java/.springBeans deleted file mode 100644 index 7623a7e888..0000000000 --- a/spring-mvc-java/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md index bf76c7e1d4..951d80033e 100644 --- a/spring-mvc-java/README.md +++ b/spring-mvc-java/README.md @@ -2,5 +2,11 @@ ## Spring MVC with Java Configuration Example Project +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: +- [Spring Bean Annotations](http://www.baeldung.com/spring-bean-annotations) +- [Introduction to Pointcut Expressions in Spring](http://www.baeldung.com/spring-aop-pointcut-tutorial) +- [Introduction to Advice Types in Spring](http://www.baeldung.com/spring-aop-advice-tutorial) +- [A Guide to the ViewResolver in Spring MVC](http://www.baeldung.com/spring-mvc-view-resolver-tutorial) diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml index 19610f5ab0..7361d16b33 100644 --- a/spring-mvc-java/pom.xml +++ b/spring-mvc-java/pom.xml @@ -1,6 +1,7 @@ - + 4.0.0 - org.baeldung + com.baeldung spring-mvc-java 0.1-SNAPSHOT spring-mvc-java @@ -11,6 +12,12 @@ org.springframework spring-web ${org.springframework.version} + + + commons-logging + commons-logging + + org.springframework @@ -18,27 +25,27 @@ ${org.springframework.version} - org.springframework - spring-websocket - ${org.springframework.version} - - - org.springframework - spring-messaging - ${org.springframework.version} - - - - com.fasterxml.jackson.core - jackson-core - 2.7.3 - - - com.fasterxml.jackson.core - jackson-databind - 2.7.3 - - + org.springframework + spring-websocket + ${org.springframework.version} + + + org.springframework + spring-messaging + ${org.springframework.version} + + + + com.fasterxml.jackson.core + jackson-core + 2.7.3 + + + com.fasterxml.jackson.core + jackson-databind + 2.7.3 + + javax.servlet @@ -68,24 +75,62 @@ aspectjweaver ${aspectj.version} + + + + commons-fileupload + commons-fileupload + 1.3.1 + + + + + org.thymeleaf + thymeleaf-spring4 + ${thymeleaf.version} + + + org.thymeleaf + thymeleaf + ${thymeleaf.version} + + + + + com.fasterxml.jackson.core + jackson-core + 2.1.2 + + + com.fasterxml.jackson.core + jackson-databind + 2.1.2 + + org.slf4j slf4j-api ${org.slf4j.version} + + ch.qos.logback + logback-classic + + ${logback.version} + org.slf4j - slf4j-log4j12 + jcl-over-slf4j + ${org.slf4j.version} - - - commons-fileupload - commons-fileupload - 1.3.1 - - + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + junit @@ -111,23 +156,19 @@ ${mockito.version} test + + com.jayway.jsonpath + json-path + 2.2.0 + test + org.springframework spring-test ${org.springframework.version} test - - - org.thymeleaf - thymeleaf-spring4 - ${thymeleaf.version} - - - org.thymeleaf - thymeleaf - ${thymeleaf.version} - + @@ -181,7 +222,6 @@ cargo-maven2-plugin ${cargo-maven2-plugin.version} - true jetty8x embedded @@ -198,18 +238,19 @@
    - + - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 2.1.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 - 1.7.13 - 1.1.3 + 1.7.21 + 1.1.5 + 5.2.2.Final @@ -221,15 +262,18 @@ 1.10.19 4.4.1 4.5 - 2.4.1 + 2.9.0 + 2.23 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.17 + 1.4.18 + 1.8.7 - -
    \ No newline at end of file + +
    + diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/LoggingAspect.java b/spring-mvc-java/src/main/java/com/baeldung/aop/LoggingAspect.java similarity index 90% rename from spring-mvc-java/src/main/java/org/baeldung/aop/LoggingAspect.java rename to spring-mvc-java/src/main/java/com/baeldung/aop/LoggingAspect.java index c59c4f060a..7ae37404be 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/aop/LoggingAspect.java +++ b/spring-mvc-java/src/main/java/com/baeldung/aop/LoggingAspect.java @@ -1,4 +1,4 @@ -package org.baeldung.aop; +package com.baeldung.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; @@ -27,11 +27,11 @@ public class LoggingAspect { public void repositoryMethods() { } - @Pointcut("@annotation(org.baeldung.aop.annotations.Loggable)") + @Pointcut("@annotation(com.baeldung.aop.annotations.Loggable)") public void loggableMethods() { } - @Pointcut("@args(org.baeldung.aop.annotations.Entity)") + @Pointcut("@args(com.baeldung.aop.annotations.Entity)") public void methodsAcceptingEntities() { } diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/PerformanceAspect.java b/spring-mvc-java/src/main/java/com/baeldung/aop/PerformanceAspect.java similarity index 97% rename from spring-mvc-java/src/main/java/org/baeldung/aop/PerformanceAspect.java rename to spring-mvc-java/src/main/java/com/baeldung/aop/PerformanceAspect.java index 2d07e5a5f3..1f2076adff 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/aop/PerformanceAspect.java +++ b/spring-mvc-java/src/main/java/com/baeldung/aop/PerformanceAspect.java @@ -1,4 +1,4 @@ -package org.baeldung.aop; +package com.baeldung.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/PublishingAspect.java b/spring-mvc-java/src/main/java/com/baeldung/aop/PublishingAspect.java similarity index 94% rename from spring-mvc-java/src/main/java/org/baeldung/aop/PublishingAspect.java rename to spring-mvc-java/src/main/java/com/baeldung/aop/PublishingAspect.java index 324605dab1..7791c63e7b 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/aop/PublishingAspect.java +++ b/spring-mvc-java/src/main/java/com/baeldung/aop/PublishingAspect.java @@ -1,10 +1,10 @@ -package org.baeldung.aop; +package com.baeldung.aop; +import com.baeldung.events.FooCreationEvent; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; -import org.baeldung.events.FooCreationEvent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Entity.java b/spring-mvc-java/src/main/java/com/baeldung/aop/annotations/Entity.java similarity index 86% rename from spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Entity.java rename to spring-mvc-java/src/main/java/com/baeldung/aop/annotations/Entity.java index f964c3979e..61d91b0777 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Entity.java +++ b/spring-mvc-java/src/main/java/com/baeldung/aop/annotations/Entity.java @@ -1,4 +1,4 @@ -package org.baeldung.aop.annotations; +package com.baeldung.aop.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Loggable.java b/spring-mvc-java/src/main/java/com/baeldung/aop/annotations/Loggable.java similarity index 87% rename from spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Loggable.java rename to spring-mvc-java/src/main/java/com/baeldung/aop/annotations/Loggable.java index ef2863957f..92aa950e58 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Loggable.java +++ b/spring-mvc-java/src/main/java/com/baeldung/aop/annotations/Loggable.java @@ -1,4 +1,4 @@ -package org.baeldung.aop.annotations; +package com.baeldung.aop.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/spring-mvc-java/src/main/java/com/baeldung/circulardependency/CircularDependencyA b/spring-mvc-java/src/main/java/com/baeldung/circulardependency/CircularDependencyA new file mode 100644 index 0000000000..54b012e347 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/circulardependency/CircularDependencyA @@ -0,0 +1,29 @@ +package com.baeldung.circulardependency; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class CircularDependencyA implements ApplicationContextAware, InitializingBean { + + private CircularDependencyB circB; + + private ApplicationContext context; + + public CircularDependencyB getCircB() { + return circB; + } + + @Override + public void afterPropertiesSet() throws Exception { + circB = context.getBean(CircularDependencyB.class); + } + + @Override + public void setApplicationContext(final ApplicationContext ctx) throws BeansException { + context = ctx; + } +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/circulardependency/CircularDependencyB b/spring-mvc-java/src/main/java/com/baeldung/circulardependency/CircularDependencyB new file mode 100644 index 0000000000..dc2240d0b5 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/circulardependency/CircularDependencyB @@ -0,0 +1,22 @@ +package com.baeldung.circulardependency; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class CircularDependencyB { + + private CircularDependencyA circA; + + private String message = "Hi!"; + + @Autowired + public void setCircA(final CircularDependencyA circA) { + this.circA = circA; + } + + public String getMessage() { + return message; + } + +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/dao/FooDao.java b/spring-mvc-java/src/main/java/com/baeldung/dao/FooDao.java similarity index 75% rename from spring-mvc-java/src/main/java/org/baeldung/dao/FooDao.java rename to spring-mvc-java/src/main/java/com/baeldung/dao/FooDao.java index f204440b2d..1d28b082ec 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/dao/FooDao.java +++ b/spring-mvc-java/src/main/java/com/baeldung/dao/FooDao.java @@ -1,7 +1,7 @@ -package org.baeldung.dao; +package com.baeldung.dao; -import org.baeldung.aop.annotations.Loggable; -import org.baeldung.model.Foo; +import com.baeldung.aop.annotations.Loggable; +import com.baeldung.model.Foo; import org.springframework.stereotype.Repository; @Repository diff --git a/spring-mvc-java/src/main/java/org/baeldung/dialect/CustomDialect.java b/spring-mvc-java/src/main/java/com/baeldung/dialect/CustomDialect.java similarity index 86% rename from spring-mvc-java/src/main/java/org/baeldung/dialect/CustomDialect.java rename to spring-mvc-java/src/main/java/com/baeldung/dialect/CustomDialect.java index e6d1ad6b74..0c6a7c3ae0 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/dialect/CustomDialect.java +++ b/spring-mvc-java/src/main/java/com/baeldung/dialect/CustomDialect.java @@ -1,9 +1,9 @@ -package org.baeldung.dialect; +package com.baeldung.dialect; import java.util.HashSet; import java.util.Set; -import org.baeldung.processor.NameProcessor; +import com.baeldung.processor.NameProcessor; import org.thymeleaf.dialect.AbstractDialect; import org.thymeleaf.processor.IProcessor; diff --git a/spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEvent.java b/spring-mvc-java/src/main/java/com/baeldung/events/FooCreationEvent.java similarity index 86% rename from spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEvent.java rename to spring-mvc-java/src/main/java/com/baeldung/events/FooCreationEvent.java index af11f3a4be..5ea4b46c04 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEvent.java +++ b/spring-mvc-java/src/main/java/com/baeldung/events/FooCreationEvent.java @@ -1,4 +1,4 @@ -package org.baeldung.events; +package com.baeldung.events; import org.springframework.context.ApplicationEvent; diff --git a/spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEventListener.java b/spring-mvc-java/src/main/java/com/baeldung/events/FooCreationEventListener.java similarity index 94% rename from spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEventListener.java rename to spring-mvc-java/src/main/java/com/baeldung/events/FooCreationEventListener.java index 35dcfd2bc3..c0aa744bc1 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEventListener.java +++ b/spring-mvc-java/src/main/java/com/baeldung/events/FooCreationEventListener.java @@ -1,4 +1,4 @@ -package org.baeldung.events; +package com.baeldung.events; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/Company.java b/spring-mvc-java/src/main/java/com/baeldung/model/Company.java new file mode 100644 index 0000000000..558507268a --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/model/Company.java @@ -0,0 +1,38 @@ +package com.baeldung.model; + +public class Company { + + private long id; + private String name; + + public Company() { + super(); + } + + public Company(final long id, final String name) { + this.id = id; + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + @Override + public String toString() { + return "Company [id=" + id + ", name=" + name + "]"; + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/Employee.java b/spring-mvc-java/src/main/java/com/baeldung/model/Employee.java new file mode 100644 index 0000000000..fb0a452219 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/model/Employee.java @@ -0,0 +1,61 @@ +package com.baeldung.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class Employee { + + private long id; + private String name; + private String contactNumber; + private String workingArea; + + public Employee() { + super(); + } + + public Employee(final long id, final String name, final String contactNumber, final String workingArea) { + this.id = id; + this.name = name; + this.contactNumber = contactNumber; + this.workingArea = workingArea; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getContactNumber() { + return contactNumber; + } + + public void setContactNumber(final String contactNumber) { + this.contactNumber = contactNumber; + } + + public String getWorkingArea() { + return workingArea; + } + + public void setWorkingArea(final String workingArea) { + this.workingArea = workingArea; + } + + @Override + public String toString() { + return "Employee [id=" + id + ", name=" + name + ", contactNumber=" + contactNumber + ", workingArea=" + workingArea + "]"; + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/Foo.java b/spring-mvc-java/src/main/java/com/baeldung/model/Foo.java new file mode 100644 index 0000000000..01f5f43f60 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/model/Foo.java @@ -0,0 +1,19 @@ +package com.baeldung.model; + +import com.baeldung.aop.annotations.Entity; + +@Entity +public class Foo { + private Long id; + private String name; + + public Foo(Long id, String name) { + this.id = id; + this.name = name; + } + + @Override + public String toString() { + return "Foo{" + "id=" + id + ", name='" + name + '\'' + '}'; + } +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/Greeting.java b/spring-mvc-java/src/main/java/com/baeldung/model/Greeting.java new file mode 100644 index 0000000000..db021b8e8c --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/model/Greeting.java @@ -0,0 +1,22 @@ +package com.baeldung.model; + +public class Greeting { + private int id; + private String message; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/model/Message.java b/spring-mvc-java/src/main/java/com/baeldung/model/Message.java similarity index 85% rename from spring-mvc-java/src/main/java/org/baeldung/model/Message.java rename to spring-mvc-java/src/main/java/com/baeldung/model/Message.java index 051fa0d880..c1f7f52215 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/model/Message.java +++ b/spring-mvc-java/src/main/java/com/baeldung/model/Message.java @@ -1,4 +1,4 @@ -package org.baeldung.model; +package com.baeldung.model; public class Message { diff --git a/spring-mvc-java/src/main/java/org/baeldung/model/OutputMessage.java b/spring-mvc-java/src/main/java/com/baeldung/model/OutputMessage.java similarity index 93% rename from spring-mvc-java/src/main/java/org/baeldung/model/OutputMessage.java rename to spring-mvc-java/src/main/java/com/baeldung/model/OutputMessage.java index 53a7081f2c..fc201ed016 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/model/OutputMessage.java +++ b/spring-mvc-java/src/main/java/com/baeldung/model/OutputMessage.java @@ -1,4 +1,4 @@ -package org.baeldung.model; +package com.baeldung.model; public class OutputMessage { diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/User.java b/spring-mvc-java/src/main/java/com/baeldung/model/User.java new file mode 100644 index 0000000000..dc4480c986 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/model/User.java @@ -0,0 +1,32 @@ +package com.baeldung.model; + +public class User { + private String firstname; + private String lastname; + private String emailId; + + public String getFirstname() { + return firstname; + } + + public void setFirstname(final String firstname) { + this.firstname = firstname; + } + + public String getLastname() { + return lastname; + } + + public void setLastname(final String lastname) { + this.lastname = lastname; + } + + public String getEmailId() { + return emailId; + } + + public void setEmailId(final String emailId) { + this.emailId = emailId; + } + +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/processor/NameProcessor.java b/spring-mvc-java/src/main/java/com/baeldung/processor/NameProcessor.java similarity index 94% rename from spring-mvc-java/src/main/java/org/baeldung/processor/NameProcessor.java rename to spring-mvc-java/src/main/java/com/baeldung/processor/NameProcessor.java index df9a4da7f0..9a7857198c 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/processor/NameProcessor.java +++ b/spring-mvc-java/src/main/java/com/baeldung/processor/NameProcessor.java @@ -1,4 +1,4 @@ -package org.baeldung.processor; +package com.baeldung.processor; import org.thymeleaf.Arguments; import org.thymeleaf.dom.Element; diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationConfig.java new file mode 100644 index 0000000000..261d5793dc --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationConfig.java @@ -0,0 +1,36 @@ +package com.baeldung.spring.web.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; + +@EnableWebMvc +@Configuration +@ComponentScan(basePackages = { "com.baeldung.web.controller" }) +public class ApplicationConfig extends WebMvcConfigurerAdapter { + + public ApplicationConfig() { + super(); + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("index"); + } + + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/jsp/"); + bean.setSuffix(".jsp"); + return bean; + } +} \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ClientWebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ClientWebConfig.java new file mode 100644 index 0000000000..1b30479685 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ClientWebConfig.java @@ -0,0 +1,93 @@ +package com.baeldung.spring.web.config; + +import java.util.HashSet; +import java.util.Set; + +import com.baeldung.dialect.CustomDialect; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Description; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; +import org.thymeleaf.dialect.IDialect; +import org.thymeleaf.spring4.SpringTemplateEngine; +import org.thymeleaf.spring4.view.ThymeleafViewResolver; +import org.thymeleaf.templateresolver.ServletContextTemplateResolver; + +@EnableWebMvc +@Configuration +public class ClientWebConfig extends WebMvcConfigurerAdapter { + + public ClientWebConfig() { + super(); + } + + // API + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + + registry.addViewController("/sample.html"); + } + + @Bean + public ViewResolver thymeleafViewResolver() { + final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); + viewResolver.setTemplateEngine(templateEngine()); + viewResolver.setOrder(1); + return viewResolver; + } + + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/view/"); + bean.setSuffix(".jsp"); + bean.setOrder(0); + return bean; + } + + @Bean + @Description("Thymeleaf template resolver serving HTML 5") + public ServletContextTemplateResolver templateResolver() { + final ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(); + templateResolver.setPrefix("/WEB-INF/templates/"); + templateResolver.setSuffix(".html"); + templateResolver.setTemplateMode("HTML5"); + return templateResolver; + } + + @Bean + @Description("Thymeleaf template engine with Spring integration") + public SpringTemplateEngine templateEngine() { + final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.setTemplateResolver(templateResolver()); + final Set dialects = new HashSet<>(); + dialects.add(new CustomDialect()); + templateEngine.setAdditionalDialects(dialects); + return templateEngine; + } + + @Bean + @Description("Spring message resolver") + public MessageSource messageSource() { + final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setBasename("messages"); + return messageSource; + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } + +} \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ContentManagementWebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ContentManagementWebConfig.java new file mode 100644 index 0000000000..498105ded1 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ContentManagementWebConfig.java @@ -0,0 +1,46 @@ +package com.baeldung.spring.web.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.MediaType; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; + +@EnableWebMvc +@Configuration +public class ContentManagementWebConfig extends WebMvcConfigurerAdapter { + + public ContentManagementWebConfig() { + super(); + } + + // API + + @Override + public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) { + configurer.favorPathExtension(false).favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(true).useJaf(false).defaultContentType(MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML).mediaType("json", + MediaType.APPLICATION_JSON); + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/sample.html"); + } + + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/view/"); + bean.setSuffix(".jsp"); + bean.setOrder(0); + return bean; + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java new file mode 100644 index 0000000000..f428fc3223 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java @@ -0,0 +1,50 @@ +package com.baeldung.spring.web.config; + +import java.util.Set; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +public class MainWebAppInitializer implements WebApplicationInitializer { + + private static final String TMP_FOLDER = "/tmp"; + private static final int MAX_UPLOAD_SIZE = 5 * 1024 * 1024; // 5 MB + + /** + * Register and configure all Servlet container components necessary to power the web application. + */ + @Override + public void onStartup(final ServletContext sc) throws ServletException { + + // Create the 'root' Spring application context + final AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); + root.scan("com.baeldung.spring.web.config"); + // root.getEnvironment().setDefaultProfiles("embedded"); + + // Manages the lifecycle of the root application context + sc.addListener(new ContextLoaderListener(root)); + + // Handles requests into the application + final ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext())); + appServlet.setLoadOnStartup(1); + + // final MultipartConfigElement multipartConfigElement = new + // MultipartConfigElement(TMP_FOLDER, MAX_UPLOAD_SIZE, + // MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2); + // + // appServlet.setMultipartConfig(multipartConfigElement); + + final Set mappingConflicts = appServlet.addMapping("/"); + if (!mappingConflicts.isEmpty()) { + throw new IllegalStateException("'appServlet' could not be mapped to '/' due " + "to an existing mapping. This is a known issue under Tomcat versions " + "<= 7.0.14; see https://issues.apache.org/bugzilla/show_bug.cgi?id=51278"); + } + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java new file mode 100644 index 0000000000..663b9cc4d2 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java @@ -0,0 +1,109 @@ +package com.baeldung.spring.web.config; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.MediaType; +import org.springframework.http.converter.ByteArrayHttpMessageConverter; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.web.multipart.commons.CommonsMultipartResolver; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; +import org.springframework.web.servlet.view.ResourceBundleViewResolver; +import org.springframework.web.servlet.view.XmlViewResolver; +import org.springframework.web.util.UrlPathHelper; + +@Configuration +@EnableWebMvc +@ComponentScan("com.baeldung.web") +public class WebConfig extends WebMvcConfigurerAdapter { + + public WebConfig() { + super(); + } + + // @Bean + // public StandardServletMultipartResolver multipartResolver() { + // return new StandardServletMultipartResolver(); + // } + + @Bean(name = "multipartResolver") + public CommonsMultipartResolver multipartResolver() { + + final CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); + multipartResolver.setMaxUploadSize(100000); + + return multipartResolver; + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/sample.html"); + } + + @Bean + public ViewResolver internalResourceViewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/view/"); + bean.setSuffix(".jsp"); + bean.setOrder(2); + return bean; + } + + @Bean + public ViewResolver xmlViewResolver() { + final XmlViewResolver bean = new XmlViewResolver(); + bean.setLocation(new ClassPathResource("views.xml")); + bean.setOrder(1); + return bean; + } + + @Bean + public ViewResolver resourceBundleViewResolver() { + final ResourceBundleViewResolver bean = new ResourceBundleViewResolver(); + bean.setBasename("views"); + bean.setOrder(0); + return bean; + } + + @Override + public void extendMessageConverters(final List> converters) { + converters.add(byteArrayHttpMessageConverter()); + } + + @Bean + public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() { + final ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter(); + arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes()); + + return arrayHttpMessageConverter; + } + + private List getSupportedMediaTypes() { + final List list = new ArrayList(); + list.add(MediaType.IMAGE_JPEG); + list.add(MediaType.IMAGE_PNG); + list.add(MediaType.APPLICATION_OCTET_STREAM); + + return list; + } + + @Override + public void configurePathMatch(final PathMatchConfigurer configurer) { + final UrlPathHelper urlPathHelper = new UrlPathHelper(); + urlPathHelper.setRemoveSemicolonContent(false); + + configurer.setUrlPathHelper(urlPathHelper); + } +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/WebSocketConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java similarity index 95% rename from spring-mvc-java/src/main/java/org/baeldung/spring/web/config/WebSocketConfig.java rename to spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java index 03f4cb54e5..6330041c60 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/WebSocketConfig.java +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java @@ -1,4 +1,4 @@ -package org.baeldung.spring.web.config; +package com.baeldung.spring.web.config; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; diff --git a/spring-mvc-java/src/main/java/org/baeldung/web/BeanA.java b/spring-mvc-java/src/main/java/com/baeldung/web/BeanA.java similarity index 89% rename from spring-mvc-java/src/main/java/org/baeldung/web/BeanA.java rename to spring-mvc-java/src/main/java/com/baeldung/web/BeanA.java index b6b6f49c16..79fac724f7 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/web/BeanA.java +++ b/spring-mvc-java/src/main/java/com/baeldung/web/BeanA.java @@ -1,4 +1,4 @@ -package org.baeldung.web; +package com.baeldung.web; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/spring-mvc-java/src/main/java/org/baeldung/web/BeanB.java b/spring-mvc-java/src/main/java/com/baeldung/web/BeanB.java similarity index 83% rename from spring-mvc-java/src/main/java/org/baeldung/web/BeanB.java rename to spring-mvc-java/src/main/java/com/baeldung/web/BeanB.java index 49e5af4ccb..05c9560a0c 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/web/BeanB.java +++ b/spring-mvc-java/src/main/java/com/baeldung/web/BeanB.java @@ -1,4 +1,4 @@ -package org.baeldung.web; +package com.baeldung.web; import org.springframework.stereotype.Component; diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/ChatController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ChatController.java new file mode 100644 index 0000000000..f4bed1950b --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ChatController.java @@ -0,0 +1,23 @@ +package com.baeldung.web.controller; + +import com.baeldung.model.Message; +import com.baeldung.model.OutputMessage; +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.handler.annotation.SendTo; +import org.springframework.stereotype.Controller; + +import java.text.SimpleDateFormat; +import java.util.Date; + +@Controller +public class ChatController { + + @MessageMapping("/chat") + @SendTo("/topic/messages") + public OutputMessage send(final Message message) throws Exception { + + final String time = new SimpleDateFormat("HH:mm").format(new Date()); + return new OutputMessage(message.getFrom(), message.getText(), time); + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/CompanyController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/CompanyController.java new file mode 100644 index 0000000000..8dcfe68a84 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/CompanyController.java @@ -0,0 +1,80 @@ +package com.baeldung.web.controller; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.MatrixVariable; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +import com.baeldung.model.Company; + +@Controller +public class CompanyController { + + Map companyMap = new HashMap<>(); + + @RequestMapping(value = "/company", method = RequestMethod.GET) + public ModelAndView showForm() { + return new ModelAndView("companyHome", "company", new Company()); + } + + @RequestMapping(value = "/company/{Id}", produces = { "application/json", + "application/xml" }, method = RequestMethod.GET) + public @ResponseBody Company getCompanyById(@PathVariable final long Id) { + return companyMap.get(Id); + } + + @RequestMapping(value = "/addCompany", method = RequestMethod.POST) + public String submit(@ModelAttribute("company") final Company company, + final BindingResult result, final ModelMap model) { + if (result.hasErrors()) { + return "error"; + } + model.addAttribute("name", company.getName()); + model.addAttribute("id", company.getId()); + + companyMap.put(company.getId(), company); + + return "companyView"; + } + + @RequestMapping(value = "/companyEmployee/{company}/employeeData/{employee}", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity> getEmployeeDataFromCompany( + @MatrixVariable(pathVar = "employee") final Map matrixVars) { + return new ResponseEntity<>(matrixVars, HttpStatus.OK); + } + + @RequestMapping(value = "/companyData/{company}/employeeData/{employee}", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity> getCompanyName( + @MatrixVariable(value = "name", pathVar = "company") final String name) { + final Map result = new HashMap(); + result.put("name", name); + return new ResponseEntity<>(result, HttpStatus.OK); + } + + @RequestMapping(value = "/companyResponseBody", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public Company getCompanyResponseBody() { + final Company company = new Company(2, "ABC"); + return company; + } + + @RequestMapping(value = "/companyResponseEntity", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getCompanyResponseEntity() { + final Company company = new Company(3, "123"); + return new ResponseEntity(company, HttpStatus.OK); + } +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/EmployeeController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/EmployeeController.java new file mode 100644 index 0000000000..fd5fa6bc27 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/EmployeeController.java @@ -0,0 +1,110 @@ +package com.baeldung.web.controller; + +import com.baeldung.model.Employee; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.ui.ModelMap; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import java.util.*; + +@SessionAttributes("employees") +@Controller +@ControllerAdvice +public class EmployeeController { + + Map employeeMap = new HashMap<>(); + + @ModelAttribute("employees") + public void initEmployees() { + employeeMap.put(1L, new Employee(1L, "John", "223334411", "rh")); + employeeMap.put(2L, new Employee(2L, "Peter", "22001543", "informatics")); + employeeMap.put(3L, new Employee(3L, "Mike", "223334411", "admin")); + } + + @RequestMapping(value = "/employee", method = RequestMethod.GET) + public ModelAndView showForm() { + return new ModelAndView("employeeHome", "employee", new Employee()); + } + + @RequestMapping(value = "/employee/{Id}", produces = {"application/json", "application/xml"}, method = RequestMethod.GET) + public + @ResponseBody + Employee getEmployeeById(@PathVariable final long Id) { + return employeeMap.get(Id); + } + + @RequestMapping(value = "/addEmployee", method = RequestMethod.POST) + public String submit(@ModelAttribute("employee") final Employee employee, final BindingResult result, final ModelMap model) { + if (result.hasErrors()) { + return "error"; + } + model.addAttribute("name", employee.getName()); + model.addAttribute("contactNumber", employee.getContactNumber()); + model.addAttribute("workingArea", employee.getWorkingArea()); + model.addAttribute("id", employee.getId()); + + employeeMap.put(employee.getId(), employee); + + return "employeeView"; + } + + @ModelAttribute + public void addAttributes(final Model model) { + model.addAttribute("msg", "Welcome to the Netherlands!"); + } + + @RequestMapping(value = "/employees/{name}", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity> getEmployeeByNameAndBeginContactNumber(@PathVariable final String name, @MatrixVariable final String beginContactNumber) { + final List employeesList = new ArrayList(); + for (final Map.Entry employeeEntry : employeeMap.entrySet()) { + final Employee employee = employeeEntry.getValue(); + if (employee.getName().equalsIgnoreCase(name) && employee.getContactNumber().startsWith(beginContactNumber)) { + employeesList.add(employee); + } + } + return new ResponseEntity<>(employeesList, HttpStatus.OK); + } + + @RequestMapping(value = "/employeesContacts/{contactNumber}", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity> getEmployeeBycontactNumber(@MatrixVariable(required = true) final String contactNumber) { + final List employeesList = new ArrayList(); + for (final Map.Entry employeeEntry : employeeMap.entrySet()) { + final Employee employee = employeeEntry.getValue(); + if (employee.getContactNumber().equalsIgnoreCase(contactNumber)) { + employeesList.add(employee); + } + } + return new ResponseEntity<>(employeesList, HttpStatus.OK); + } + + @RequestMapping(value = "employeeData/{employee}", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity> getEmployeeData(@MatrixVariable final Map matrixVars) { + return new ResponseEntity<>(matrixVars, HttpStatus.OK); + } + + @RequestMapping(value = "employeeArea/{workingArea}", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity> getEmployeeByWorkingArea(@MatrixVariable final Map> matrixVars) { + final List employeesList = new ArrayList(); + final LinkedList workingArea = matrixVars.get("workingArea"); + for (final Map.Entry employeeEntry : employeeMap.entrySet()) { + final Employee employee = employeeEntry.getValue(); + for (final String area : workingArea) { + if (employee.getWorkingArea().equalsIgnoreCase(area)) { + employeesList.add(employee); + break; + } + } + } + return new ResponseEntity<>(employeesList, HttpStatus.OK); + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java new file mode 100644 index 0000000000..61bccb21aa --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java @@ -0,0 +1,32 @@ +package com.baeldung.web.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +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.multipart.MultipartFile; + +@Controller +public class FileUploadController { + + @RequestMapping(value = "/fileUpload", method = RequestMethod.GET) + public String displayForm() { + + return "fileUploadForm"; + } + + @RequestMapping(value = "/uploadFile", method = RequestMethod.POST) + public String submit(@RequestParam("file") final MultipartFile file, final ModelMap modelMap) { + + modelMap.addAttribute("file", file); + return "fileUploadView"; + } + + @RequestMapping(value = "/uploadMultiFile", method = RequestMethod.POST) + public String submit(@RequestParam("files") final MultipartFile[] files, final ModelMap modelMap) { + + modelMap.addAttribute("files", files); + return "fileUploadView"; + } +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/GreetController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/GreetController.java new file mode 100644 index 0000000000..6f764fedfb --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/GreetController.java @@ -0,0 +1,59 @@ +package com.baeldung.web.controller; + +import com.baeldung.model.Greeting; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +@Controller +public class GreetController { + + @RequestMapping(value = "/homePage", method = RequestMethod.GET) + public String index() { + return "index"; + } + + @RequestMapping(value = "/greet", method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public Greeting greet() { + Greeting greeting = new Greeting(); + greeting.setId(1); + greeting.setMessage("Hello World!!!"); + return greeting; + } + + @RequestMapping(value = "/greetWithPathVariable/{name}", method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public Greeting greetWithPathVariable(@PathVariable("name") String name) { + Greeting greeting = new Greeting(); + greeting.setId(1); + greeting.setMessage("Hello World " + name + "!!!"); + return greeting; + } + + @RequestMapping(value = "/greetWithQueryVariable", method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public Greeting greetWithQueryVariable(@RequestParam("name") String name) { + Greeting greeting = new Greeting(); + greeting.setId(1); + greeting.setMessage("Hello World " + name + "!!!"); + return greeting; + } + + @RequestMapping(value = "/greetWithPost", method = RequestMethod.POST, produces = "application/json") + @ResponseBody + public Greeting greetWithPost() { + Greeting greeting = new Greeting(); + greeting.setId(1); + greeting.setMessage("Hello World!!!"); + return greeting; + } + + @RequestMapping(value = "/greetWithPostAndFormData", method = RequestMethod.POST, produces = "application/json") + @ResponseBody + public Greeting greetWithPostAndFormData(@RequestParam("id") int id, @RequestParam("name") String name) { + Greeting greeting = new Greeting(); + greeting.setId(id); + greeting.setMessage("Hello World " + name + "!!!"); + return greeting; + } +} \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/ImageController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ImageController.java new file mode 100644 index 0000000000..5a8a491989 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ImageController.java @@ -0,0 +1,27 @@ +package com.baeldung.web.controller; + +import java.io.IOException; +import java.io.InputStream; + +import javax.servlet.ServletContext; + +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class ImageController { + + @Autowired + ServletContext servletContext; + + @RequestMapping(value = "/image-byte-array", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE) + public @ResponseBody byte[] getImageAsByteArray() throws IOException { + final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); + return IOUtils.toByteArray(in); + } +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/MessageController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/MessageController.java new file mode 100644 index 0000000000..cfc73aeabe --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/MessageController.java @@ -0,0 +1,24 @@ +package com.baeldung.web.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +@Controller +@RequestMapping("/message") +public class MessageController { + + @RequestMapping(value = "/showForm", method = RequestMethod.GET) + public String showForm() { + return "message"; + } + + @RequestMapping(value = "/processForm", method = RequestMethod.POST) + public String processForm(@RequestParam("message") final String message, final Model model) { + model.addAttribute("message", message); + return "message"; + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/UserController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/UserController.java new file mode 100644 index 0000000000..fda159f204 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/UserController.java @@ -0,0 +1,31 @@ +package com.baeldung.web.controller; + +import com.baeldung.model.User; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +@RequestMapping("/") +public class UserController { + + @RequestMapping(value = "/", method = RequestMethod.GET) + public String showForm(final Model model) { + final User user = new User(); + user.setFirstname("John"); + user.setLastname("Roy"); + user.setEmailId("John.Roy@gmail.com"); + model.addAttribute("user", user); + return "index"; + } + + @RequestMapping(value = "/processForm", method = RequestMethod.POST) + public String processForm(@ModelAttribute(value = "user") final User user, final Model model) { + // Insert User into DB + model.addAttribute("name", user.getFirstname() + " " + user.getLastname()); + return "hello"; + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java new file mode 100644 index 0000000000..8557b15492 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java @@ -0,0 +1,13 @@ +package com.baeldung.web.controller.advice; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice; + +@ControllerAdvice +public class JsonpControllerAdvice extends AbstractJsonpResponseBodyAdvice { + + public JsonpControllerAdvice() { + super("callback"); + } + +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/model/Foo.java b/spring-mvc-java/src/main/java/org/baeldung/model/Foo.java deleted file mode 100644 index 87bd7132e6..0000000000 --- a/spring-mvc-java/src/main/java/org/baeldung/model/Foo.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.baeldung.model; - -import org.baeldung.aop.annotations.Entity; - -@Entity -public class Foo { - private Long id; - private String name; - - public Foo(Long id, String name) { - this.id = id; - this.name = name; - } - - @Override - public String toString() { - return "Foo{" + "id=" + id + ", name='" + name + '\'' + '}'; - } -} diff --git a/spring-mvc-java/src/main/java/org/baeldung/model/User.java b/spring-mvc-java/src/main/java/org/baeldung/model/User.java deleted file mode 100644 index df549cd21d..0000000000 --- a/spring-mvc-java/src/main/java/org/baeldung/model/User.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.baeldung.model; - -public class User { - private String firstname; - private String lastname; - private String emailId; - - public String getFirstname() { - return firstname; - } - - public void setFirstname(final String firstname) { - this.firstname = firstname; - } - - public String getLastname() { - return lastname; - } - - public void setLastname(final String lastname) { - this.lastname = lastname; - } - - public String getEmailId() { - return emailId; - } - - public void setEmailId(final String emailId) { - this.emailId = emailId; - } - -} diff --git a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/ClientWebConfig.java b/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/ClientWebConfig.java deleted file mode 100644 index 6084943ddd..0000000000 --- a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/ClientWebConfig.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.baeldung.spring.web.config; - -import java.util.HashSet; -import java.util.Set; - -import org.baeldung.dialect.CustomDialect; -import org.springframework.context.MessageSource; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Description; -import org.springframework.context.support.ResourceBundleMessageSource; -import org.springframework.web.servlet.ViewResolver; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -import org.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.JstlView; -import org.thymeleaf.dialect.IDialect; -import org.thymeleaf.spring4.SpringTemplateEngine; -import org.thymeleaf.spring4.view.ThymeleafViewResolver; -import org.thymeleaf.templateresolver.ServletContextTemplateResolver; - -@EnableWebMvc -@Configuration -public class ClientWebConfig extends WebMvcConfigurerAdapter { - - public ClientWebConfig() { - super(); - } - - // API - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); - - registry.addViewController("/sample.html"); - } - - @Bean - public ViewResolver thymeleafViewResolver() { - final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); - viewResolver.setTemplateEngine(templateEngine()); - viewResolver.setOrder(1); - return viewResolver; - } - - @Bean - public ViewResolver viewResolver() { - final InternalResourceViewResolver bean = new InternalResourceViewResolver(); - bean.setViewClass(JstlView.class); - bean.setPrefix("/WEB-INF/view/"); - bean.setSuffix(".jsp"); - bean.setOrder(0); - return bean; - } - - @Bean - @Description("Thymeleaf template resolver serving HTML 5") - public ServletContextTemplateResolver templateResolver() { - final ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(); - templateResolver.setPrefix("/WEB-INF/templates/"); - templateResolver.setSuffix(".html"); - templateResolver.setTemplateMode("HTML5"); - return templateResolver; - } - - @Bean - @Description("Thymeleaf template engine with Spring integration") - public SpringTemplateEngine templateEngine() { - final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); - templateEngine.setTemplateResolver(templateResolver()); - final Set dialects = new HashSet<>(); - dialects.add(new CustomDialect()); - templateEngine.setAdditionalDialects(dialects); - return templateEngine; - } - - @Bean - @Description("Spring message resolver") - public MessageSource messageSource() { - final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); - messageSource.setBasename("messages"); - return messageSource; - } - - @Override - public void addResourceHandlers(final ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); - } - -} \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/MainWebAppInitializer.java b/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/MainWebAppInitializer.java deleted file mode 100644 index 60043ef342..0000000000 --- a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/MainWebAppInitializer.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.baeldung.spring.web.config; - -import java.util.Set; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; - -import org.springframework.web.WebApplicationInitializer; -import org.springframework.web.context.ContextLoaderListener; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; -import org.springframework.web.context.support.GenericWebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; - -public class MainWebAppInitializer implements WebApplicationInitializer { - - private static final String TMP_FOLDER = "/tmp"; - private static final int MAX_UPLOAD_SIZE = 5 * 1024 * 1024; // 5 MB - - /** - * Register and configure all Servlet container components necessary to power the web application. - */ - @Override - public void onStartup(final ServletContext sc) throws ServletException { - - // Create the 'root' Spring application context - final AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); - root.scan("org.baeldung.spring.web.config"); - // root.getEnvironment().setDefaultProfiles("embedded"); - - // Manages the lifecycle of the root application context - sc.addListener(new ContextLoaderListener(root)); - - // Handles requests into the application - final ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext())); - appServlet.setLoadOnStartup(1); - - // final MultipartConfigElement multipartConfigElement = new - // MultipartConfigElement(TMP_FOLDER, MAX_UPLOAD_SIZE, - // MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2); - // - // appServlet.setMultipartConfig(multipartConfigElement); - - final Set mappingConflicts = appServlet.addMapping("/"); - if (!mappingConflicts.isEmpty()) { - throw new IllegalStateException("'appServlet' could not be mapped to '/' due " + "to an existing mapping. This is a known issue under Tomcat versions " + "<= 7.0.14; see https://issues.apache.org/bugzilla/show_bug.cgi?id=51278"); - } - } - -} diff --git a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/WebConfig.java b/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/WebConfig.java deleted file mode 100644 index cd9ae582d8..0000000000 --- a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/WebConfig.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.baeldung.spring.web.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.ClassPathResource; -import org.springframework.web.multipart.commons.CommonsMultipartResolver; -import org.springframework.web.servlet.ViewResolver; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -import org.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.JstlView; -import org.springframework.web.servlet.view.ResourceBundleViewResolver; -import org.springframework.web.servlet.view.XmlViewResolver; - -@Configuration -@EnableWebMvc -@ComponentScan("org.baeldung.web") -public class WebConfig extends WebMvcConfigurerAdapter { - - public WebConfig() { - super(); - } - - // @Bean - // public StandardServletMultipartResolver multipartResolver() { - // return new StandardServletMultipartResolver(); - // } - - @Bean(name = "multipartResolver") - public CommonsMultipartResolver multipartResolver() { - - final CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); - multipartResolver.setMaxUploadSize(100000); - - return multipartResolver; - } - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - - super.addViewControllers(registry); - registry.addViewController("/sample.html"); - } - - @Bean - public ViewResolver internalResourceViewResolver() { - - final InternalResourceViewResolver bean = new InternalResourceViewResolver(); - bean.setViewClass(JstlView.class); - bean.setPrefix("/WEB-INF/view/"); - bean.setSuffix(".jsp"); - bean.setOrder(2); - return bean; - } - - @Bean - public ViewResolver xmlViewResolver() { - - final XmlViewResolver bean = new XmlViewResolver(); - bean.setLocation(new ClassPathResource("views.xml")); - bean.setOrder(1); - return bean; - } - - @Bean - public ViewResolver resourceBundleViewResolver() { - - final ResourceBundleViewResolver bean = new ResourceBundleViewResolver(); - bean.setBasename("views"); - bean.setOrder(0); - return bean; - } -} \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/org/baeldung/web/controller/ChatController.java b/spring-mvc-java/src/main/java/org/baeldung/web/controller/ChatController.java deleted file mode 100644 index cc39695dc8..0000000000 --- a/spring-mvc-java/src/main/java/org/baeldung/web/controller/ChatController.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.web.controller; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.baeldung.model.Message; -import org.baeldung.model.OutputMessage; -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.stereotype.Controller; - -@Controller -public class ChatController { - - @MessageMapping("/chat") - @SendTo("/topic/messages") - public OutputMessage send(final Message message) throws Exception { - - final String time = new SimpleDateFormat("HH:mm").format(new Date()); - return new OutputMessage(message.getFrom(), message.getText(), time); - } - -} diff --git a/spring-mvc-java/src/main/java/org/baeldung/web/controller/FileUploadController.java b/spring-mvc-java/src/main/java/org/baeldung/web/controller/FileUploadController.java deleted file mode 100644 index 6f557adf0f..0000000000 --- a/spring-mvc-java/src/main/java/org/baeldung/web/controller/FileUploadController.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.baeldung.web.controller; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.ModelMap; -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.multipart.MultipartFile; - -@Controller -public class FileUploadController { - - @RequestMapping(value = "/fileUpload", method = RequestMethod.GET) - public String displayForm() { - - return "fileUploadForm"; - } - - @RequestMapping(value = "/uploadFile", method = RequestMethod.POST) - public String submit(@RequestParam("file") final MultipartFile file, final ModelMap modelMap) { - - modelMap.addAttribute("file", file); - return "fileUploadView"; - } - - @RequestMapping(value = "/uploadMultiFile", method = RequestMethod.POST) - public String submit(@RequestParam("files") final MultipartFile[] files, final ModelMap modelMap) { - - modelMap.addAttribute("files", files); - return "fileUploadView"; - } -} diff --git a/spring-mvc-java/src/main/java/org/baeldung/web/controller/UserController.java b/spring-mvc-java/src/main/java/org/baeldung/web/controller/UserController.java deleted file mode 100644 index da39a36adf..0000000000 --- a/spring-mvc-java/src/main/java/org/baeldung/web/controller/UserController.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.baeldung.web.controller; - -import org.baeldung.model.User; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -@Controller -@RequestMapping("/") -public class UserController { - - @RequestMapping(value = "/", method = RequestMethod.GET) - public String showForm(final Model model) { - final User user = new User(); - user.setFirstname("John"); - user.setLastname("Roy"); - user.setEmailId("John.Roy@gmail.com"); - model.addAttribute("user", user); - return "index"; - } - - @RequestMapping(value = "/processForm", method = RequestMethod.POST) - public String processForm(@ModelAttribute(value = "user") final User user, final Model model) { - // Insert User into DB - model.addAttribute("name", user.getFirstname() + " " + user.getLastname()); - return "hello"; - } - -} diff --git a/spring-mvc-java/src/main/resources/com/baeldung/aop/beans.xml b/spring-mvc-java/src/main/resources/com/baeldung/aop/beans.xml new file mode 100644 index 0000000000..e6aa9d77c4 --- /dev/null +++ b/spring-mvc-java/src/main/resources/com/baeldung/aop/beans.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-mvc-java/src/main/resources/logback.xml b/spring-mvc-java/src/main/resources/logback.xml index 1146dade63..e0721aa890 100644 --- a/spring-mvc-java/src/main/resources/logback.xml +++ b/spring-mvc-java/src/main/resources/logback.xml @@ -2,7 +2,8 @@ - web - %date [%thread] %-5level %logger{36} - %message%n + + %date [%thread] %-5level %logger{6} - %message%n diff --git a/spring-mvc-java/src/main/resources/org/baeldung/aop/beans.xml b/spring-mvc-java/src/main/resources/org/baeldung/aop/beans.xml deleted file mode 100644 index 17c63e39e4..0000000000 --- a/spring-mvc-java/src/main/resources/org/baeldung/aop/beans.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/images/image-example.jpg b/spring-mvc-java/src/main/webapp/WEB-INF/images/image-example.jpg new file mode 100644 index 0000000000..219abe530f Binary files /dev/null and b/spring-mvc-java/src/main/webapp/WEB-INF/images/image-example.jpg differ diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 0000000000..2cf02bc2d8 --- /dev/null +++ b/spring-mvc-java/src/main/webapp/WEB-INF/jsp/index.jsp @@ -0,0 +1,5 @@ + + +

    Spring MVC - Integration Testing

    + + \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/companyHome.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/view/companyHome.jsp new file mode 100644 index 0000000000..38ef8d12ee --- /dev/null +++ b/spring-mvc-java/src/main/webapp/WEB-INF/view/companyHome.jsp @@ -0,0 +1,31 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + + + Form Example - Register a Company + + +

    Welcome, Enter The Company Details

    + + + + + + + + + + + + + + +
    Name
    Id
    +
    + + + + \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/companyView.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/view/companyView.jsp new file mode 100644 index 0000000000..8f34059b0a --- /dev/null +++ b/spring-mvc-java/src/main/webapp/WEB-INF/view/companyView.jsp @@ -0,0 +1,20 @@ +<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> + + + Spring MVC Form Handling + + + +

    Submitted Company Information

    + + + + + + + + + +
    Name :${name}
    ID :${id}
    + + \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/employeeHome.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/view/employeeHome.jsp new file mode 100644 index 0000000000..8a32fd12b6 --- /dev/null +++ b/spring-mvc-java/src/main/webapp/WEB-INF/view/employeeHome.jsp @@ -0,0 +1,37 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> + + + +Form Example - Register an Employee + + +

    Welcome, Enter The Employee Details

    + + + + + + + + + + + + + + + + + + + + + + +
    Name
    Id
    Contact Number
    Working Area
    +
    + + + + \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/employeeView.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/view/employeeView.jsp new file mode 100644 index 0000000000..627a9d9ddb --- /dev/null +++ b/spring-mvc-java/src/main/webapp/WEB-INF/view/employeeView.jsp @@ -0,0 +1,29 @@ +<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> + + +Spring MVC Form Handling + + + +

    Submitted Employee Information

    +

    ${msg}

    + + + + + + + + + + + + + + + + + +
    Name :${name}
    ID :${id}
    Contact Number :${contactNumber}
    Working Area :${workingArea}
    + + \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/index.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/view/index.jsp new file mode 100644 index 0000000000..fa5498c966 --- /dev/null +++ b/spring-mvc-java/src/main/webapp/WEB-INF/view/index.jsp @@ -0,0 +1,66 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1" %> + + + + + Company Data + + + + + + + + +
    + + + + \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/web_old.xml b/spring-mvc-java/src/main/webapp/WEB-INF/web_old.xml index 016369ad27..c8b38fae30 100644 --- a/spring-mvc-java/src/main/webapp/WEB-INF/web_old.xml +++ b/spring-mvc-java/src/main/webapp/WEB-INF/web_old.xml @@ -16,7 +16,7 @@ contextConfigLocation - org.baeldung.spring.web.config + com.baeldung.spring.web.config diff --git a/spring-mvc-java/src/test/java/org/baeldung/aop/AopLoggingTest.java b/spring-mvc-java/src/test/java/com/baeldung/aop/AopLoggingTest.java similarity index 95% rename from spring-mvc-java/src/test/java/org/baeldung/aop/AopLoggingTest.java rename to spring-mvc-java/src/test/java/com/baeldung/aop/AopLoggingTest.java index b1c9867e41..19bf4d0fac 100644 --- a/spring-mvc-java/src/test/java/org/baeldung/aop/AopLoggingTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/aop/AopLoggingTest.java @@ -1,8 +1,8 @@ -package org.baeldung.aop; +package com.baeldung.aop; -import org.baeldung.config.TestConfig; -import org.baeldung.dao.FooDao; -import org.baeldung.model.Foo; +import com.baeldung.config.TestConfig; +import com.baeldung.dao.FooDao; +import com.baeldung.model.Foo; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-mvc-java/src/test/java/org/baeldung/aop/AopPerformanceTest.java b/spring-mvc-java/src/test/java/com/baeldung/aop/AopPerformanceTest.java similarity index 95% rename from spring-mvc-java/src/test/java/org/baeldung/aop/AopPerformanceTest.java rename to spring-mvc-java/src/test/java/com/baeldung/aop/AopPerformanceTest.java index 69083c60a2..4ad5a3e1a6 100644 --- a/spring-mvc-java/src/test/java/org/baeldung/aop/AopPerformanceTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/aop/AopPerformanceTest.java @@ -1,7 +1,7 @@ -package org.baeldung.aop; +package com.baeldung.aop; -import org.baeldung.config.TestConfig; -import org.baeldung.dao.FooDao; +import com.baeldung.config.TestConfig; +import com.baeldung.dao.FooDao; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-mvc-java/src/test/java/org/baeldung/aop/AopPublishingTest.java b/spring-mvc-java/src/test/java/com/baeldung/aop/AopPublishingTest.java similarity index 90% rename from spring-mvc-java/src/test/java/org/baeldung/aop/AopPublishingTest.java rename to spring-mvc-java/src/test/java/com/baeldung/aop/AopPublishingTest.java index e691dbd32e..c075db9fc6 100644 --- a/spring-mvc-java/src/test/java/org/baeldung/aop/AopPublishingTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/aop/AopPublishingTest.java @@ -1,9 +1,9 @@ -package org.baeldung.aop; +package com.baeldung.aop; -import org.baeldung.config.TestConfig; -import org.baeldung.dao.FooDao; -import org.baeldung.events.FooCreationEventListener; -import org.baeldung.model.Foo; +import com.baeldung.config.TestConfig; +import com.baeldung.dao.FooDao; +import com.baeldung.events.FooCreationEventListener; +import com.baeldung.model.Foo; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-mvc-java/src/test/java/org/baeldung/aop/AopXmlConfigPerformanceTest.java b/spring-mvc-java/src/test/java/com/baeldung/aop/AopXmlConfigPerformanceTest.java similarity index 94% rename from spring-mvc-java/src/test/java/org/baeldung/aop/AopXmlConfigPerformanceTest.java rename to spring-mvc-java/src/test/java/com/baeldung/aop/AopXmlConfigPerformanceTest.java index 7ef25d743c..4d2df50d18 100644 --- a/spring-mvc-java/src/test/java/org/baeldung/aop/AopXmlConfigPerformanceTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/aop/AopXmlConfigPerformanceTest.java @@ -1,6 +1,6 @@ -package org.baeldung.aop; +package com.baeldung.aop; -import org.baeldung.dao.FooDao; +import com.baeldung.dao.FooDao; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -21,7 +21,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration("/org/baeldung/aop/beans.xml") +@ContextConfiguration("/com/baeldung/aop/beans.xml") public class AopXmlConfigPerformanceTest { @Before diff --git a/spring-mvc-java/src/test/java/com/baeldung/circulardependency/CircularDependencyTest b/spring-mvc-java/src/test/java/com/baeldung/circulardependency/CircularDependencyTest new file mode 100644 index 0000000000..4229f21f10 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/circulardependency/CircularDependencyTest @@ -0,0 +1,35 @@ +package com.baeldung.circulardependency; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { TestConfig.class }) +public class CircularDependencyTest { + + @Autowired + ApplicationContext context; + + @Bean + public CircularDependencyA getCircularDependencyA() { + return new CircularDependencyA(); + } + + @Bean + public CircularDependencyB getCircularDependencyB() { + return new CircularDependencyB(); + } + + @Test + public void givenCircularDependency_whenSetterInjection_thenItWorks() { + final CircularDependencyA circA = context.getBean(CircularDependencyA.class); + + Assert.assertEquals("Hi!", circA.getCircB().getMessage()); + } +} diff --git a/spring-mvc-java/src/test/java/com/baeldung/circulardependency/TestConfig b/spring-mvc-java/src/test/java/com/baeldung/circulardependency/TestConfig new file mode 100644 index 0000000000..a072c5d402 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/circulardependency/TestConfig @@ -0,0 +1,10 @@ +package com.baeldung.circulardependency; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages = { "com.baeldung.circulardependency" }) +public class TestConfig { + +} diff --git a/spring-mvc-java/src/test/java/com/baeldung/config/TestConfig.java b/spring-mvc-java/src/test/java/com/baeldung/config/TestConfig.java new file mode 100644 index 0000000000..641513a24a --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/config/TestConfig.java @@ -0,0 +1,11 @@ +package com.baeldung.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +@Configuration +@ComponentScan(basePackages = { "com.baeldung.dao", "com.baeldung.aop", "com.baeldung.events" }) +@EnableAspectJAutoProxy +public class TestConfig { +} diff --git a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndJUnitTest.java b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndJUnitTest.java new file mode 100644 index 0000000000..58e5f9829b --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndJUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.htmlunit; + +import org.junit.Assert; +import org.junit.Test; + +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.html.HtmlPage; + +public class HtmlUnitAndJUnitTest { + + @Test + public void givenAClient_whenEnteringBaeldung_thenPageTitleIsCorrect() throws Exception { + try (final WebClient webClient = new WebClient()) { + + webClient.getOptions().setThrowExceptionOnScriptError(false); + + final HtmlPage page = webClient.getPage("http://www.baeldung.com/"); + Assert.assertEquals("Baeldung | Java, Spring and Web Development tutorials", page.getTitleText()); + } + } + +} diff --git a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndSpringTest.java b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndSpringTest.java new file mode 100644 index 0000000000..dcc7555ae2 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndSpringTest.java @@ -0,0 +1,79 @@ +package com.baeldung.htmlunit; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.htmlunit.MockMvcWebClientBuilder; +import org.springframework.web.context.WebApplicationContext; + +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.html.HtmlForm; +import com.gargoylesoftware.htmlunit.html.HtmlPage; +import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; +import com.gargoylesoftware.htmlunit.html.HtmlTextInput; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { TestConfig.class }) +public class HtmlUnitAndSpringTest { + + @Autowired + private WebApplicationContext wac; + + private WebClient webClient; + + @Before + public void setup() { + webClient = MockMvcWebClientBuilder.webAppContextSetup(wac).build(); + } + + @Test + @Ignore + public void givenAMessage_whenSent_thenItShows() { + final String text = "Hello world!"; + HtmlPage page; + + try { + + page = webClient.getPage("http://localhost/message/showForm"); + System.out.println(page.asXml()); + + final HtmlTextInput messageText = page.getHtmlElementById("message"); + messageText.setValueAttribute(text); + + final HtmlForm form = page.getForms().get(0); + final HtmlSubmitInput submit = form.getOneHtmlElementByAttribute("input", "type", "submit"); + final HtmlPage newPage = submit.click(); + + final String receivedText = newPage.getHtmlElementById("received").getTextContent(); + + Assert.assertEquals(receivedText, text); + System.out.println(newPage.asXml()); + + } catch (FailingHttpStatusCodeException | IOException e) { + e.printStackTrace(); + } + + } + + @Test + public void givenAClient_whenEnteringBaeldung_thenPageTitleIsCorrect() throws Exception { + try (final WebClient client = new WebClient()) { + + webClient.getOptions().setThrowExceptionOnScriptError(false); + + final HtmlPage page = webClient.getPage("http://www.baeldung.com/"); + Assert.assertEquals("Baeldung | Java, Spring and Web Development tutorials", page.getTitleText()); + } + } + +} diff --git a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitWebScraping.java b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitWebScraping.java new file mode 100644 index 0000000000..16d18717e6 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitWebScraping.java @@ -0,0 +1,40 @@ +package com.baeldung.htmlunit; + +import java.util.List; + +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.html.HtmlAnchor; +import com.gargoylesoftware.htmlunit.html.HtmlHeading1; +import com.gargoylesoftware.htmlunit.html.HtmlHeading2; +import com.gargoylesoftware.htmlunit.html.HtmlPage; + +public class HtmlUnitWebScraping { + + public static void main(final String[] args) throws Exception { + try (final WebClient webClient = new WebClient()) { + + webClient.getOptions().setCssEnabled(false); + webClient.getOptions().setJavaScriptEnabled(false); + + final HtmlPage page = webClient.getPage("http://www.baeldung.com/full_archive"); + final HtmlAnchor latestPostLink = (HtmlAnchor) page.getByXPath("(//ul[@class='car-monthlisting']/li)[1]/a").get(0); + + System.out.println("Entering: " + latestPostLink.getHrefAttribute()); + + final HtmlPage postPage = latestPostLink.click(); + + final HtmlHeading1 heading1 = (HtmlHeading1) postPage.getByXPath("//h1").get(0); + System.out.println("Title: " + heading1.getTextContent()); + + final List headings2 = (List) postPage.getByXPath("//h2"); + + final StringBuilder sb = new StringBuilder(heading1.getTextContent()); + for (final HtmlHeading2 h2 : headings2) { + sb.append("\n").append(h2.getTextContent()); + } + + System.out.println(sb.toString()); + } + } + +} diff --git a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java new file mode 100644 index 0000000000..1357310b1f --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java @@ -0,0 +1,42 @@ +package com.baeldung.htmlunit; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.thymeleaf.spring4.SpringTemplateEngine; +import org.thymeleaf.spring4.view.ThymeleafViewResolver; +import org.thymeleaf.templateresolver.ServletContextTemplateResolver; + +@Configuration +@EnableWebMvc +@ComponentScan(basePackages = { "com.baeldung.web.controller" }) +public class TestConfig extends WebMvcConfigurerAdapter { + + @Bean + public ViewResolver thymeleafViewResolver() { + final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); + viewResolver.setTemplateEngine(templateEngine()); + viewResolver.setOrder(1); + return viewResolver; + } + + @Bean + public ServletContextTemplateResolver templateResolver() { + final ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(); + templateResolver.setPrefix("/WEB-INF/templates/"); + templateResolver.setSuffix(".html"); + templateResolver.setTemplateMode("HTML5"); + return templateResolver; + } + + @Bean + public SpringTemplateEngine templateEngine() { + final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.setTemplateResolver(templateResolver()); + return templateEngine; + } + +} diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeTest.java new file mode 100644 index 0000000000..c1e79a2a63 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeTest.java @@ -0,0 +1,42 @@ +package com.baeldung.web.controller; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.spring.web.config.WebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = WebConfig.class) +public class EmployeeTest { + + @Autowired + private WebApplicationContext webAppContext; + private MockMvc mockMvc; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mockMvc = MockMvcBuilders.webAppContextSetup(webAppContext).build(); + } + + @Test + public void whenEmployeeGETisPerformed_thenRetrievedStatusAndViewNameAndAttributeAreCorrect() throws Exception { + mockMvc.perform(get("/employee")).andExpect(status().isOk()).andExpect(view().name("employeeHome")).andExpect(model().attributeExists("employee")).andDo(print()); + } +} diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeTestWithoutMockMvc.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeTestWithoutMockMvc.java new file mode 100644 index 0000000000..19806e0559 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeTestWithoutMockMvc.java @@ -0,0 +1,51 @@ +package com.baeldung.web.controller; + +import org.junit.Before; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import com.baeldung.model.Employee; +import com.baeldung.spring.web.config.WebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = WebConfig.class) +public class EmployeeTestWithoutMockMvc { + + @Autowired + private EmployeeController employeeController; + + @Before + public void setup() { + employeeController.initEmployees(); + } + + @Test + public void whenInitEmployees_thenVerifyValuesInitiation() { + + Employee employee1 = employeeController.employeeMap.get(1L); + Employee employee2 = employeeController.employeeMap.get(2L); + Employee employee3 = employeeController.employeeMap.get(3L); + + Assert.assertTrue(employee1.getId() == 1L); + Assert.assertTrue(employee1.getName().equals("John")); + Assert.assertTrue(employee1.getContactNumber().equals("223334411")); + Assert.assertTrue(employee1.getWorkingArea().equals("rh")); + + Assert.assertTrue(employee2.getId() == 2L); + Assert.assertTrue(employee2.getName().equals("Peter")); + Assert.assertTrue(employee2.getContactNumber().equals("22001543")); + Assert.assertTrue(employee2.getWorkingArea().equals("informatics")); + + Assert.assertTrue(employee3.getId() == 3L); + Assert.assertTrue(employee3.getName().equals("Mike")); + Assert.assertTrue(employee3.getContactNumber().equals("223334411")); + Assert.assertTrue(employee3.getWorkingArea().equals("admin")); + } + +} diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java new file mode 100644 index 0000000000..d1d1167369 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java @@ -0,0 +1,92 @@ +package com.baeldung.web.controller; + + +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +import javax.servlet.ServletContext; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.spring.web.config.ApplicationConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = {ApplicationConfig.class}) +public class GreetControllerIntegrationTest { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + private static final String CONTENT_TYPE = "application/json"; + + + @Before + public void setup() throws Exception { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void givenWAC_whenServletContext_thenItProvidesGreetController() { + ServletContext servletContext = wac.getServletContext(); + Assert.assertNotNull(servletContext); + Assert.assertTrue(servletContext instanceof MockServletContext); + Assert.assertNotNull(wac.getBean("greetController")); + } + + @Test + public void givenHomePageURI_whenMockMVC_thenReturnsIndexJSPViewName() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/homePage")).andDo(print()).andExpect(MockMvcResultMatchers.view().name("index")); + } + + @Test + public void givenGreetURI_whenMockMVC_thenVerifyResponse() throws Exception { + MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders.get("/greet")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.jsonPath("$.message").value("Hello World!!!")).andReturn(); + Assert.assertEquals(CONTENT_TYPE, mvcResult.getResponse().getContentType()); + } + + @Test + public void givenGreetURIWithPathVariable_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/greetWithPathVariable/John")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$.message").value("Hello World John!!!")); + } + + @Test + public void givenGreetURIWithPathVariable_2_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/greetWithPathVariable/{name}", "Doe")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$.message").value("Hello World Doe!!!")); + } + + @Test + public void givenGreetURIWithQueryParameter_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/greetWithQueryVariable").param("name", "John Doe")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)).andExpect(MockMvcResultMatchers.jsonPath("$.message").value("Hello World John Doe!!!")); + } + + @Test + public void givenGreetURIWithPost_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.post("/greetWithPost")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)) + .andExpect(MockMvcResultMatchers.jsonPath("$.message").value("Hello World!!!")); + } + + @Test + public void givenGreetURIWithPostAndFormData_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.post("/greetWithPostAndFormData").param("id", "1").param("name", "John Doe")).andDo(print()).andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)).andExpect(MockMvcResultMatchers.jsonPath("$.message").value("Hello World John Doe!!!")).andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1)); + } +} \ No newline at end of file diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerTest.java new file mode 100644 index 0000000000..0fd71a46dd --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerTest.java @@ -0,0 +1,61 @@ +package com.baeldung.web.controller; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +public class GreetControllerTest { + + private MockMvc mockMvc; + private static final String CONTENT_TYPE = "application/json"; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.standaloneSetup(new GreetController()).build(); + } + + @Test + public void givenHomePageURI_whenMockMVC_thenReturnsIndexJSPViewName() throws Exception { + this.mockMvc.perform(get("/homePage")).andExpect(view().name("index")); + } + + @Test + public void givenGreetURI_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(get("/greet")).andExpect(status().isOk()).andExpect(content().contentType(CONTENT_TYPE)).andExpect(jsonPath("$.message").value("Hello World!!!")); + } + + @Test + public void givenGreetURIWithPathVariable_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(get("/greetWithPathVariable/John")).andExpect(status().isOk()).andExpect(content().contentType(CONTENT_TYPE)).andExpect(jsonPath("$.message").value("Hello World John!!!")); + } + + @Test + public void givenGreetURIWithPathVariable_2_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(get("/greetWithPathVariable/{name}", "Doe")).andExpect(status().isOk()).andExpect(content().contentType(CONTENT_TYPE)).andExpect(jsonPath("$.message").value("Hello World Doe!!!")); + } + + @Test + public void givenGreetURIWithQueryParameter_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(get("/greetWithQueryVariable").param("name", "John Doe")).andDo(print()).andExpect(status().isOk()) + .andExpect(content().contentType(CONTENT_TYPE)).andExpect(jsonPath("$.message").value("Hello World John Doe!!!")); + } + + @Test + public void givenGreetURIWithPost_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.post("/greetWithPost")).andDo(print()).andExpect(status().isOk()).andExpect(content().contentType(CONTENT_TYPE)) + .andExpect(jsonPath("$.message").value("Hello World!!!")); + } + + @Test + public void givenGreetURIWithPostAndFormData_whenMockMVC_thenVerifyResponse() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.post("/greetWithPostAndFormData").param("id", "1").param("name", "John Doe")).andDo(print()).andExpect(status().isOk()) + .andExpect(content().contentType(CONTENT_TYPE)).andExpect(jsonPath("$.message").value("Hello World John Doe!!!")).andExpect(jsonPath("$.id").value(1)); + } +} diff --git a/spring-mvc-java/src/test/java/org/baeldung/config/TestConfig.java b/spring-mvc-java/src/test/java/org/baeldung/config/TestConfig.java deleted file mode 100644 index f9573b2add..0000000000 --- a/spring-mvc-java/src/test/java/org/baeldung/config/TestConfig.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.baeldung.config; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.EnableAspectJAutoProxy; - -@Configuration -@ComponentScan(basePackages = { "org.baeldung.dao", "org.baeldung.aop", "org.baeldung.events" }) -@EnableAspectJAutoProxy -public class TestConfig { -} diff --git a/spring-mvc-java/src/test/resources/log4j.properties b/spring-mvc-java/src/test/resources/log4j.properties deleted file mode 100644 index 6193d62fd8..0000000000 --- a/spring-mvc-java/src/test/resources/log4j.properties +++ /dev/null @@ -1,9 +0,0 @@ -# Set root logger level to DEBUG and its only appender to A1. -log4j.rootLogger=WARN, A1 - -# A1 is set to be a ConsoleAppender. -log4j.appender.A1=org.apache.log4j.ConsoleAppender - -# A1 uses PatternLayout. -log4j.appender.A1.layout=org.apache.log4j.PatternLayout -log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n \ No newline at end of file diff --git a/spring-mvc-java/src/test/resources/logback-test.xml b/spring-mvc-java/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..e0721aa890 --- /dev/null +++ b/spring-mvc-java/src/test/resources/logback-test.xml @@ -0,0 +1,21 @@ + + + + + + %date [%thread] %-5level %logger{6} - %message%n + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-mvc-no-xml/.classpath b/spring-mvc-no-xml/.classpath deleted file mode 100644 index 6b533711d3..0000000000 --- a/spring-mvc-no-xml/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-mvc-no-xml/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-mvc-no-xml/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-mvc-no-xml/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-mvc-no-xml/.project b/spring-mvc-no-xml/.project deleted file mode 100644 index 9e6d801990..0000000000 --- a/spring-mvc-no-xml/.project +++ /dev/null @@ -1,43 +0,0 @@ - - - spring-mvc-no-xml - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-mvc-no-xml/.settings/.jsdtscope b/spring-mvc-no-xml/.settings/.jsdtscope deleted file mode 100644 index b46b9207a8..0000000000 --- a/spring-mvc-no-xml/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-mvc-no-xml/.settings/org.eclipse.jdt.core.prefs b/spring-mvc-no-xml/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 5ff04b9f96..0000000000 --- a/spring-mvc-no-xml/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,91 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-mvc-no-xml/.settings/org.eclipse.jdt.ui.prefs b/spring-mvc-no-xml/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-mvc-no-xml/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-mvc-no-xml/.settings/org.eclipse.m2e.core.prefs b/spring-mvc-no-xml/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-mvc-no-xml/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-mvc-no-xml/.settings/org.eclipse.m2e.wtp.prefs b/spring-mvc-no-xml/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-mvc-no-xml/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-mvc-no-xml/.settings/org.eclipse.wst.common.component b/spring-mvc-no-xml/.settings/org.eclipse.wst.common.component deleted file mode 100644 index a37385bf84..0000000000 --- a/spring-mvc-no-xml/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-mvc-no-xml/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-mvc-no-xml/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 9ca0d1c1b7..0000000000 --- a/spring-mvc-no-xml/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/spring-mvc-no-xml/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-mvc-no-xml/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-mvc-no-xml/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-mvc-no-xml/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-mvc-no-xml/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-mvc-no-xml/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-mvc-no-xml/.settings/org.eclipse.wst.validation.prefs b/spring-mvc-no-xml/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-mvc-no-xml/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-mvc-no-xml/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-mvc-no-xml/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-mvc-no-xml/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-mvc-no-xml/.springBeans b/spring-mvc-no-xml/.springBeans deleted file mode 100644 index 7623a7e888..0000000000 --- a/spring-mvc-no-xml/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/spring-mvc-no-xml/README.md b/spring-mvc-no-xml/README.md index 5ffe2385b5..208cb35f78 100644 --- a/spring-mvc-no-xml/README.md +++ b/spring-mvc-no-xml/README.md @@ -2,6 +2,8 @@ ## Spring MVC with NO XML Configuration Example Project +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- \ No newline at end of file +- diff --git a/spring-mvc-no-xml/pom.xml b/spring-mvc-no-xml/pom.xml index da71a699db..202aee7295 100644 --- a/spring-mvc-no-xml/pom.xml +++ b/spring-mvc-no-xml/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung 0.1-SNAPSHOT spring-mvc-no-xml @@ -144,7 +144,7 @@ - 4.2.4.RELEASE + 4.2.5.RELEASE 1.7.13 @@ -158,14 +158,14 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-mvc-tiles/pom.xml b/spring-mvc-tiles/pom.xml new file mode 100644 index 0000000000..1a72549e70 --- /dev/null +++ b/spring-mvc-tiles/pom.xml @@ -0,0 +1,85 @@ + + 4.0.0 + com.baeldung + spring-mvc-tiles + 0.0.1-SNAPSHOT + war + spring-mvc-tiles + Integrating Spring MVC with Apache Tiles + + + 4.3.2.RELEASE + 3.0.5 + + + + + + org.springframework + spring-core + ${springframework.version} + + + org.springframework + spring-web + ${springframework.version} + + + org.springframework + spring-webmvc + ${springframework.version} + + + + org.apache.tiles + tiles-jsp + ${apachetiles.version} + + + + + javax.servlet + javax.servlet-api + 3.1.0 + + + javax.servlet.jsp + javax.servlet.jsp-api + 2.3.1 + + + javax.servlet + jstl + 1.2 + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.2 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-war-plugin + 2.4 + + src/main/webapp + spring-mvc-tiles + false + + + + + spring-mvc-tiles + + diff --git a/spring-mvc-tiles/src/main/java/com/baeldung/tiles/springmvc/ApplicationConfiguration.java b/spring-mvc-tiles/src/main/java/com/baeldung/tiles/springmvc/ApplicationConfiguration.java new file mode 100644 index 0000000000..d2e90a4f53 --- /dev/null +++ b/spring-mvc-tiles/src/main/java/com/baeldung/tiles/springmvc/ApplicationConfiguration.java @@ -0,0 +1,47 @@ +package com.baeldung.tiles.springmvc; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.tiles3.TilesConfigurer; +import org.springframework.web.servlet.view.tiles3.TilesViewResolver; + +@Configuration +@EnableWebMvc +@ComponentScan(basePackages = "com.baeldung.tiles.springmvc") +public class ApplicationConfiguration extends WebMvcConfigurerAdapter { + + /** + * Configure TilesConfigurer. + */ + @Bean + public TilesConfigurer tilesConfigurer() { + TilesConfigurer tilesConfigurer = new TilesConfigurer(); + tilesConfigurer.setDefinitions(new String[] { "/WEB-INF/views/**/tiles.xml" }); + tilesConfigurer.setCheckRefresh(true); + return tilesConfigurer; + } + + /** + * Configure ViewResolvers to deliver views. + */ + @Override + public void configureViewResolvers(ViewResolverRegistry registry) { + TilesViewResolver viewResolver = new TilesViewResolver(); + registry.viewResolver(viewResolver); + } + + /** + * Configure ResourceHandlers to serve static resources + */ + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/static/**").addResourceLocations("/static/"); + } + +} diff --git a/spring-mvc-tiles/src/main/java/com/baeldung/tiles/springmvc/ApplicationController.java b/spring-mvc-tiles/src/main/java/com/baeldung/tiles/springmvc/ApplicationController.java new file mode 100644 index 0000000000..1a348d1c26 --- /dev/null +++ b/spring-mvc-tiles/src/main/java/com/baeldung/tiles/springmvc/ApplicationController.java @@ -0,0 +1,26 @@ +package com.baeldung.tiles.springmvc; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +@RequestMapping("/") +public class ApplicationController { + + @RequestMapping(value = { "/" }, method = RequestMethod.GET) + public String homePage(ModelMap model) { + return "home"; + } + + @RequestMapping(value = { "/apachetiles" }, method = RequestMethod.GET) + public String productsPage(ModelMap model) { + return "apachetiles"; + } + + @RequestMapping(value = { "/springmvc" }, method = RequestMethod.GET) + public String contactUsPage(ModelMap model) { + return "springmvc"; + } +} diff --git a/spring-mvc-tiles/src/main/java/com/baeldung/tiles/springmvc/ApplicationInitializer.java b/spring-mvc-tiles/src/main/java/com/baeldung/tiles/springmvc/ApplicationInitializer.java new file mode 100644 index 0000000000..79583dbe83 --- /dev/null +++ b/spring-mvc-tiles/src/main/java/com/baeldung/tiles/springmvc/ApplicationInitializer.java @@ -0,0 +1,22 @@ +package com.baeldung.tiles.springmvc; + +import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; + +public class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { + + @Override + protected Class[] getRootConfigClasses() { + return new Class[] { ApplicationConfiguration.class }; + } + + @Override + protected Class[] getServletConfigClasses() { + return null; + } + + @Override + protected String[] getServletMappings() { + return new String[] { "/" }; + } + +} diff --git a/spring-mvc-tiles/src/main/webapp/WEB-INF/views/pages/apachetiles.jsp b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/pages/apachetiles.jsp new file mode 100644 index 0000000000..9936957c04 --- /dev/null +++ b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/pages/apachetiles.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Apache Tiles + + +

    Tiles with Spring MVC Demo

    + + \ No newline at end of file diff --git a/spring-mvc-tiles/src/main/webapp/WEB-INF/views/pages/home.jsp b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/pages/home.jsp new file mode 100644 index 0000000000..b501d4968e --- /dev/null +++ b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/pages/home.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Home + + +

    Welcome to Apache Tiles integration with Spring MVC

    + + \ No newline at end of file diff --git a/spring-mvc-tiles/src/main/webapp/WEB-INF/views/pages/springmvc.jsp b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/pages/springmvc.jsp new file mode 100644 index 0000000000..209b1004de --- /dev/null +++ b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/pages/springmvc.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Spring MVC + + +

    Spring MVC configured to work with Apache Tiles

    + + \ No newline at end of file diff --git a/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/layouts/defaultLayout.jsp b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/layouts/defaultLayout.jsp new file mode 100644 index 0000000000..2370ad4ab1 --- /dev/null +++ b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/layouts/defaultLayout.jsp @@ -0,0 +1,25 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@ page isELIgnored="false"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%> + + + + + +<tiles:getAsString name="title" /> + + + + +
    + + +
    + +
    + +
    + + diff --git a/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/templates/defaultFooter.jsp b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/templates/defaultFooter.jsp new file mode 100644 index 0000000000..3849cc5230 --- /dev/null +++ b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/templates/defaultFooter.jsp @@ -0,0 +1,2 @@ + +
    copyright © Baeldung
    diff --git a/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/templates/defaultHeader.jsp b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/templates/defaultHeader.jsp new file mode 100644 index 0000000000..8a878c857d --- /dev/null +++ b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/templates/defaultHeader.jsp @@ -0,0 +1,3 @@ +
    +

    Welcome to Spring MVC integration with Apache Tiles

    +
    \ No newline at end of file diff --git a/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/templates/defaultMenu.jsp b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/templates/defaultMenu.jsp new file mode 100644 index 0000000000..2c91eace85 --- /dev/null +++ b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/templates/defaultMenu.jsp @@ -0,0 +1,8 @@ + diff --git a/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/tiles.xml b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/tiles.xml new file mode 100644 index 0000000000..789fbd809a --- /dev/null +++ b/spring-mvc-tiles/src/main/webapp/WEB-INF/views/tiles/tiles.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-mvc-tiles/src/main/webapp/static/css/app.css b/spring-mvc-tiles/src/main/webapp/static/css/app.css new file mode 100644 index 0000000000..9976e5406e --- /dev/null +++ b/spring-mvc-tiles/src/main/webapp/static/css/app.css @@ -0,0 +1,36 @@ +.flex-container { + display: -webkit-flex; + display: flex; + -webkit-flex-flow: row wrap; + flex-flow: row wrap; + text-align: center; +} + +.flex-container > * { + padding: 15px; + -webkit-flex: 1 100%; + flex: 1 100%; +} + +.article { + text-align: left; +} + +header {background: black;color:white;} +footer {background: #aaa;color:white;} +.nav {background:#eee;} + +.nav ul { + list-style-type: none; + padding: 0; +} + +.nav ul a { + text-decoration: none; +} + +@media all and (min-width: 768px) { + .nav {text-align:left;-webkit-flex: 1 auto;flex:1 auto;-webkit-order:1;order:1;} + .article {-webkit-flex:5 0px;flex:5 0px;-webkit-order:2;order:2;} + footer {-webkit-order:3;order:3;} +} \ No newline at end of file diff --git a/spring-mvc-velocity/pom.xml b/spring-mvc-velocity/pom.xml new file mode 100644 index 0000000000..6c63e0be18 --- /dev/null +++ b/spring-mvc-velocity/pom.xml @@ -0,0 +1,179 @@ + + 4.0.0 + com.baeldung + 0.1-SNAPSHOT + spring-mvc-velocity + + spring-mvc-velocity + war + + + + + + + org.springframework + spring-web + ${org.springframework.version} + + + org.springframework + spring-webmvc + ${org.springframework.version} + + + org.springframework + spring-core + ${org.springframework.version} + + + org.springframework + spring-context-support + ${org.springframework.version} + + + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + org.apache.velocity + velocity + 1.7 + + + + org.apache.velocity + velocity-tools + 2.0 + + + + + + junit + junit + ${junit.version} + test + + + + org.hamcrest + hamcrest-core + ${org.hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito + ${powermock.version} + test + + + org.springframework + spring-test + ${org.springframework.version} + test + + + + + + spring-mvc-velocity + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + + + + + + + + + + + + + + 4.1.4.RELEASE + + + + 1.3 + 4.12 + 1.10.19 + 1.6.4 + + 4.4.1 + 4.5 + + 2.4.1 + + + 3.5.1 + 2.6 + 2.19.1 + 2.7 + 1.4.18 + + + + \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java new file mode 100644 index 0000000000..679a455f3f --- /dev/null +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java @@ -0,0 +1,42 @@ +package com.baeldung.mvc.velocity.controller; + +import com.baeldung.mvc.velocity.domain.Tutorial; +import com.baeldung.mvc.velocity.service.ITutorialsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.List; + +@Controller +@RequestMapping("/") +public class MainController { + + @Autowired + private ITutorialsService tutService; + + @RequestMapping(value ="/", method = RequestMethod.GET) + public String welcomePage() { + return "index"; + } + + + @RequestMapping(value ="/list", method = RequestMethod.GET) + public String listTutorialsPage(Model model) { + List list = tutService.listTutorials(); + model.addAttribute("tutorials", list); + return "list"; + } + + public ITutorialsService getTutService() { + return tutService; + } + + public void setTutService(ITutorialsService tutService) { + this.tutService = tutService; + } + + +} \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java new file mode 100644 index 0000000000..ccbaa0e905 --- /dev/null +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java @@ -0,0 +1,33 @@ +package com.baeldung.mvc.velocity.domain; + +public class Tutorial { + + private final Integer tutId; + private final String title; + private final String description; + private final String author; + + public Tutorial(Integer tutId, String title, String description, String author) { + this.tutId = tutId; + this.title = title; + this.description = description; + this.author = author; + } + + public Integer getTutId() { + return tutId; + } + + public String getTitle() { + return title; + } + + public String getDescription() { + return description; + } + + public String getAuthor() { + return author; + } + +} diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/ITutorialsService.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/ITutorialsService.java new file mode 100644 index 0000000000..24059f2662 --- /dev/null +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/ITutorialsService.java @@ -0,0 +1,10 @@ +package com.baeldung.mvc.velocity.service; + +import com.baeldung.mvc.velocity.domain.Tutorial; + +import java.util.List; + +public interface ITutorialsService { + + List listTutorials(); +} diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java new file mode 100644 index 0000000000..f67cc0824f --- /dev/null +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java @@ -0,0 +1,18 @@ +package com.baeldung.mvc.velocity.service; + +import com.baeldung.mvc.velocity.domain.Tutorial; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.List; + +@Service +public class TutorialsService implements ITutorialsService { + + public List listTutorials() { + return Arrays.asList( + new Tutorial(1, "Guava", "Introduction to Guava", "GuavaAuthor"), + new Tutorial(2, "Android", "Introduction to Android", "AndroidAuthor") + ); + } +} diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/MainWebAppInitializer.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/MainWebAppInitializer.java new file mode 100644 index 0000000000..a2871716df --- /dev/null +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/MainWebAppInitializer.java @@ -0,0 +1,36 @@ +package com.baeldung.mvc.velocity.spring.config; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; +import java.util.Set; + +public class MainWebAppInitializer implements WebApplicationInitializer { + + @Override + public void onStartup(final ServletContext sc) throws ServletException { + + // Create the 'root' Spring application context + final AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); + root.register(WebConfig.class); + + // Manages the lifecycle of the root application context + sc.addListener(new ContextLoaderListener(root)); + + // Handles requests into the application + final ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext())); + appServlet.setLoadOnStartup(1); + + final Set mappingConflicts = appServlet.addMapping("/"); + if (!mappingConflicts.isEmpty()) { + throw new IllegalStateException("'appServlet' could not be mapped to '/' due " + "to an existing mapping. This is a known issue under Tomcat versions " + "<= 7.0.14; see https://issues.apache.org/bugzilla/show_bug.cgi?id=51278"); + } + } + +} diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/WebConfig.java b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/WebConfig.java new file mode 100644 index 0000000000..ce8ce1919a --- /dev/null +++ b/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/WebConfig.java @@ -0,0 +1,45 @@ +package com.baeldung.mvc.velocity.spring.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.velocity.VelocityConfigurer; +import org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver; + +@Configuration +@EnableWebMvc +@ComponentScan(basePackages = { "com.baeldung.mvc.velocity.controller", "com.baeldung.mvc.velocity.service"}) +public class WebConfig extends WebMvcConfigurerAdapter { + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } + + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + @Bean + public ViewResolver viewResolver() { + final VelocityLayoutViewResolver bean = new VelocityLayoutViewResolver(); + bean.setCache(true); + bean.setPrefix("/WEB-INF/views/"); + bean.setLayoutUrl("/WEB-INF/layouts/layout.vm"); + bean.setSuffix(".vm"); + return bean; + } + + @Bean + public VelocityConfigurer velocityConfig() { + VelocityConfigurer velocityConfigurer = new VelocityConfigurer(); + velocityConfigurer.setResourceLoaderPath("/"); + return velocityConfigurer; + } +} diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm b/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm new file mode 100644 index 0000000000..41bb36ce5e --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm @@ -0,0 +1,4 @@ +
    + @Copyright baeldung.com +
    \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm b/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm new file mode 100644 index 0000000000..8fffa6cdab --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm @@ -0,0 +1,5 @@ +
    +
    +

    Our tutorials

    +
    +
    \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm b/spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm new file mode 100644 index 0000000000..3bac96aaae --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm @@ -0,0 +1,22 @@ + + + Spring with Velocity + + +
    + #parse("/WEB-INF/fragments/header.vm") +
    + + +
    + + + $screen_content + +
    + +
    + #parse("/WEB-INF/fragments/footer.vm") +
    + + \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml new file mode 100644 index 0000000000..8b4fd570fe --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + / + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml b/spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml new file mode 100644 index 0000000000..2f3b0f19bb --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm b/spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm new file mode 100644 index 0000000000..8883a50658 --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm @@ -0,0 +1,4 @@ +

    Index

    + +

    Welcome page

    +This is just the welcome page \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/views/list.vm b/spring-mvc-velocity/src/main/webapp/WEB-INF/views/list.vm new file mode 100644 index 0000000000..9e06a09e4f --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/views/list.vm @@ -0,0 +1,19 @@ +

    Index

    + +

    Tutorials list

    + + + + + + + +#foreach($tut in $tutorials) + + + + + + +#end +
    Tutorial IdTutorial TitleTutorial DescriptionTutorial Author
    $tut.tutId$tut.title$tut.description$tut.author
    \ No newline at end of file diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/web_old.xml b/spring-mvc-velocity/src/main/webapp/WEB-INF/web_old.xml new file mode 100644 index 0000000000..72050c0d37 --- /dev/null +++ b/spring-mvc-velocity/src/main/webapp/WEB-INF/web_old.xml @@ -0,0 +1,32 @@ + + + + Spring MVC Velocity + + + mvc + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + /WEB-INF/mvc-servlet.xml + + 1 + + + + mvc + /* + + + + contextConfigLocation + /WEB-INF/spring-context.xml + + + + org.springframework.web.context.ContextLoaderListener + + \ No newline at end of file diff --git a/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/DataContentControllerTest.java b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/DataContentControllerTest.java new file mode 100644 index 0000000000..a9fb242755 --- /dev/null +++ b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/DataContentControllerTest.java @@ -0,0 +1,61 @@ +package com.baeldung.mvc.velocity.test; + +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.mvc.velocity.spring.config.WebConfig; +import com.baeldung.mvc.velocity.test.config.TestConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +// @ContextConfiguration(locations = {"classpath:mvc-servlet.xml"}) +@ContextConfiguration(classes = { TestConfig.class, WebConfig.class }) +@WebAppConfiguration +public class DataContentControllerTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext webApplicationContext; + + @Before + public void setUp() { + + + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + } + + @Test + public void whenCallingList_ThenModelAndContentOK() throws Exception { + + mockMvc.perform(get("/list")).andExpect(status().isOk()).andExpect(view().name("list")).andExpect(model().attribute("tutorials", hasSize(2))) + .andExpect(model().attribute("tutorials", hasItem(allOf(hasProperty("tutId", is(1)), hasProperty("author", is("GuavaAuthor")), hasProperty("title", is("Guava")))))) + .andExpect(model().attribute("tutorials", hasItem(allOf(hasProperty("tutId", is(2)), hasProperty("author", is("AndroidAuthor")), hasProperty("title", is("Android")))))); + + mockMvc.perform(get("/list")).andExpect(xpath("//table").exists()); + mockMvc.perform(get("/list")).andExpect(xpath("//td[@id='tutId_1']").exists()); + } + + @Test + public void whenCallingIndex_thenViewOK() throws Exception{ + mockMvc.perform(get("/")).andExpect(status().isOk()).andExpect(view().name("index")).andExpect(model().size(0)); + } +} diff --git a/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/config/TestConfig.java b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/config/TestConfig.java new file mode 100644 index 0000000000..8b84bcdd23 --- /dev/null +++ b/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/config/TestConfig.java @@ -0,0 +1,32 @@ +package com.baeldung.mvc.velocity.test.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.view.velocity.VelocityConfigurer; +import org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver; + +@Configuration +public class TestConfig { + + + @Bean + public ViewResolver viewResolver() { + final VelocityLayoutViewResolver bean = new VelocityLayoutViewResolver(); + bean.setCache(true); + bean.setPrefix("/WEB-INF/views/"); + bean.setLayoutUrl("/WEB-INF/layouts/layout.vm"); + bean.setSuffix(".vm"); + return bean; + } + + @Bean + public VelocityConfigurer velocityConfig() { + VelocityConfigurer velocityConfigurer = new VelocityConfigurer(); + velocityConfigurer.setResourceLoaderPath("/"); + return velocityConfigurer; + } + + + +} diff --git a/spring-mvc-velocity/src/test/resources/mvc-servlet.xml b/spring-mvc-velocity/src/test/resources/mvc-servlet.xml new file mode 100644 index 0000000000..8b4fd570fe --- /dev/null +++ b/spring-mvc-velocity/src/test/resources/mvc-servlet.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + / + + + + + + + + + + + + \ No newline at end of file diff --git a/sandbox/src/test/resources/.gitignore b/spring-mvc-web-vs-initializer/.gitignore similarity index 100% rename from sandbox/src/test/resources/.gitignore rename to spring-mvc-web-vs-initializer/.gitignore diff --git a/spring-mvc-web-vs-initializer/README.MD b/spring-mvc-web-vs-initializer/README.MD new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/spring-mvc-web-vs-initializer/README.MD @@ -0,0 +1 @@ + diff --git a/spring-mvc-web-vs-initializer/pom.xml b/spring-mvc-web-vs-initializer/pom.xml new file mode 100644 index 0000000000..0d735e7188 --- /dev/null +++ b/spring-mvc-web-vs-initializer/pom.xml @@ -0,0 +1,201 @@ + + 4.0.0 + com.baeldung + spring-mvc-web-vs-initializer + 0.1-SNAPSHOT + + spring-mvc-web-vs-initializer + war + + + org.springframework.boot + spring-boot-starter-parent + 1.3.6.RELEASE + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + + org.springframework + spring-web + + + org.springframework + spring-webmvc + + + org.springframework + spring-context + + + + + + javax.servlet + javax.servlet-api + provided + + + + javax.servlet + jstl + runtime + + + + + + com.google.guava + guava + ${guava.version} + + + + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + + + + org.slf4j + jcl-over-slf4j + + + + org.slf4j + log4j-over-slf4j + + + + + + org.springframework + spring-test + test + + + + junit + junit + test + + + + org.assertj + assertj-core + 3.5.1 + test + + + + org.hamcrest + hamcrest-core + test + + + org.hamcrest + hamcrest-library + test + + + + org.mockito + mockito-core + test + + + + org.easymock + easymock + 3.4 + test + + + + + + + + + + org.springframework + spring-framework-bom + ${org.springframework.version} + pom + import + + + + org.springframework + spring-core + ${org.springframework.version} + + + + + + + + spring-mvc-web-vs-initializer + + + src/main/resources + true + + + + + + + + 4.3.1.RELEASE + 4.0.4.RELEASE + 3.20.0-GA + 1.2 + + + 4.3.11.Final + 5.1.38 + + + 1.7.13 + 1.1.3 + + + 5.2.2.Final + + + 19.0 + 3.4 + + + 1.3 + 4.12 + 1.10.19 + + 4.4.1 + 4.5 + + 2.9.0 + + + 3.5.1 + 2.6 + 2.19.1 + 2.7 + 1.4.18 + + + + \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/AppInitializer.java b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/AppInitializer.java new file mode 100644 index 0000000000..21e33820ca --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/AppInitializer.java @@ -0,0 +1,26 @@ +package org.baeldung.config; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +public class AppInitializer implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext container) throws ServletException { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setConfigLocation("org.baeldung.config"); + + container.addListener(new ContextLoaderListener(context)); + + ServletRegistration.Dynamic dispatcher = container.addServlet("java-servlet", new DispatcherServlet(context)); + dispatcher.setLoadOnStartup(1); + dispatcher.addMapping("/java-servlet/*"); + } + +} diff --git a/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/MvcConfig.java b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/MvcConfig.java new file mode 100644 index 0000000000..d460113458 --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/MvcConfig.java @@ -0,0 +1,25 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +@Configuration +@EnableWebMvc +@ComponentScan(basePackages = "org.baeldung.controller.java") +public class MvcConfig extends WebMvcConfigurerAdapter { + + @Bean + public ViewResolver viewResolver() { + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/WEB-INF/view/"); + viewResolver.setSuffix(".jsp"); + + return viewResolver; + } + +} diff --git a/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/java/JavaController.java b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/java/JavaController.java new file mode 100644 index 0000000000..c979c88b34 --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/java/JavaController.java @@ -0,0 +1,18 @@ +package org.baeldung.controller.java; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +@Controller +public class JavaController { + + @RequestMapping(value = "/endpoint") + public ModelAndView handleRequestFromJavaConfiguredServlet() { + ModelAndView mv = new ModelAndView(); + mv.setViewName("from-java"); + + return mv; + } + +} \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/xml/XmlController.java b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/xml/XmlController.java new file mode 100644 index 0000000000..bdefc1781c --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/xml/XmlController.java @@ -0,0 +1,18 @@ +package org.baeldung.controller.xml; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +@Controller +public class XmlController { + + @RequestMapping(value = "/endpoint") + public ModelAndView handleRequestFromXmlConfiguredServlet() { + ModelAndView mv = new ModelAndView(); + mv.setViewName("from-xml"); + + return mv; + } + +} \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/resources/mvc-configuration.xml b/spring-mvc-web-vs-initializer/src/main/resources/mvc-configuration.xml new file mode 100644 index 0000000000..7505614c99 --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/resources/mvc-configuration.xml @@ -0,0 +1,20 @@ + + + + + + + + + /WEB-INF/view/ + + + .jsp + + + + \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/view/from-java.jsp b/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/view/from-java.jsp new file mode 100644 index 0000000000..e54d7520dc --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/view/from-java.jsp @@ -0,0 +1,7 @@ + + + + +

    Java

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

    XML

    + + \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/web.xml b/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..9bebc263be --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,24 @@ + + + + xml-servlet + + org.springframework.web.servlet.DispatcherServlet + + 1 + + contextConfigLocation + classpath*:mvc-configuration.xml + + + + + xml-servlet + /xml-servlet/* + + + diff --git a/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/JavaServletTest.java b/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/JavaServletTest.java new file mode 100644 index 0000000000..99b5ef8c2f --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/JavaServletTest.java @@ -0,0 +1,45 @@ +package org.baeldung.controller; + +import org.baeldung.config.MvcConfig; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.AnnotationConfigWebContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.ModelAndView; + + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(loader=AnnotationConfigWebContextLoader.class, classes = MvcConfig.class) +public class JavaServletTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + @Before + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void testJavaEndpoint() throws Exception { + ModelAndView mv = this.mockMvc.perform(MockMvcRequestBuilders.get("/endpoint")) + .andReturn() + .getModelAndView(); + + // validate view name + Assert.assertSame(mv.getViewName(), "from-java"); + } + +} diff --git a/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/XmlServletTest.java b/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/XmlServletTest.java new file mode 100644 index 0000000000..e7695e36c0 --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/XmlServletTest.java @@ -0,0 +1,44 @@ +package org.baeldung.controller; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.GenericXmlWebContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.ModelAndView; + + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(loader=GenericXmlWebContextLoader.class, locations = "classpath*:mvc-configuration.xml") +public class XmlServletTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + @Before + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void testXmlEndpoint() throws Exception { + ModelAndView mv = this.mockMvc.perform(MockMvcRequestBuilders.get("/endpoint")) + .andReturn() + .getModelAndView(); + + // validate view name + Assert.assertSame(mv.getViewName(), "from-xml"); + } + +} diff --git a/spring-mvc-xml/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-mvc-xml/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-mvc-xml/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-mvc-xml/.project b/spring-mvc-xml/.project deleted file mode 100644 index de41bcaace..0000000000 --- a/spring-mvc-xml/.project +++ /dev/null @@ -1,43 +0,0 @@ - - - spring-mvc-xml - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-mvc-xml/.settings/.jsdtscope b/spring-mvc-xml/.settings/.jsdtscope deleted file mode 100644 index b46b9207a8..0000000000 --- a/spring-mvc-xml/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-mvc-xml/.settings/org.eclipse.jdt.core.prefs b/spring-mvc-xml/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 5ff04b9f96..0000000000 --- a/spring-mvc-xml/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,91 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-mvc-xml/.settings/org.eclipse.jdt.ui.prefs b/spring-mvc-xml/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-mvc-xml/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-mvc-xml/.settings/org.eclipse.m2e.core.prefs b/spring-mvc-xml/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-mvc-xml/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-mvc-xml/.settings/org.eclipse.m2e.wtp.prefs b/spring-mvc-xml/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-mvc-xml/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-mvc-xml/.settings/org.eclipse.wst.common.component b/spring-mvc-xml/.settings/org.eclipse.wst.common.component deleted file mode 100644 index fc995759ac..0000000000 --- a/spring-mvc-xml/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-mvc-xml/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-mvc-xml/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 9ca0d1c1b7..0000000000 --- a/spring-mvc-xml/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/spring-mvc-xml/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-mvc-xml/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-mvc-xml/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-mvc-xml/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-mvc-xml/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-mvc-xml/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-mvc-xml/.settings/org.eclipse.wst.validation.prefs b/spring-mvc-xml/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-mvc-xml/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-mvc-xml/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-mvc-xml/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-mvc-xml/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-mvc-xml/.springBeans b/spring-mvc-xml/.springBeans deleted file mode 100644 index 7623a7e888..0000000000 --- a/spring-mvc-xml/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/spring-mvc-xml/README.md b/spring-mvc-xml/README.md index 908e21d4bf..ce823a9682 100644 --- a/spring-mvc-xml/README.md +++ b/spring-mvc-xml/README.md @@ -1,5 +1,8 @@ ========= +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + ## Spring MVC with XML Configuration Example Project - access a sample jsp page at: `http://localhost:8080/spring-mvc-xml/sample.html` @@ -7,3 +10,4 @@ ### Relevant Articles: - [Spring MVC Tutorial](http://www.baeldung.com/spring-mvc-tutorial) - [Servlet Session Timeout](http://www.baeldung.com/servlet-session-timeout) +- [Basic Forms with Spring MVC](http://www.baeldung.com/spring-mvc-form-tutorial) diff --git a/spring-mvc-xml/pom.xml b/spring-mvc-xml/pom.xml index 896d744e99..9c65ccdadd 100644 --- a/spring-mvc-xml/pom.xml +++ b/spring-mvc-xml/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung 0.1-SNAPSHOT spring-mvc-xml @@ -98,6 +98,24 @@ test + + + com.fasterxml.jackson.core + jackson-core + 2.7.2 + + + com.fasterxml.jackson.core + jackson-databind + 2.7.2 + + + + + commons-io + commons-io + 2.2 + @@ -146,7 +164,7 @@ - 4.2.4.RELEASE + 4.2.5.RELEASE 1.7.13 @@ -160,14 +178,14 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java new file mode 100644 index 0000000000..76351b96f7 --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java @@ -0,0 +1,17 @@ +package com.baeldung.spring; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@ImportResource("classpath:webMvcConfig.xml") +@Configuration +public class ClientWebConfig extends WebMvcConfigurerAdapter { + + public ClientWebConfig() { + super(); + } + + // API + +} \ No newline at end of file diff --git a/spring-mvc-xml/src/main/java/org/baeldung/spring/ClientWebConfigJava.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java similarity index 98% rename from spring-mvc-xml/src/main/java/org/baeldung/spring/ClientWebConfigJava.java rename to spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java index c82201880f..bee09b742a 100644 --- a/spring-mvc-xml/src/main/java/org/baeldung/spring/ClientWebConfigJava.java +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java @@ -1,4 +1,4 @@ -package org.baeldung.spring; +package com.baeldung.spring; import java.util.Locale; import java.util.ResourceBundle; diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/EmployeeController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/EmployeeController.java new file mode 100644 index 0000000000..aa25f47a2a --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/EmployeeController.java @@ -0,0 +1,45 @@ +package com.baeldung.spring.controller; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +import com.baeldung.spring.form.Employee; + +@Controller +public class EmployeeController { + + Map employeeMap = new HashMap<>(); + + @RequestMapping(value = "/employee", method = RequestMethod.GET) + public ModelAndView showForm() { + return new ModelAndView("employeeHome", "employee", new Employee()); + } + + @RequestMapping(value = "/employee/{Id}", produces = { "application/json", "application/xml" }, method = RequestMethod.GET) + public @ResponseBody Employee getEmployeeById(@PathVariable final long Id) { + return employeeMap.get(Id); + } + + @RequestMapping(value = "/addEmployee", method = RequestMethod.POST) + public String submit(@ModelAttribute("employee") final Employee employee, final BindingResult result, final ModelMap model) { + if (result.hasErrors()) { + return "error"; + } + model.addAttribute("name", employee.getName()); + model.addAttribute("contactNumber", employee.getContactNumber()); + model.addAttribute("id", employee.getId()); + employeeMap.put(employee.getId(), employee); + return "employeeView"; + } + +} diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloController.java new file mode 100644 index 0000000000..cc9d66d4d4 --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloController.java @@ -0,0 +1,19 @@ +package com.baeldung.spring.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +public class HelloController extends AbstractController { + + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { + ModelAndView model = new ModelAndView("helloworld"); + model.addObject("msg", "Welcome to Baeldung's Spring Handler Mappings Guide.
    This request was mapped" + + " using SimpleUrlHandlerMapping."); + + return model; + } +} diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloGuestController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloGuestController.java new file mode 100644 index 0000000000..614888ae42 --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloGuestController.java @@ -0,0 +1,18 @@ +package com.baeldung.spring.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +public class HelloGuestController extends AbstractController { + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { + ModelAndView model = new ModelAndView("helloworld"); + model.addObject("msg", "Welcome to Baeldung's Spring Handler Mappings Guide.
    This request was mapped" + + " using ControllerClassNameHandlerMapping."); + + return model; + } +} diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloWorldController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloWorldController.java new file mode 100644 index 0000000000..6ed3d06ab7 --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloWorldController.java @@ -0,0 +1,18 @@ +package com.baeldung.spring.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +public class HelloWorldController extends AbstractController { + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { + ModelAndView model = new ModelAndView("helloworld"); + model.addObject("msg", "Welcome to Baeldung's Spring Handler Mappings Guide.
    This request was mapped" + + " using BeanNameUrlHandlerMapping."); + + return model; + } +} diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ImageController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ImageController.java new file mode 100644 index 0000000000..ef8d1214df --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ImageController.java @@ -0,0 +1,62 @@ +package com.baeldung.spring.controller; + +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.http.*; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.context.support.ServletContextResource; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletResponse; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +@Controller +public class ImageController { + + @Autowired + private ServletContext servletContext; + + @RequestMapping(value = "/image-view", method = RequestMethod.GET) + public String imageView() throws IOException { + return "image-download"; + } + + @RequestMapping(value = "/image-manual-response", method = RequestMethod.GET) + public void getImageAsByteArray(HttpServletResponse response) throws IOException { + final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); + response.setContentType(MediaType.IMAGE_JPEG_VALUE); + IOUtils.copy(in, response.getOutputStream()); + } + + @RequestMapping(value = "/image-byte-array", method = RequestMethod.GET) + @ResponseBody + public byte[] getImageAsByteArray() throws IOException { + final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); + return IOUtils.toByteArray(in); + } + + @RequestMapping(value = "/image-response-entity", method = RequestMethod.GET) + public ResponseEntity getImageAsResponseEntity() throws IOException { + ResponseEntity responseEntity; + final HttpHeaders headers = new HttpHeaders(); + final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); + byte[] media = IOUtils.toByteArray(in); + headers.setCacheControl(CacheControl.noCache().getHeaderValue()); + responseEntity = new ResponseEntity<>(media, headers, HttpStatus.OK); + return responseEntity; + } + + @RequestMapping(value = "/image-resource", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity getImageAsResource() { + final HttpHeaders headers = new HttpHeaders(); + Resource resource = new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg"); + return new ResponseEntity<>(resource, headers, HttpStatus.OK); + } +} diff --git a/spring-mvc-xml/src/main/java/org/baeldung/spring/controller/PersonController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/PersonController.java similarity index 94% rename from spring-mvc-xml/src/main/java/org/baeldung/spring/controller/PersonController.java rename to spring-mvc-xml/src/main/java/com/baeldung/spring/controller/PersonController.java index 0d89a29b9d..39dabf86ed 100644 --- a/spring-mvc-xml/src/main/java/org/baeldung/spring/controller/PersonController.java +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/PersonController.java @@ -1,4 +1,4 @@ -package org.baeldung.spring.controller; +package com.baeldung.spring.controller; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -7,8 +7,8 @@ import java.util.Map; import javax.validation.Valid; -import org.baeldung.spring.form.Person; -import org.baeldung.spring.validator.PersonValidator; +import com.baeldung.spring.form.Person; +import com.baeldung.spring.validator.PersonValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/WelcomeController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/WelcomeController.java new file mode 100644 index 0000000000..5459481674 --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/WelcomeController.java @@ -0,0 +1,19 @@ +package com.baeldung.spring.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +public class WelcomeController extends AbstractController { + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { + + ModelAndView model = new ModelAndView("welcome"); + model.addObject("msg", " Baeldung's Spring Handler Mappings Guide.
    This request was mapped" + + " using SimpleUrlHandlerMapping."); + + return model; + } +} \ No newline at end of file diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Employee.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Employee.java new file mode 100644 index 0000000000..66b2e9f185 --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Employee.java @@ -0,0 +1,49 @@ +package com.baeldung.spring.form; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class Employee { + + private long id; + + @NotNull + @Size(min = 1) + private String name; + @NotNull + @Size(min = 1) + private String contactNumber; + + public Employee() { + super(); + } + + // + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getContactNumber() { + return contactNumber; + } + + public void setContactNumber(final String contactNumber) { + this.contactNumber = contactNumber; + } + +} diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java new file mode 100644 index 0000000000..88e4f9ff4c --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java @@ -0,0 +1,152 @@ +package com.baeldung.spring.form; + +import java.util.List; + +import org.hibernate.validator.constraints.NotEmpty; +import org.springframework.web.multipart.MultipartFile; + +public class Person { + + private long id; + + private String name; + private String email; + private String dateOfBirth; + + @NotEmpty + private String password; + private String sex; + private String country; + private String book; + private String job; + private boolean receiveNewsletter; + private String[] hobbies; + private List favouriteLanguage; + private List fruit; + private String notes; + private MultipartFile file; + + public Person() { + super(); + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(final String email) { + this.email = email; + } + + public String getDateOfBirth() { + return dateOfBirth; + } + + public void setDateOfBirth(final String dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } + + public String getPassword() { + return password; + } + + public void setPassword(final String password) { + this.password = password; + } + + public String getSex() { + return sex; + } + + public void setSex(final String sex) { + this.sex = sex; + } + + public String getCountry() { + return country; + } + + public void setCountry(final String country) { + this.country = country; + } + + public String getJob() { + return job; + } + + public void setJob(final String job) { + this.job = job; + } + + public boolean isReceiveNewsletter() { + return receiveNewsletter; + } + + public void setReceiveNewsletter(final boolean receiveNewsletter) { + this.receiveNewsletter = receiveNewsletter; + } + + public String[] getHobbies() { + return hobbies; + } + + public void setHobbies(final String[] hobbies) { + this.hobbies = hobbies; + } + + public List getFavouriteLanguage() { + return favouriteLanguage; + } + + public void setFavouriteLanguage(final List favouriteLanguage) { + this.favouriteLanguage = favouriteLanguage; + } + + public String getNotes() { + return notes; + } + + public void setNotes(final String notes) { + this.notes = notes; + } + + public List getFruit() { + return fruit; + } + + public void setFruit(final List fruit) { + this.fruit = fruit; + } + + public String getBook() { + return book; + } + + public void setBook(final String book) { + this.book = book; + } + + public MultipartFile getFile() { + return file; + } + + public void setFile(final MultipartFile file) { + this.file = file; + } +} diff --git a/spring-mvc-xml/src/main/java/org/baeldung/spring/validator/PersonValidator.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java similarity index 83% rename from spring-mvc-xml/src/main/java/org/baeldung/spring/validator/PersonValidator.java rename to spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java index 068a9fee7f..3a271f6545 100644 --- a/spring-mvc-xml/src/main/java/org/baeldung/spring/validator/PersonValidator.java +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java @@ -1,6 +1,6 @@ -package org.baeldung.spring.validator; +package com.baeldung.spring.validator; -import org.baeldung.spring.form.Person; +import com.baeldung.spring.form.Person; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; diff --git a/spring-mvc-xml/src/main/java/org/baeldung/spring/ClientWebConfig.java b/spring-mvc-xml/src/main/java/org/baeldung/spring/ClientWebConfig.java deleted file mode 100644 index 9705d51606..0000000000 --- a/spring-mvc-xml/src/main/java/org/baeldung/spring/ClientWebConfig.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.baeldung.spring; - -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; - -@ImportResource("classpath:webMvcConfig.xml") -@Configuration -public class ClientWebConfig extends WebMvcConfigurerAdapter { - - public ClientWebConfig() { - super(); - } - - // API - -} \ No newline at end of file diff --git a/spring-mvc-xml/src/main/java/org/baeldung/spring/controller/EmployeeController.java b/spring-mvc-xml/src/main/java/org/baeldung/spring/controller/EmployeeController.java deleted file mode 100644 index 1dbe230adc..0000000000 --- a/spring-mvc-xml/src/main/java/org/baeldung/spring/controller/EmployeeController.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.baeldung.spring.controller; - -import javax.validation.Valid; - -import org.baeldung.spring.form.Employee; -import org.springframework.stereotype.Controller; -import org.springframework.ui.ModelMap; -import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.servlet.ModelAndView; - -@Controller -public class EmployeeController { - - @RequestMapping(value = "/employee", method = RequestMethod.GET) - public ModelAndView showForm() { - return new ModelAndView("employeeHome", "employee", new Employee()); - } - - @RequestMapping(value = "/addEmployee", method = RequestMethod.POST) - public String submit(@Valid @ModelAttribute("employee") final Employee employee, final BindingResult result, final ModelMap model) { - if (result.hasErrors()) { - return "error"; - } - - model.addAttribute("name", employee.getName()); - model.addAttribute("contactNumber", employee.getContactNumber()); - model.addAttribute("id", employee.getId()); - return "employeeView"; - } - -} diff --git a/spring-mvc-xml/src/main/java/org/baeldung/spring/form/Employee.java b/spring-mvc-xml/src/main/java/org/baeldung/spring/form/Employee.java deleted file mode 100644 index 70132b9665..0000000000 --- a/spring-mvc-xml/src/main/java/org/baeldung/spring/form/Employee.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.baeldung.spring.form; - -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -public class Employee { - - private long id; - - @NotNull - @Size(min = 1) - private String name; - @NotNull - @Size(min = 1) - private String contactNumber; - - public Employee() { - super(); - } - - // - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - public long getId() { - return id; - } - - public void setId(final long id) { - this.id = id; - } - - public String getContactNumber() { - return contactNumber; - } - - public void setContactNumber(final String contactNumber) { - this.contactNumber = contactNumber; - } - -} diff --git a/spring-mvc-xml/src/main/java/org/baeldung/spring/form/Person.java b/spring-mvc-xml/src/main/java/org/baeldung/spring/form/Person.java deleted file mode 100644 index bf313b4d7d..0000000000 --- a/spring-mvc-xml/src/main/java/org/baeldung/spring/form/Person.java +++ /dev/null @@ -1,152 +0,0 @@ -package org.baeldung.spring.form; - -import java.util.List; - -import org.hibernate.validator.constraints.NotEmpty; -import org.springframework.web.multipart.MultipartFile; - -public class Person { - - private long id; - - private String name; - private String email; - private String dateOfBirth; - - @NotEmpty - private String password; - private String sex; - private String country; - private String book; - private String job; - private boolean receiveNewsletter; - private String[] hobbies; - private List favouriteLanguage; - private List fruit; - private String notes; - private MultipartFile file; - - public Person() { - super(); - } - - public long getId() { - return id; - } - - public void setId(final long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(final String email) { - this.email = email; - } - - public String getDateOfBirth() { - return dateOfBirth; - } - - public void setDateOfBirth(final String dateOfBirth) { - this.dateOfBirth = dateOfBirth; - } - - public String getPassword() { - return password; - } - - public void setPassword(final String password) { - this.password = password; - } - - public String getSex() { - return sex; - } - - public void setSex(final String sex) { - this.sex = sex; - } - - public String getCountry() { - return country; - } - - public void setCountry(final String country) { - this.country = country; - } - - public String getJob() { - return job; - } - - public void setJob(final String job) { - this.job = job; - } - - public boolean isReceiveNewsletter() { - return receiveNewsletter; - } - - public void setReceiveNewsletter(final boolean receiveNewsletter) { - this.receiveNewsletter = receiveNewsletter; - } - - public String[] getHobbies() { - return hobbies; - } - - public void setHobbies(final String[] hobbies) { - this.hobbies = hobbies; - } - - public List getFavouriteLanguage() { - return favouriteLanguage; - } - - public void setFavouriteLanguage(final List favouriteLanguage) { - this.favouriteLanguage = favouriteLanguage; - } - - public String getNotes() { - return notes; - } - - public void setNotes(final String notes) { - this.notes = notes; - } - - public List getFruit() { - return fruit; - } - - public void setFruit(final List fruit) { - this.fruit = fruit; - } - - public String getBook() { - return book; - } - - public void setBook(final String book) { - this.book = book; - } - - public MultipartFile getFile() { - return file; - } - - public void setFile(final MultipartFile file) { - this.file = file; - } -} diff --git a/spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml b/spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml new file mode 100644 index 0000000000..e68c88d19d --- /dev/null +++ b/spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-mvc-xml/src/main/resources/webMvcConfig.xml b/spring-mvc-xml/src/main/resources/webMvcConfig.xml index f127cfd637..c471adf331 100644 --- a/spring-mvc-xml/src/main/resources/webMvcConfig.xml +++ b/spring-mvc-xml/src/main/resources/webMvcConfig.xml @@ -5,14 +5,25 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-4.2.xsd + http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd" > - + + + + + + image/jpeg + image/png + + + + + - + @@ -21,8 +32,7 @@ - - - - - \ No newline at end of file + + + + diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/images/image-example.jpg b/spring-mvc-xml/src/main/webapp/WEB-INF/images/image-example.jpg new file mode 100644 index 0000000000..219abe530f Binary files /dev/null and b/spring-mvc-xml/src/main/webapp/WEB-INF/images/image-example.jpg differ diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-mvc-xml/src/main/webapp/WEB-INF/mvc-servlet.xml index 4ba9642448..47e2769902 100644 --- a/spring-mvc-xml/src/main/webapp/WEB-INF/mvc-servlet.xml +++ b/spring-mvc-xml/src/main/webapp/WEB-INF/mvc-servlet.xml @@ -1,6 +1,61 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd + http://www.springframework.org/schema/mvc + http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> + + + + + + + + + + + + + + + + + + + + + + welcomeController + welcomeController + helloController + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/hello.jsp b/spring-mvc-xml/src/main/webapp/WEB-INF/view/hello.jsp new file mode 100644 index 0000000000..2acdae9b0f --- /dev/null +++ b/spring-mvc-xml/src/main/webapp/WEB-INF/view/hello.jsp @@ -0,0 +1,15 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Hello World + + +

    Hello ${msg}

    +
    +

    + Go to spring handler mappings homepage + + \ No newline at end of file diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/helloworld.jsp b/spring-mvc-xml/src/main/webapp/WEB-INF/view/helloworld.jsp new file mode 100644 index 0000000000..2eeabbe0ac --- /dev/null +++ b/spring-mvc-xml/src/main/webapp/WEB-INF/view/helloworld.jsp @@ -0,0 +1,15 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Hello World + + +

    Hello World ${msg}

    +
    +

    + Go to spring handler mappings homepage + + \ No newline at end of file diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/image-download.jsp b/spring-mvc-xml/src/main/webapp/WEB-INF/view/image-download.jsp new file mode 100644 index 0000000000..3a4da24bcb --- /dev/null +++ b/spring-mvc-xml/src/main/webapp/WEB-INF/view/image-download.jsp @@ -0,0 +1,18 @@ + +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Image download examples + + +

    Image download examples

    + + + diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/personForm.jsp b/spring-mvc-xml/src/main/webapp/WEB-INF/view/personForm.jsp index 2836c11668..535348b7d2 100644 --- a/spring-mvc-xml/src/main/webapp/WEB-INF/view/personForm.jsp +++ b/spring-mvc-xml/src/main/webapp/WEB-INF/view/personForm.jsp @@ -117,4 +117,4 @@ - \ No newline at end of file + diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/personView.jsp b/spring-mvc-xml/src/main/webapp/WEB-INF/view/personView.jsp index bd14474dfe..1f9ba86c69 100644 --- a/spring-mvc-xml/src/main/webapp/WEB-INF/view/personView.jsp +++ b/spring-mvc-xml/src/main/webapp/WEB-INF/view/personView.jsp @@ -62,4 +62,4 @@ - \ No newline at end of file + diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/welcome.jsp b/spring-mvc-xml/src/main/webapp/WEB-INF/view/welcome.jsp new file mode 100644 index 0000000000..348ca652ff --- /dev/null +++ b/spring-mvc-xml/src/main/webapp/WEB-INF/view/welcome.jsp @@ -0,0 +1,15 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Welcome Page + + +

    Welcome to ${msg}

    +
    +

    + Go to spring handler mappings homepage + + \ No newline at end of file diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/web.xml b/spring-mvc-xml/src/main/webapp/WEB-INF/web.xml index 5275efdf24..29608a17ef 100644 --- a/spring-mvc-xml/src/main/webapp/WEB-INF/web.xml +++ b/spring-mvc-xml/src/main/webapp/WEB-INF/web.xml @@ -16,7 +16,7 @@ contextConfigLocation - org.baeldung.spring + com.baeldung.spring diff --git a/spring-mvc-xml/src/main/webapp/index.jsp b/spring-mvc-xml/src/main/webapp/index.jsp index 1ecfcec9d7..149fc5fe0b 100644 --- a/spring-mvc-xml/src/main/webapp/index.jsp +++ b/spring-mvc-xml/src/main/webapp/index.jsp @@ -12,6 +12,8 @@

    Spring MVC Examples

    diff --git a/spring-mvc-xml/src/main/webapp/spring-handler-index.jsp b/spring-mvc-xml/src/main/webapp/spring-handler-index.jsp new file mode 100644 index 0000000000..0fdd51d1ec --- /dev/null +++ b/spring-mvc-xml/src/main/webapp/spring-handler-index.jsp @@ -0,0 +1,18 @@ + + + + + Welcome + + +

    Spring Handler Mapping Examples

    +

    Click each link below to see how the request is mapped using the specified mapping: +

    +
      +
    1. BeanNameUrlHandlerMapping - Mapping by bean name
    2. +
    3. SimpleUrlHandlerMapping
    4. +
    5. ControllerClassNameHandlerMapping - Mapping by controller name
    6. +
    +Home + + \ No newline at end of file diff --git a/spring-openid/README.md b/spring-openid/README.md new file mode 100644 index 0000000000..c5989217f4 --- /dev/null +++ b/spring-openid/README.md @@ -0,0 +1,17 @@ +========= + +## OpenID Connect with Spring Security + + +### Build the Project +``` +mvn clean install +``` + + +### Obtain Google App - Client ID, Secret +- You need to get client id and client secret from [Google Developer Console](https://console.developers.google.com/project/_/apiui/credential?pli=1) +- Make sure to add OAuth2 credentials by selecting Add credentials > OAuth 2.0 client ID +- Make sure you set redirect URI to http://localhost:8081/google-login + +- Once you have your client id and secret, make sure you add them to the `application.properties` of the project diff --git a/spring-openid/pom.xml b/spring-openid/pom.xml new file mode 100644 index 0000000000..39cf3e9d4e --- /dev/null +++ b/spring-openid/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + com.baeldung + spring-openid + 0.0.1-SNAPSHOT + war + + spring-openid + Spring OpenID sample project + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.springframework.security.oauth + spring-security-oauth2 + + + + org.springframework.security + spring-security-jwt + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + + + diff --git a/spring-openid/src/main/java/org/baeldung/config/GoogleOpenIdConnectConfig.java b/spring-openid/src/main/java/org/baeldung/config/GoogleOpenIdConnectConfig.java new file mode 100644 index 0000000000..8e9c6e974e --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/config/GoogleOpenIdConnectConfig.java @@ -0,0 +1,51 @@ +package org.baeldung.config; + +import java.util.Arrays; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.OAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; + +@Configuration +@EnableOAuth2Client +public class GoogleOpenIdConnectConfig { + @Value("${google.clientId}") + private String clientId; + + @Value("${google.clientSecret}") + private String clientSecret; + + @Value("${google.accessTokenUri}") + private String accessTokenUri; + + @Value("${google.userAuthorizationUri}") + private String userAuthorizationUri; + + @Value("${google.redirectUri}") + private String redirectUri; + + @Bean + public OAuth2ProtectedResourceDetails googleOpenId() { + final AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); + details.setClientId(clientId); + details.setClientSecret(clientSecret); + details.setAccessTokenUri(accessTokenUri); + details.setUserAuthorizationUri(userAuthorizationUri); + details.setScope(Arrays.asList("openid", "email")); + details.setPreEstablishedRedirectUri(redirectUri); + details.setUseCurrentUri(false); + return details; + } + + @Bean + public OAuth2RestTemplate googleOpenIdTemplate(final OAuth2ClientContext clientContext) { + final OAuth2RestTemplate template = new OAuth2RestTemplate(googleOpenId(), clientContext); + return template; + } + +} diff --git a/spring-openid/src/main/java/org/baeldung/config/HomeController.java b/spring-openid/src/main/java/org/baeldung/config/HomeController.java new file mode 100644 index 0000000000..f0a5378019 --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/config/HomeController.java @@ -0,0 +1,22 @@ +package org.baeldung.config; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class HomeController { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @RequestMapping("/") + @ResponseBody + public final String home() { + final String username = SecurityContextHolder.getContext().getAuthentication().getName(); + logger.info(username); + return "Welcome, " + username; + } + +} diff --git a/spring-openid/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-openid/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..d929bfd631 --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,49 @@ +package org.baeldung.config; + +import org.baeldung.security.OpenIdConnectFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; +import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + @Autowired + private OAuth2RestTemplate restTemplate; + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Bean + public OpenIdConnectFilter myFilter() { + final OpenIdConnectFilter filter = new OpenIdConnectFilter("/google-login"); + filter.setRestTemplate(restTemplate); + return filter; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .addFilterAfter(new OAuth2ClientContextFilter(), AbstractPreAuthenticatedProcessingFilter.class) + .addFilterAfter(myFilter(), OAuth2ClientContextFilter.class) + .httpBasic().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/google-login")) + .and() + .authorizeRequests() + // .antMatchers("/","/index*").permitAll() + .anyRequest().authenticated() + ; + + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-openid/src/main/java/org/baeldung/config/SpringOpenidApplication.java b/spring-openid/src/main/java/org/baeldung/config/SpringOpenidApplication.java new file mode 100644 index 0000000000..608e8a6819 --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/config/SpringOpenidApplication.java @@ -0,0 +1,13 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringOpenidApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringOpenidApplication.class, args); + } + +} diff --git a/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectFilter.java b/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectFilter.java new file mode 100644 index 0000000000..c0970ab3cf --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectFilter.java @@ -0,0 +1,71 @@ +package org.baeldung.security; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.jwt.Jwt; +import org.springframework.security.jwt.JwtHelper; +import org.springframework.security.oauth2.client.OAuth2RestOperations; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class OpenIdConnectFilter extends AbstractAuthenticationProcessingFilter { + public OAuth2RestOperations restTemplate; + + public OpenIdConnectFilter(String defaultFilterProcessesUrl) { + super(defaultFilterProcessesUrl); + setAuthenticationManager(new NoopAuthenticationManager()); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + + OAuth2AccessToken accessToken; + try { + accessToken = restTemplate.getAccessToken(); + } catch (final OAuth2Exception e) { + throw new BadCredentialsException("Could not obtain access token", e); + } + try { + final String idToken = accessToken.getAdditionalInformation().get("id_token").toString(); + final Jwt tokenDecoded = JwtHelper.decode(idToken); + System.out.println("===== : " + tokenDecoded.getClaims()); + + final Map authInfo = new ObjectMapper().readValue(tokenDecoded.getClaims(), Map.class); + + final OpenIdConnectUserDetails user = new OpenIdConnectUserDetails(authInfo, accessToken); + return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); + } catch (final InvalidTokenException e) { + throw new BadCredentialsException("Could not obtain user details from token", e); + } + + } + + public void setRestTemplate(OAuth2RestTemplate restTemplate2) { + restTemplate = restTemplate2; + + } + + private static class NoopAuthenticationManager implements AuthenticationManager { + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + throw new UnsupportedOperationException("No authentication should be done with this AuthenticationManager"); + } + + } +} diff --git a/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectUserDetails.java b/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectUserDetails.java new file mode 100644 index 0000000000..f0d91fdc27 --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectUserDetails.java @@ -0,0 +1,81 @@ +package org.baeldung.security; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; + +public class OpenIdConnectUserDetails implements UserDetails { + + private static final long serialVersionUID = 1L; + + private String userId; + private String username; + private OAuth2AccessToken token; + + public OpenIdConnectUserDetails(Map userInfo, OAuth2AccessToken token) { + this.userId = userInfo.get("sub"); + this.username = userInfo.get("email"); + this.token = token; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public Collection getAuthorities() { + return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public OAuth2AccessToken getToken() { + return token; + } + + public void setToken(OAuth2AccessToken token) { + this.token = token; + } + + public void setUsername(String username) { + this.username = username; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + +} diff --git a/spring-openid/src/main/resources/application.properties.sample.properties b/spring-openid/src/main/resources/application.properties.sample.properties new file mode 100644 index 0000000000..3b4f7716f0 --- /dev/null +++ b/spring-openid/src/main/resources/application.properties.sample.properties @@ -0,0 +1,6 @@ +server.port=8081 +google.clientId=TODO +google.clientSecret=TODO +google.accessTokenUri=https://www.googleapis.com/oauth2/v3/token +google.userAuthorizationUri=https://accounts.google.com/o/oauth2/auth +google.redirectUri=http://localhost:8081/google-login \ No newline at end of file diff --git a/spring-protobuf/pom.xml b/spring-protobuf/pom.xml new file mode 100644 index 0000000000..1275d72edf --- /dev/null +++ b/spring-protobuf/pom.xml @@ -0,0 +1,58 @@ + + 4.0.0 + com.baeldung + spring-protobuf + 0.1-SNAPSHOT + spring-protobuf + + + org.springframework.boot + spring-boot-starter-parent + 1.2.4.RELEASE + + + + + com.google.protobuf + protobuf-java + 3.0.0-beta-3 + + + com.googlecode.protobuf-java-format + protobuf-java-format + 1.4 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.apache.httpcomponents + httpclient + 4.5.2 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + diff --git a/spring-protobuf/src/main/java/com/baeldung/protobuf/Application.java b/spring-protobuf/src/main/java/com/baeldung/protobuf/Application.java new file mode 100644 index 0000000000..76f0e45244 --- /dev/null +++ b/spring-protobuf/src/main/java/com/baeldung/protobuf/Application.java @@ -0,0 +1,66 @@ +package com.baeldung.protobuf; + +import com.baeldung.protobuf.BaeldungTraining.Course; +import com.baeldung.protobuf.BaeldungTraining.Student; +import com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber; +import com.baeldung.protobuf.BaeldungTraining.Student.PhoneType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@SpringBootApplication +public class Application { + + @Bean + RestTemplate restTemplate(ProtobufHttpMessageConverter hmc) { + return new RestTemplate(Arrays.asList(hmc)); + } + + @Bean + ProtobufHttpMessageConverter protobufHttpMessageConverter() { + return new ProtobufHttpMessageConverter(); + } + + @Bean + public CourseRepository createTestCourses() { + Map courses = new HashMap<>(); + + Course course1 = Course.newBuilder().setId(1).setCourseName("REST with Spring").addAllStudent(createTestStudents()).build(); + + Course course2 = Course.newBuilder().setId(2).setCourseName("Learn Spring Security").addAllStudent(new ArrayList<>()).build(); + + courses.put(course1.getId(), course1); + courses.put(course2.getId(), course2); + + return new CourseRepository(courses); + } + + private List createTestStudents() { + PhoneNumber phone1 = createPhone("123456", PhoneType.MOBILE); + Student student1 = createStudent(1, "John", "Doe", "john.doe@baeldung.com", Arrays.asList(phone1)); + + PhoneNumber phone2 = createPhone("234567", PhoneType.LANDLINE); + Student student2 = createStudent(2, "Richard", "Roe", "richard.roe@baeldung.com", Arrays.asList(phone2)); + + PhoneNumber phone3_1 = createPhone("345678", PhoneType.MOBILE); + PhoneNumber phone3_2 = createPhone("456789", PhoneType.LANDLINE); + Student student3 = createStudent(3, "Jane", "Doe", "jane.doe@baeldung.com", Arrays.asList(phone3_1, phone3_2)); + + return Arrays.asList(student1, student2, student3); + } + + private Student createStudent(int id, String firstName, String lastName, String email, List phones) { + return Student.newBuilder().setId(id).setFirstName(firstName).setLastName(lastName).setEmail(email).addAllPhone(phones).build(); + } + + private PhoneNumber createPhone(String number, PhoneType type) { + return PhoneNumber.newBuilder().setNumber(number).setType(type).build(); + } +} \ No newline at end of file diff --git a/spring-protobuf/src/main/java/com/baeldung/protobuf/BaeldungTraining.java b/spring-protobuf/src/main/java/com/baeldung/protobuf/BaeldungTraining.java new file mode 100644 index 0000000000..5cab2ae908 --- /dev/null +++ b/spring-protobuf/src/main/java/com/baeldung/protobuf/BaeldungTraining.java @@ -0,0 +1,2589 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: resources/baeldung.proto + +package com.baeldung.protobuf; + +public final class BaeldungTraining { + private BaeldungTraining() { + } + + public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry) { + } + + public interface CourseOrBuilder extends + // @@protoc_insertion_point(interface_extends:baeldung.Course) + com.google.protobuf.MessageOrBuilder { + + /** + * optional int32 id = 1; + */ + int getId(); + + /** + * optional string course_name = 2; + */ + java.lang.String getCourseName(); + + /** + * optional string course_name = 2; + */ + com.google.protobuf.ByteString getCourseNameBytes(); + + /** + * repeated .baeldung.Student student = 3; + */ + java.util.List getStudentList(); + + /** + * repeated .baeldung.Student student = 3; + */ + com.baeldung.protobuf.BaeldungTraining.Student getStudent(int index); + + /** + * repeated .baeldung.Student student = 3; + */ + int getStudentCount(); + + /** + * repeated .baeldung.Student student = 3; + */ + java.util.List getStudentOrBuilderList(); + + /** + * repeated .baeldung.Student student = 3; + */ + com.baeldung.protobuf.BaeldungTraining.StudentOrBuilder getStudentOrBuilder(int index); + } + + /** + * Protobuf type {@code baeldung.Course} + */ + public static final class Course extends com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:baeldung.Course) + CourseOrBuilder { + // Use Course.newBuilder() to construct. + private Course(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + + private Course() { + id_ = 0; + courseName_ = ""; + student_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + + private Course(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 8: { + + id_ = input.readInt32(); + break; + } + case 18: { + java.lang.String s = input.readStringRequireUtf8(); + + courseName_ = s; + break; + } + case 26: { + if (!((mutable_bitField0_ & 0x00000004) == 0x00000004)) { + student_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000004; + } + student_.add(input.readMessage(com.baeldung.protobuf.BaeldungTraining.Student.parser(), extensionRegistry)); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000004) == 0x00000004)) { + student_ = java.util.Collections.unmodifiableList(student_); + } + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Course_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Course_fieldAccessorTable.ensureFieldAccessorsInitialized(com.baeldung.protobuf.BaeldungTraining.Course.class, com.baeldung.protobuf.BaeldungTraining.Course.Builder.class); + } + + private int bitField0_; + public static final int ID_FIELD_NUMBER = 1; + private int id_; + + /** + * optional int32 id = 1; + */ + public int getId() { + return id_; + } + + public static final int COURSE_NAME_FIELD_NUMBER = 2; + private volatile java.lang.Object courseName_; + + /** + * optional string course_name = 2; + */ + public java.lang.String getCourseName() { + java.lang.Object ref = courseName_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + courseName_ = s; + return s; + } + } + + /** + * optional string course_name = 2; + */ + public com.google.protobuf.ByteString getCourseNameBytes() { + java.lang.Object ref = courseName_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + courseName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int STUDENT_FIELD_NUMBER = 3; + private java.util.List student_; + + /** + * repeated .baeldung.Student student = 3; + */ + public java.util.List getStudentList() { + return student_; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public java.util.List getStudentOrBuilderList() { + return student_; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public int getStudentCount() { + return student_.size(); + } + + /** + * repeated .baeldung.Student student = 3; + */ + public com.baeldung.protobuf.BaeldungTraining.Student getStudent(int index) { + return student_.get(index); + } + + /** + * repeated .baeldung.Student student = 3; + */ + public com.baeldung.protobuf.BaeldungTraining.StudentOrBuilder getStudentOrBuilder(int index) { + return student_.get(index); + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) + return true; + if (isInitialized == 0) + return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (id_ != 0) { + output.writeInt32(1, id_); + } + if (!getCourseNameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, courseName_); + } + for (int i = 0; i < student_.size(); i++) { + output.writeMessage(3, student_.get(i)); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) + return size; + + size = 0; + if (id_ != 0) { + size += com.google.protobuf.CodedOutputStream.computeInt32Size(1, id_); + } + if (!getCourseNameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, courseName_); + } + for (int i = 0; i < student_.size(); i++) { + size += com.google.protobuf.CodedOutputStream.computeMessageSize(3, student_.get(i)); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + + public static com.baeldung.protobuf.BaeldungTraining.Course parseFrom(com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.baeldung.protobuf.BaeldungTraining.Course parseFrom(com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Course parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.baeldung.protobuf.BaeldungTraining.Course parseFrom(byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Course parseFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input); + } + + public static com.baeldung.protobuf.BaeldungTraining.Course parseFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Course parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input); + } + + public static com.baeldung.protobuf.BaeldungTraining.Course parseDelimitedFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Course parseFrom(com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input); + } + + public static com.baeldung.protobuf.BaeldungTraining.Course parseFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(com.baeldung.protobuf.BaeldungTraining.Course prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + + /** + * Protobuf type {@code baeldung.Course} + */ + public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:baeldung.Course) + com.baeldung.protobuf.BaeldungTraining.CourseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Course_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Course_fieldAccessorTable.ensureFieldAccessorsInitialized(com.baeldung.protobuf.BaeldungTraining.Course.class, com.baeldung.protobuf.BaeldungTraining.Course.Builder.class); + } + + // Construct using com.baeldung.protobuf.BaeldungTraining.Course.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + getStudentFieldBuilder(); + } + } + + public Builder clear() { + super.clear(); + id_ = 0; + + courseName_ = ""; + + if (studentBuilder_ == null) { + student_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); + } else { + studentBuilder_.clear(); + } + return this; + } + + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Course_descriptor; + } + + public com.baeldung.protobuf.BaeldungTraining.Course getDefaultInstanceForType() { + return com.baeldung.protobuf.BaeldungTraining.Course.getDefaultInstance(); + } + + public com.baeldung.protobuf.BaeldungTraining.Course build() { + com.baeldung.protobuf.BaeldungTraining.Course result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public com.baeldung.protobuf.BaeldungTraining.Course buildPartial() { + com.baeldung.protobuf.BaeldungTraining.Course result = new com.baeldung.protobuf.BaeldungTraining.Course(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + result.id_ = id_; + result.courseName_ = courseName_; + if (studentBuilder_ == null) { + if (((bitField0_ & 0x00000004) == 0x00000004)) { + student_ = java.util.Collections.unmodifiableList(student_); + bitField0_ = (bitField0_ & ~0x00000004); + } + result.student_ = student_; + } else { + result.student_ = studentBuilder_.build(); + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.baeldung.protobuf.BaeldungTraining.Course) { + return mergeFrom((com.baeldung.protobuf.BaeldungTraining.Course) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.baeldung.protobuf.BaeldungTraining.Course other) { + if (other == com.baeldung.protobuf.BaeldungTraining.Course.getDefaultInstance()) + return this; + if (other.getId() != 0) { + setId(other.getId()); + } + if (!other.getCourseName().isEmpty()) { + courseName_ = other.courseName_; + onChanged(); + } + if (studentBuilder_ == null) { + if (!other.student_.isEmpty()) { + if (student_.isEmpty()) { + student_ = other.student_; + bitField0_ = (bitField0_ & ~0x00000004); + } else { + ensureStudentIsMutable(); + student_.addAll(other.student_); + } + onChanged(); + } + } else { + if (!other.student_.isEmpty()) { + if (studentBuilder_.isEmpty()) { + studentBuilder_.dispose(); + studentBuilder_ = null; + student_ = other.student_; + bitField0_ = (bitField0_ & ~0x00000004); + studentBuilder_ = com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? getStudentFieldBuilder() : null; + } else { + studentBuilder_.addAllMessages(other.student_); + } + } + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + com.baeldung.protobuf.BaeldungTraining.Course parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.baeldung.protobuf.BaeldungTraining.Course) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private int bitField0_; + + private int id_; + + /** + * optional int32 id = 1; + */ + public int getId() { + return id_; + } + + /** + * optional int32 id = 1; + */ + public Builder setId(int value) { + + id_ = value; + onChanged(); + return this; + } + + /** + * optional int32 id = 1; + */ + public Builder clearId() { + + id_ = 0; + onChanged(); + return this; + } + + private java.lang.Object courseName_ = ""; + + /** + * optional string course_name = 2; + */ + public java.lang.String getCourseName() { + java.lang.Object ref = courseName_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + courseName_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + + /** + * optional string course_name = 2; + */ + public com.google.protobuf.ByteString getCourseNameBytes() { + java.lang.Object ref = courseName_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + courseName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * optional string course_name = 2; + */ + public Builder setCourseName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + courseName_ = value; + onChanged(); + return this; + } + + /** + * optional string course_name = 2; + */ + public Builder clearCourseName() { + + courseName_ = getDefaultInstance().getCourseName(); + onChanged(); + return this; + } + + /** + * optional string course_name = 2; + */ + public Builder setCourseNameBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + courseName_ = value; + onChanged(); + return this; + } + + private java.util.List student_ = java.util.Collections.emptyList(); + + private void ensureStudentIsMutable() { + if (!((bitField0_ & 0x00000004) == 0x00000004)) { + student_ = new java.util.ArrayList(student_); + bitField0_ |= 0x00000004; + } + } + + private com.google.protobuf.RepeatedFieldBuilder studentBuilder_; + + /** + * repeated .baeldung.Student student = 3; + */ + public java.util.List getStudentList() { + if (studentBuilder_ == null) { + return java.util.Collections.unmodifiableList(student_); + } else { + return studentBuilder_.getMessageList(); + } + } + + /** + * repeated .baeldung.Student student = 3; + */ + public int getStudentCount() { + if (studentBuilder_ == null) { + return student_.size(); + } else { + return studentBuilder_.getCount(); + } + } + + /** + * repeated .baeldung.Student student = 3; + */ + public com.baeldung.protobuf.BaeldungTraining.Student getStudent(int index) { + if (studentBuilder_ == null) { + return student_.get(index); + } else { + return studentBuilder_.getMessage(index); + } + } + + /** + * repeated .baeldung.Student student = 3; + */ + public Builder setStudent(int index, com.baeldung.protobuf.BaeldungTraining.Student value) { + if (studentBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureStudentIsMutable(); + student_.set(index, value); + onChanged(); + } else { + studentBuilder_.setMessage(index, value); + } + return this; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public Builder setStudent(int index, com.baeldung.protobuf.BaeldungTraining.Student.Builder builderForValue) { + if (studentBuilder_ == null) { + ensureStudentIsMutable(); + student_.set(index, builderForValue.build()); + onChanged(); + } else { + studentBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public Builder addStudent(com.baeldung.protobuf.BaeldungTraining.Student value) { + if (studentBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureStudentIsMutable(); + student_.add(value); + onChanged(); + } else { + studentBuilder_.addMessage(value); + } + return this; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public Builder addStudent(int index, com.baeldung.protobuf.BaeldungTraining.Student value) { + if (studentBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureStudentIsMutable(); + student_.add(index, value); + onChanged(); + } else { + studentBuilder_.addMessage(index, value); + } + return this; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public Builder addStudent(com.baeldung.protobuf.BaeldungTraining.Student.Builder builderForValue) { + if (studentBuilder_ == null) { + ensureStudentIsMutable(); + student_.add(builderForValue.build()); + onChanged(); + } else { + studentBuilder_.addMessage(builderForValue.build()); + } + return this; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public Builder addStudent(int index, com.baeldung.protobuf.BaeldungTraining.Student.Builder builderForValue) { + if (studentBuilder_ == null) { + ensureStudentIsMutable(); + student_.add(index, builderForValue.build()); + onChanged(); + } else { + studentBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public Builder addAllStudent(java.lang.Iterable values) { + if (studentBuilder_ == null) { + ensureStudentIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll(values, student_); + onChanged(); + } else { + studentBuilder_.addAllMessages(values); + } + return this; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public Builder clearStudent() { + if (studentBuilder_ == null) { + student_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + } else { + studentBuilder_.clear(); + } + return this; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public Builder removeStudent(int index) { + if (studentBuilder_ == null) { + ensureStudentIsMutable(); + student_.remove(index); + onChanged(); + } else { + studentBuilder_.remove(index); + } + return this; + } + + /** + * repeated .baeldung.Student student = 3; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.Builder getStudentBuilder(int index) { + return getStudentFieldBuilder().getBuilder(index); + } + + /** + * repeated .baeldung.Student student = 3; + */ + public com.baeldung.protobuf.BaeldungTraining.StudentOrBuilder getStudentOrBuilder(int index) { + if (studentBuilder_ == null) { + return student_.get(index); + } else { + return studentBuilder_.getMessageOrBuilder(index); + } + } + + /** + * repeated .baeldung.Student student = 3; + */ + public java.util.List getStudentOrBuilderList() { + if (studentBuilder_ != null) { + return studentBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(student_); + } + } + + /** + * repeated .baeldung.Student student = 3; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.Builder addStudentBuilder() { + return getStudentFieldBuilder().addBuilder(com.baeldung.protobuf.BaeldungTraining.Student.getDefaultInstance()); + } + + /** + * repeated .baeldung.Student student = 3; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.Builder addStudentBuilder(int index) { + return getStudentFieldBuilder().addBuilder(index, com.baeldung.protobuf.BaeldungTraining.Student.getDefaultInstance()); + } + + /** + * repeated .baeldung.Student student = 3; + */ + public java.util.List getStudentBuilderList() { + return getStudentFieldBuilder().getBuilderList(); + } + + private com.google.protobuf.RepeatedFieldBuilder getStudentFieldBuilder() { + if (studentBuilder_ == null) { + studentBuilder_ = new com.google.protobuf.RepeatedFieldBuilder(student_, + ((bitField0_ & 0x00000004) == 0x00000004), getParentForChildren(), isClean()); + student_ = null; + } + return studentBuilder_; + } + + public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + // @@protoc_insertion_point(builder_scope:baeldung.Course) + } + + // @@protoc_insertion_point(class_scope:baeldung.Course) + private static final com.baeldung.protobuf.BaeldungTraining.Course DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.baeldung.protobuf.BaeldungTraining.Course(); + } + + public static com.baeldung.protobuf.BaeldungTraining.Course getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = new com.google.protobuf.AbstractParser() { + public Course parsePartialFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return new Course(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public com.baeldung.protobuf.BaeldungTraining.Course getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface StudentOrBuilder extends + // @@protoc_insertion_point(interface_extends:baeldung.Student) + com.google.protobuf.MessageOrBuilder { + + /** + * optional int32 id = 1; + */ + int getId(); + + /** + * optional string first_name = 2; + */ + java.lang.String getFirstName(); + + /** + * optional string first_name = 2; + */ + com.google.protobuf.ByteString getFirstNameBytes(); + + /** + * optional string last_name = 3; + */ + java.lang.String getLastName(); + + /** + * optional string last_name = 3; + */ + com.google.protobuf.ByteString getLastNameBytes(); + + /** + * optional string email = 4; + */ + java.lang.String getEmail(); + + /** + * optional string email = 4; + */ + com.google.protobuf.ByteString getEmailBytes(); + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + java.util.List getPhoneList(); + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber getPhone(int index); + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + int getPhoneCount(); + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + java.util.List getPhoneOrBuilderList(); + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumberOrBuilder getPhoneOrBuilder(int index); + } + + /** + * Protobuf type {@code baeldung.Student} + */ + public static final class Student extends com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:baeldung.Student) + StudentOrBuilder { + // Use Student.newBuilder() to construct. + private Student(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + + private Student() { + id_ = 0; + firstName_ = ""; + lastName_ = ""; + email_ = ""; + phone_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + + private Student(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 8: { + + id_ = input.readInt32(); + break; + } + case 18: { + java.lang.String s = input.readStringRequireUtf8(); + + firstName_ = s; + break; + } + case 26: { + java.lang.String s = input.readStringRequireUtf8(); + + lastName_ = s; + break; + } + case 34: { + java.lang.String s = input.readStringRequireUtf8(); + + email_ = s; + break; + } + case 42: { + if (!((mutable_bitField0_ & 0x00000010) == 0x00000010)) { + phone_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000010; + } + phone_.add(input.readMessage(com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.parser(), extensionRegistry)); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); + } finally { + if (((mutable_bitField0_ & 0x00000010) == 0x00000010)) { + phone_ = java.util.Collections.unmodifiableList(phone_); + } + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Student_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Student_fieldAccessorTable.ensureFieldAccessorsInitialized(com.baeldung.protobuf.BaeldungTraining.Student.class, com.baeldung.protobuf.BaeldungTraining.Student.Builder.class); + } + + /** + * Protobuf enum {@code baeldung.Student.PhoneType} + */ + public enum PhoneType implements com.google.protobuf.ProtocolMessageEnum { + /** + * MOBILE = 0; + */ + MOBILE(0), + /** + * LANDLINE = 1; + */ + LANDLINE(1), UNRECOGNIZED(-1),; + + /** + * MOBILE = 0; + */ + public static final int MOBILE_VALUE = 0; + /** + * LANDLINE = 1; + */ + public static final int LANDLINE_VALUE = 1; + + public final int getNumber() { + if (this == UNRECOGNIZED) { + throw new java.lang.IllegalArgumentException("Can't get the number of an unknown enum value."); + } + return value; + } + + /** + * @deprecated Use {@link #forNumber(int)} instead. + */ + @java.lang.Deprecated + public static PhoneType valueOf(int value) { + return forNumber(value); + } + + public static PhoneType forNumber(int value) { + switch (value) { + case 0: + return MOBILE; + case 1: + return LANDLINE; + default: + return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap internalGetValueMap() { + return internalValueMap; + } + + private static final com.google.protobuf.Internal.EnumLiteMap internalValueMap = new com.google.protobuf.Internal.EnumLiteMap() { + public PhoneType findValueByNumber(int number) { + return PhoneType.forNumber(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor getValueDescriptor() { + return getDescriptor().getValues().get(ordinal()); + } + + public final com.google.protobuf.Descriptors.EnumDescriptor getDescriptorForType() { + return getDescriptor(); + } + + public static final com.google.protobuf.Descriptors.EnumDescriptor getDescriptor() { + return com.baeldung.protobuf.BaeldungTraining.Student.getDescriptor().getEnumTypes().get(0); + } + + private static final PhoneType[] VALUES = values(); + + public static PhoneType valueOf(com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException("EnumValueDescriptor is not for this type."); + } + if (desc.getIndex() == -1) { + return UNRECOGNIZED; + } + return VALUES[desc.getIndex()]; + } + + private final int value; + + private PhoneType(int value) { + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:baeldung.Student.PhoneType) + } + + public interface PhoneNumberOrBuilder extends + // @@protoc_insertion_point(interface_extends:baeldung.Student.PhoneNumber) + com.google.protobuf.MessageOrBuilder { + + /** + * optional string number = 1; + */ + java.lang.String getNumber(); + + /** + * optional string number = 1; + */ + com.google.protobuf.ByteString getNumberBytes(); + + /** + * optional .baeldung.Student.PhoneType type = 2; + */ + int getTypeValue(); + + /** + * optional .baeldung.Student.PhoneType type = 2; + */ + com.baeldung.protobuf.BaeldungTraining.Student.PhoneType getType(); + } + + /** + * Protobuf type {@code baeldung.Student.PhoneNumber} + */ + public static final class PhoneNumber extends com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:baeldung.Student.PhoneNumber) + PhoneNumberOrBuilder { + // Use PhoneNumber.newBuilder() to construct. + private PhoneNumber(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + + private PhoneNumber() { + number_ = ""; + type_ = 0; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + + private PhoneNumber(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + + number_ = s; + break; + } + case 16: { + int rawValue = input.readEnum(); + + type_ = rawValue; + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(this); + } finally { + makeExtensionsImmutable(); + } + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Student_PhoneNumber_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Student_PhoneNumber_fieldAccessorTable.ensureFieldAccessorsInitialized(com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.class, + com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.Builder.class); + } + + public static final int NUMBER_FIELD_NUMBER = 1; + private volatile java.lang.Object number_; + + /** + * optional string number = 1; + */ + public java.lang.String getNumber() { + java.lang.Object ref = number_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + number_ = s; + return s; + } + } + + /** + * optional string number = 1; + */ + public com.google.protobuf.ByteString getNumberBytes() { + java.lang.Object ref = number_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + number_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int TYPE_FIELD_NUMBER = 2; + private int type_; + + /** + * optional .baeldung.Student.PhoneType type = 2; + */ + public int getTypeValue() { + return type_; + } + + /** + * optional .baeldung.Student.PhoneType type = 2; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneType getType() { + com.baeldung.protobuf.BaeldungTraining.Student.PhoneType result = com.baeldung.protobuf.BaeldungTraining.Student.PhoneType.forNumber(type_); + return result == null ? com.baeldung.protobuf.BaeldungTraining.Student.PhoneType.UNRECOGNIZED : result; + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) + return true; + if (isInitialized == 0) + return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (!getNumberBytes().isEmpty()) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, number_); + } + if (type_ != com.baeldung.protobuf.BaeldungTraining.Student.PhoneType.MOBILE.getNumber()) { + output.writeEnum(2, type_); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) + return size; + + size = 0; + if (!getNumberBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, number_); + } + if (type_ != com.baeldung.protobuf.BaeldungTraining.Student.PhoneType.MOBILE.getNumber()) { + size += com.google.protobuf.CodedOutputStream.computeEnumSize(2, type_); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parseFrom(com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parseFrom(com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parseFrom(byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parseFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parseFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parseDelimitedFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parseFrom(com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parseFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + + /** + * Protobuf type {@code baeldung.Student.PhoneNumber} + */ + public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:baeldung.Student.PhoneNumber) + com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumberOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Student_PhoneNumber_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Student_PhoneNumber_fieldAccessorTable.ensureFieldAccessorsInitialized(com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.class, + com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.Builder.class); + } + + // Construct using com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + + public Builder clear() { + super.clear(); + number_ = ""; + + type_ = 0; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Student_PhoneNumber_descriptor; + } + + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber getDefaultInstanceForType() { + return com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.getDefaultInstance(); + } + + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber build() { + com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber buildPartial() { + com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber result = new com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber(this); + result.number_ = number_; + result.type_ = type_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber) { + return mergeFrom((com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber other) { + if (other == com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.getDefaultInstance()) + return this; + if (!other.getNumber().isEmpty()) { + number_ = other.number_; + onChanged(); + } + if (other.type_ != 0) { + setTypeValue(other.getTypeValue()); + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private java.lang.Object number_ = ""; + + /** + * optional string number = 1; + */ + public java.lang.String getNumber() { + java.lang.Object ref = number_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + number_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + + /** + * optional string number = 1; + */ + public com.google.protobuf.ByteString getNumberBytes() { + java.lang.Object ref = number_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + number_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * optional string number = 1; + */ + public Builder setNumber(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + number_ = value; + onChanged(); + return this; + } + + /** + * optional string number = 1; + */ + public Builder clearNumber() { + + number_ = getDefaultInstance().getNumber(); + onChanged(); + return this; + } + + /** + * optional string number = 1; + */ + public Builder setNumberBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + number_ = value; + onChanged(); + return this; + } + + private int type_ = 0; + + /** + * optional .baeldung.Student.PhoneType type = 2; + */ + public int getTypeValue() { + return type_; + } + + /** + * optional .baeldung.Student.PhoneType type = 2; + */ + public Builder setTypeValue(int value) { + type_ = value; + onChanged(); + return this; + } + + /** + * optional .baeldung.Student.PhoneType type = 2; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneType getType() { + com.baeldung.protobuf.BaeldungTraining.Student.PhoneType result = com.baeldung.protobuf.BaeldungTraining.Student.PhoneType.forNumber(type_); + return result == null ? com.baeldung.protobuf.BaeldungTraining.Student.PhoneType.UNRECOGNIZED : result; + } + + /** + * optional .baeldung.Student.PhoneType type = 2; + */ + public Builder setType(com.baeldung.protobuf.BaeldungTraining.Student.PhoneType value) { + if (value == null) { + throw new NullPointerException(); + } + + type_ = value.getNumber(); + onChanged(); + return this; + } + + /** + * optional .baeldung.Student.PhoneType type = 2; + */ + public Builder clearType() { + + type_ = 0; + onChanged(); + return this; + } + + public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + // @@protoc_insertion_point(builder_scope:baeldung.Student.PhoneNumber) + } + + // @@protoc_insertion_point(class_scope:baeldung.Student.PhoneNumber) + private static final com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber(); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = new com.google.protobuf.AbstractParser() { + public PhoneNumber parsePartialFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return new PhoneNumber(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private int bitField0_; + public static final int ID_FIELD_NUMBER = 1; + private int id_; + + /** + * optional int32 id = 1; + */ + public int getId() { + return id_; + } + + public static final int FIRST_NAME_FIELD_NUMBER = 2; + private volatile java.lang.Object firstName_; + + /** + * optional string first_name = 2; + */ + public java.lang.String getFirstName() { + java.lang.Object ref = firstName_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + firstName_ = s; + return s; + } + } + + /** + * optional string first_name = 2; + */ + public com.google.protobuf.ByteString getFirstNameBytes() { + java.lang.Object ref = firstName_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + firstName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int LAST_NAME_FIELD_NUMBER = 3; + private volatile java.lang.Object lastName_; + + /** + * optional string last_name = 3; + */ + public java.lang.String getLastName() { + java.lang.Object ref = lastName_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + lastName_ = s; + return s; + } + } + + /** + * optional string last_name = 3; + */ + public com.google.protobuf.ByteString getLastNameBytes() { + java.lang.Object ref = lastName_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + lastName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int EMAIL_FIELD_NUMBER = 4; + private volatile java.lang.Object email_; + + /** + * optional string email = 4; + */ + public java.lang.String getEmail() { + java.lang.Object ref = email_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + email_ = s; + return s; + } + } + + /** + * optional string email = 4; + */ + public com.google.protobuf.ByteString getEmailBytes() { + java.lang.Object ref = email_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + email_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PHONE_FIELD_NUMBER = 5; + private java.util.List phone_; + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public java.util.List getPhoneList() { + return phone_; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public java.util.List getPhoneOrBuilderList() { + return phone_; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public int getPhoneCount() { + return phone_.size(); + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber getPhone(int index) { + return phone_.get(index); + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumberOrBuilder getPhoneOrBuilder(int index) { + return phone_.get(index); + } + + private byte memoizedIsInitialized = -1; + + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) + return true; + if (isInitialized == 0) + return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (id_ != 0) { + output.writeInt32(1, id_); + } + if (!getFirstNameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, firstName_); + } + if (!getLastNameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, lastName_); + } + if (!getEmailBytes().isEmpty()) { + com.google.protobuf.GeneratedMessage.writeString(output, 4, email_); + } + for (int i = 0; i < phone_.size(); i++) { + output.writeMessage(5, phone_.get(i)); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) + return size; + + size = 0; + if (id_ != 0) { + size += com.google.protobuf.CodedOutputStream.computeInt32Size(1, id_); + } + if (!getFirstNameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, firstName_); + } + if (!getLastNameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, lastName_); + } + if (!getEmailBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(4, email_); + } + for (int i = 0; i < phone_.size(); i++) { + size += com.google.protobuf.CodedOutputStream.computeMessageSize(5, phone_.get(i)); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + + public static com.baeldung.protobuf.BaeldungTraining.Student parseFrom(com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student parseFrom(com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student parseFrom(byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student parseFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student parseFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student parseDelimitedFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student parseFrom(com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student parseFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry); + } + + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(com.baeldung.protobuf.BaeldungTraining.Student prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + public Builder toBuilder() { + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + + /** + * Protobuf type {@code baeldung.Student} + */ + public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:baeldung.Student) + com.baeldung.protobuf.BaeldungTraining.StudentOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Student_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Student_fieldAccessorTable.ensureFieldAccessorsInitialized(com.baeldung.protobuf.BaeldungTraining.Student.class, + com.baeldung.protobuf.BaeldungTraining.Student.Builder.class); + } + + // Construct using com.baeldung.protobuf.BaeldungTraining.Student.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + getPhoneFieldBuilder(); + } + } + + public Builder clear() { + super.clear(); + id_ = 0; + + firstName_ = ""; + + lastName_ = ""; + + email_ = ""; + + if (phoneBuilder_ == null) { + phone_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010); + } else { + phoneBuilder_.clear(); + } + return this; + } + + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.baeldung.protobuf.BaeldungTraining.internal_static_baeldung_Student_descriptor; + } + + public com.baeldung.protobuf.BaeldungTraining.Student getDefaultInstanceForType() { + return com.baeldung.protobuf.BaeldungTraining.Student.getDefaultInstance(); + } + + public com.baeldung.protobuf.BaeldungTraining.Student build() { + com.baeldung.protobuf.BaeldungTraining.Student result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public com.baeldung.protobuf.BaeldungTraining.Student buildPartial() { + com.baeldung.protobuf.BaeldungTraining.Student result = new com.baeldung.protobuf.BaeldungTraining.Student(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + result.id_ = id_; + result.firstName_ = firstName_; + result.lastName_ = lastName_; + result.email_ = email_; + if (phoneBuilder_ == null) { + if (((bitField0_ & 0x00000010) == 0x00000010)) { + phone_ = java.util.Collections.unmodifiableList(phone_); + bitField0_ = (bitField0_ & ~0x00000010); + } + result.phone_ = phone_; + } else { + result.phone_ = phoneBuilder_.build(); + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.baeldung.protobuf.BaeldungTraining.Student) { + return mergeFrom((com.baeldung.protobuf.BaeldungTraining.Student) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.baeldung.protobuf.BaeldungTraining.Student other) { + if (other == com.baeldung.protobuf.BaeldungTraining.Student.getDefaultInstance()) + return this; + if (other.getId() != 0) { + setId(other.getId()); + } + if (!other.getFirstName().isEmpty()) { + firstName_ = other.firstName_; + onChanged(); + } + if (!other.getLastName().isEmpty()) { + lastName_ = other.lastName_; + onChanged(); + } + if (!other.getEmail().isEmpty()) { + email_ = other.email_; + onChanged(); + } + if (phoneBuilder_ == null) { + if (!other.phone_.isEmpty()) { + if (phone_.isEmpty()) { + phone_ = other.phone_; + bitField0_ = (bitField0_ & ~0x00000010); + } else { + ensurePhoneIsMutable(); + phone_.addAll(other.phone_); + } + onChanged(); + } + } else { + if (!other.phone_.isEmpty()) { + if (phoneBuilder_.isEmpty()) { + phoneBuilder_.dispose(); + phoneBuilder_ = null; + phone_ = other.phone_; + bitField0_ = (bitField0_ & ~0x00000010); + phoneBuilder_ = com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? getPhoneFieldBuilder() : null; + } else { + phoneBuilder_.addAllMessages(other.phone_); + } + } + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { + com.baeldung.protobuf.BaeldungTraining.Student parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (com.baeldung.protobuf.BaeldungTraining.Student) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private int bitField0_; + + private int id_; + + /** + * optional int32 id = 1; + */ + public int getId() { + return id_; + } + + /** + * optional int32 id = 1; + */ + public Builder setId(int value) { + + id_ = value; + onChanged(); + return this; + } + + /** + * optional int32 id = 1; + */ + public Builder clearId() { + + id_ = 0; + onChanged(); + return this; + } + + private java.lang.Object firstName_ = ""; + + /** + * optional string first_name = 2; + */ + public java.lang.String getFirstName() { + java.lang.Object ref = firstName_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + firstName_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + + /** + * optional string first_name = 2; + */ + public com.google.protobuf.ByteString getFirstNameBytes() { + java.lang.Object ref = firstName_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + firstName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * optional string first_name = 2; + */ + public Builder setFirstName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + firstName_ = value; + onChanged(); + return this; + } + + /** + * optional string first_name = 2; + */ + public Builder clearFirstName() { + + firstName_ = getDefaultInstance().getFirstName(); + onChanged(); + return this; + } + + /** + * optional string first_name = 2; + */ + public Builder setFirstNameBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + firstName_ = value; + onChanged(); + return this; + } + + private java.lang.Object lastName_ = ""; + + /** + * optional string last_name = 3; + */ + public java.lang.String getLastName() { + java.lang.Object ref = lastName_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + lastName_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + + /** + * optional string last_name = 3; + */ + public com.google.protobuf.ByteString getLastNameBytes() { + java.lang.Object ref = lastName_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + lastName_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * optional string last_name = 3; + */ + public Builder setLastName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + lastName_ = value; + onChanged(); + return this; + } + + /** + * optional string last_name = 3; + */ + public Builder clearLastName() { + + lastName_ = getDefaultInstance().getLastName(); + onChanged(); + return this; + } + + /** + * optional string last_name = 3; + */ + public Builder setLastNameBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + lastName_ = value; + onChanged(); + return this; + } + + private java.lang.Object email_ = ""; + + /** + * optional string email = 4; + */ + public java.lang.String getEmail() { + java.lang.Object ref = email_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + email_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + + /** + * optional string email = 4; + */ + public com.google.protobuf.ByteString getEmailBytes() { + java.lang.Object ref = email_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + email_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * optional string email = 4; + */ + public Builder setEmail(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + email_ = value; + onChanged(); + return this; + } + + /** + * optional string email = 4; + */ + public Builder clearEmail() { + + email_ = getDefaultInstance().getEmail(); + onChanged(); + return this; + } + + /** + * optional string email = 4; + */ + public Builder setEmailBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + email_ = value; + onChanged(); + return this; + } + + private java.util.List phone_ = java.util.Collections.emptyList(); + + private void ensurePhoneIsMutable() { + if (!((bitField0_ & 0x00000010) == 0x00000010)) { + phone_ = new java.util.ArrayList(phone_); + bitField0_ |= 0x00000010; + } + } + + private com.google.protobuf.RepeatedFieldBuilder phoneBuilder_; + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public java.util.List getPhoneList() { + if (phoneBuilder_ == null) { + return java.util.Collections.unmodifiableList(phone_); + } else { + return phoneBuilder_.getMessageList(); + } + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public int getPhoneCount() { + if (phoneBuilder_ == null) { + return phone_.size(); + } else { + return phoneBuilder_.getCount(); + } + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber getPhone(int index) { + if (phoneBuilder_ == null) { + return phone_.get(index); + } else { + return phoneBuilder_.getMessage(index); + } + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public Builder setPhone(int index, com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber value) { + if (phoneBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensurePhoneIsMutable(); + phone_.set(index, value); + onChanged(); + } else { + phoneBuilder_.setMessage(index, value); + } + return this; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public Builder setPhone(int index, com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.Builder builderForValue) { + if (phoneBuilder_ == null) { + ensurePhoneIsMutable(); + phone_.set(index, builderForValue.build()); + onChanged(); + } else { + phoneBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public Builder addPhone(com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber value) { + if (phoneBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensurePhoneIsMutable(); + phone_.add(value); + onChanged(); + } else { + phoneBuilder_.addMessage(value); + } + return this; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public Builder addPhone(int index, com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber value) { + if (phoneBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensurePhoneIsMutable(); + phone_.add(index, value); + onChanged(); + } else { + phoneBuilder_.addMessage(index, value); + } + return this; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public Builder addPhone(com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.Builder builderForValue) { + if (phoneBuilder_ == null) { + ensurePhoneIsMutable(); + phone_.add(builderForValue.build()); + onChanged(); + } else { + phoneBuilder_.addMessage(builderForValue.build()); + } + return this; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public Builder addPhone(int index, com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.Builder builderForValue) { + if (phoneBuilder_ == null) { + ensurePhoneIsMutable(); + phone_.add(index, builderForValue.build()); + onChanged(); + } else { + phoneBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public Builder addAllPhone(java.lang.Iterable values) { + if (phoneBuilder_ == null) { + ensurePhoneIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll(values, phone_); + onChanged(); + } else { + phoneBuilder_.addAllMessages(values); + } + return this; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public Builder clearPhone() { + if (phoneBuilder_ == null) { + phone_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + } else { + phoneBuilder_.clear(); + } + return this; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public Builder removePhone(int index) { + if (phoneBuilder_ == null) { + ensurePhoneIsMutable(); + phone_.remove(index); + onChanged(); + } else { + phoneBuilder_.remove(index); + } + return this; + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.Builder getPhoneBuilder(int index) { + return getPhoneFieldBuilder().getBuilder(index); + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumberOrBuilder getPhoneOrBuilder(int index) { + if (phoneBuilder_ == null) { + return phone_.get(index); + } else { + return phoneBuilder_.getMessageOrBuilder(index); + } + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public java.util.List getPhoneOrBuilderList() { + if (phoneBuilder_ != null) { + return phoneBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(phone_); + } + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.Builder addPhoneBuilder() { + return getPhoneFieldBuilder().addBuilder(com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.getDefaultInstance()); + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.Builder addPhoneBuilder(int index) { + return getPhoneFieldBuilder().addBuilder(index, com.baeldung.protobuf.BaeldungTraining.Student.PhoneNumber.getDefaultInstance()); + } + + /** + * repeated .baeldung.Student.PhoneNumber phone = 5; + */ + public java.util.List getPhoneBuilderList() { + return getPhoneFieldBuilder().getBuilderList(); + } + + private com.google.protobuf.RepeatedFieldBuilder getPhoneFieldBuilder() { + if (phoneBuilder_ == null) { + phoneBuilder_ = new com.google.protobuf.RepeatedFieldBuilder( + phone_, ((bitField0_ & 0x00000010) == 0x00000010), getParentForChildren(), isClean()); + phone_ = null; + } + return phoneBuilder_; + } + + public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + // @@protoc_insertion_point(builder_scope:baeldung.Student) + } + + // @@protoc_insertion_point(class_scope:baeldung.Student) + private static final com.baeldung.protobuf.BaeldungTraining.Student DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new com.baeldung.protobuf.BaeldungTraining.Student(); + } + + public static com.baeldung.protobuf.BaeldungTraining.Student getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = new com.google.protobuf.AbstractParser() { + public Student parsePartialFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { + return new Student(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public com.baeldung.protobuf.BaeldungTraining.Student getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private static final com.google.protobuf.Descriptors.Descriptor internal_static_baeldung_Course_descriptor; + private static final com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_baeldung_Course_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor internal_static_baeldung_Student_descriptor; + private static final com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_baeldung_Student_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor internal_static_baeldung_Student_PhoneNumber_descriptor; + private static final com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_baeldung_Student_PhoneNumber_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + return descriptor; + } + + private static com.google.protobuf.Descriptors.FileDescriptor descriptor; + static { + java.lang.String[] descriptorData = { "\n\030resources/baeldung.proto\022\010baeldung\"M\n\006" + "Course\022\n\n\002id\030\001 \001(\005\022\023\n\013course_name\030\002 \001(\t\022" + + "\"\n\007student\030\003 \003(\0132\021.baeldung.Student\"\352\001\n\007" + "Student\022\n\n\002id\030\001 \001(\005\022\022\n\nfirst_name\030\002 \001(\t\022" + + "\021\n\tlast_name\030\003 \001(\t\022\r\n\005email\030\004 \001(\t\022,\n\005pho" + "ne\030\005 \003(\0132\035.baeldung.Student.PhoneNumber\032" + "H\n\013PhoneNumber\022\016\n\006number\030\001 \001(\t\022)\n\004type\030\002" + + " \001(\0162\033.baeldung.Student.PhoneType\"%\n\tPho" + "neType\022\n\n\006MOBILE\020\000\022\014\n\010LANDLINE\020\001B)\n\025com." + "baeldung.protobufB\020BaeldungTrainingb\006pro", "to3" }; + com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { + public com.google.protobuf.ExtensionRegistry assignDescriptors(com.google.protobuf.Descriptors.FileDescriptor root) { + descriptor = root; + return null; + } + }; + com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {}, assigner); + internal_static_baeldung_Course_descriptor = getDescriptor().getMessageTypes().get(0); + internal_static_baeldung_Course_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable(internal_static_baeldung_Course_descriptor, new java.lang.String[] { "Id", "CourseName", "Student", }); + internal_static_baeldung_Student_descriptor = getDescriptor().getMessageTypes().get(1); + internal_static_baeldung_Student_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable(internal_static_baeldung_Student_descriptor, new java.lang.String[] { "Id", "FirstName", "LastName", "Email", "Phone", }); + internal_static_baeldung_Student_PhoneNumber_descriptor = internal_static_baeldung_Student_descriptor.getNestedTypes().get(0); + internal_static_baeldung_Student_PhoneNumber_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable(internal_static_baeldung_Student_PhoneNumber_descriptor, new java.lang.String[] { "Number", "Type", }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/spring-protobuf/src/main/java/com/baeldung/protobuf/CourseController.java b/spring-protobuf/src/main/java/com/baeldung/protobuf/CourseController.java new file mode 100644 index 0000000000..807b9a9ea4 --- /dev/null +++ b/spring-protobuf/src/main/java/com/baeldung/protobuf/CourseController.java @@ -0,0 +1,20 @@ +package com.baeldung.protobuf; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.protobuf.BaeldungTraining.Course; + +@RestController +public class CourseController { + + @Autowired + CourseRepository courseRepo; + + @RequestMapping("/courses/{id}") + Course customer(@PathVariable Integer id) { + return courseRepo.getCourse(id); + } +} diff --git a/spring-protobuf/src/main/java/com/baeldung/protobuf/CourseRepository.java b/spring-protobuf/src/main/java/com/baeldung/protobuf/CourseRepository.java new file mode 100644 index 0000000000..cbafd7d224 --- /dev/null +++ b/spring-protobuf/src/main/java/com/baeldung/protobuf/CourseRepository.java @@ -0,0 +1,18 @@ +package com.baeldung.protobuf; + +import com.baeldung.protobuf.BaeldungTraining.Course; + +import java.util.Map; + +public class CourseRepository { + + private final Map courses; + + public CourseRepository(Map courses) { + this.courses = courses; + } + + public Course getCourse(int id) { + return courses.get(id); + } +} diff --git a/spring-protobuf/src/main/resources/baeldung.proto b/spring-protobuf/src/main/resources/baeldung.proto new file mode 100644 index 0000000000..20124c34c4 --- /dev/null +++ b/spring-protobuf/src/main/resources/baeldung.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package baeldung; + +option java_package = "com.baeldung.protobuf"; +option java_outer_classname = "BaeldungTraining"; + +message Course { + int32 id = 1; + string course_name = 2; + repeated Student student = 3; +} + +message Student { + int32 id = 1; + string first_name = 2; + string last_name = 3; + string email = 4; + repeated PhoneNumber phone = 5; + + message PhoneNumber { + string number = 1; + PhoneType type = 2; + } + + enum PhoneType { + MOBILE = 0; + LANDLINE = 1; + } +} \ No newline at end of file diff --git a/spring-protobuf/src/test/java/com/baeldung/protobuf/ApplicationTest.java b/spring-protobuf/src/test/java/com/baeldung/protobuf/ApplicationTest.java new file mode 100644 index 0000000000..a17082cea7 --- /dev/null +++ b/spring-protobuf/src/test/java/com/baeldung/protobuf/ApplicationTest.java @@ -0,0 +1,75 @@ +package com.baeldung.protobuf; + +import com.baeldung.protobuf.BaeldungTraining.Course; +import com.googlecode.protobuf.format.JsonFormat; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.WebIntegrationTest; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.io.InputStream; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebIntegrationTest +public class ApplicationTest { + + private static final String COURSE1_URL = "http://localhost:8080/courses/1"; + + @Autowired + private RestTemplate restTemplate; + + @Test + public void whenUsingRestTemplate_thenSucceed() { + ResponseEntity course = restTemplate.getForEntity(COURSE1_URL, Course.class); + assertResponse(course.toString()); + } + + @Test + public void whenUsingHttpClient_thenSucceed() throws IOException { + InputStream responseStream = executeHttpRequest(COURSE1_URL); + String jsonOutput = convertProtobufMessageStreamToJsonString(responseStream); + assertResponse(jsonOutput); + } + + private InputStream executeHttpRequest(String url) throws IOException { + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpGet request = new HttpGet(url); + HttpResponse httpResponse = httpClient.execute(request); + return httpResponse.getEntity().getContent(); + } + + private String convertProtobufMessageStreamToJsonString(InputStream protobufStream) throws IOException { + JsonFormat jsonFormat = new JsonFormat(); + Course course = Course.parseFrom(protobufStream); + return jsonFormat.printToString(course); + } + + private void assertResponse(String response) { + assertThat(response, containsString("id")); + assertThat(response, containsString("course_name")); + assertThat(response, containsString("REST with Spring")); + assertThat(response, containsString("student")); + assertThat(response, containsString("first_name")); + assertThat(response, containsString("last_name")); + assertThat(response, containsString("email")); + assertThat(response, containsString("john.doe@baeldung.com")); + assertThat(response, containsString("richard.roe@baeldung.com")); + assertThat(response, containsString("jane.doe@baeldung.com")); + assertThat(response, containsString("phone")); + assertThat(response, containsString("number")); + assertThat(response, containsString("type")); + } +} \ No newline at end of file diff --git a/spring-quartz/pom.xml b/spring-quartz/pom.xml index ce286f3d1f..709cfb9e3d 100644 --- a/spring-quartz/pom.xml +++ b/spring-quartz/pom.xml @@ -3,7 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.baeldung + com.baeldung spring-quartz spring-quartz 0.0.1-SNAPSHOT diff --git a/spring-rest-angular/pom.xml b/spring-rest-angular/pom.xml new file mode 100644 index 0000000000..331c9a644c --- /dev/null +++ b/spring-rest-angular/pom.xml @@ -0,0 +1,95 @@ + + + 4.0.0 + spring-rest-angular + spring-rest-angular + com.baeldung + 1.0 + war + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.data + spring-data-commons + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.hsqldb + hsqldb + runtime + + + org.springframework + spring-test + test + + + org.apache.commons + commons-lang3 + 3.3 + + + com.google.guava + guava + 19.0 + + + junit + junit + test + + + io.rest-assured + rest-assured + 3.0.0 + test + + + io.rest-assured + spring-mock-mvc + 3.0.0 + test + + + + angular-spring-rest-sample + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + + false + + + + + + diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java b/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java new file mode 100644 index 0000000000..b1aafb583a --- /dev/null +++ b/spring-rest-angular/src/main/java/org/baeldung/web/dao/StudentRepository.java @@ -0,0 +1,8 @@ +package org.baeldung.web.dao; + +import org.baeldung.web.entity.Student; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface StudentRepository extends JpaRepository { + +} diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/entity/Student.java b/spring-rest-angular/src/main/java/org/baeldung/web/entity/Student.java new file mode 100644 index 0000000000..0a0b60d87d --- /dev/null +++ b/spring-rest-angular/src/main/java/org/baeldung/web/entity/Student.java @@ -0,0 +1,69 @@ +package org.baeldung.web.entity; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class Student implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public Student() { + } + + public Student(long id, String name, String gender, Integer age) { + super(); + this.id = id; + this.name = name; + this.gender = gender; + this.age = age; + } + + @Id + private long id; + @Column(nullable = false) + private String name; + @Column(nullable = false) + private String gender; + @Column(nullable = false) + private Integer age; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + +} diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/exception/MyResourceNotFoundException.java b/spring-rest-angular/src/main/java/org/baeldung/web/exception/MyResourceNotFoundException.java new file mode 100644 index 0000000000..740caec59e --- /dev/null +++ b/spring-rest-angular/src/main/java/org/baeldung/web/exception/MyResourceNotFoundException.java @@ -0,0 +1,26 @@ +package org.baeldung.web.exception; + +public class MyResourceNotFoundException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 4088649120307193208L; + + public MyResourceNotFoundException() { + super(); + } + + public MyResourceNotFoundException(final String message, final Throwable cause) { + super(message, cause); + } + + public MyResourceNotFoundException(final String message) { + super(message); + } + + public MyResourceNotFoundException(final Throwable cause) { + super(cause); + } + +} diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/main/Application.java b/spring-rest-angular/src/main/java/org/baeldung/web/main/Application.java new file mode 100644 index 0000000000..d6fe719311 --- /dev/null +++ b/spring-rest-angular/src/main/java/org/baeldung/web/main/Application.java @@ -0,0 +1,25 @@ +package org.baeldung.web.main; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.web.filter.ShallowEtagHeaderFilter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@SpringBootApplication +@EnableAutoConfiguration +@Import(PersistenceConfig.class) +public class Application extends WebMvcConfigurerAdapter { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + public ShallowEtagHeaderFilter shallowEtagHeaderFilter() { + return new ShallowEtagHeaderFilter(); + } + +} diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java b/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java new file mode 100644 index 0000000000..df1240f270 --- /dev/null +++ b/spring-rest-angular/src/main/java/org/baeldung/web/main/PersistenceConfig.java @@ -0,0 +1,33 @@ +package org.baeldung.web.main; + +import javax.sql.DataSource; + +import org.springframework.boot.orm.jpa.EntityScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +@EnableJpaRepositories("org.baeldung.web.dao") +@ComponentScan(basePackages = { "org.baeldung.web" }) +@EntityScan("org.baeldung.web.entity") +@Configuration +public class PersistenceConfig { + + @Bean + public JdbcTemplate getJdbcTemplate() { + return new JdbcTemplate(dataSource()); + } + + @Bean + public DataSource dataSource() { + EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL).addScript("db/sql/data.sql").build(); + return db; + } + +} diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/rest/StudentDirectoryRestController.java b/spring-rest-angular/src/main/java/org/baeldung/web/rest/StudentDirectoryRestController.java new file mode 100644 index 0000000000..dc295a3d97 --- /dev/null +++ b/spring-rest-angular/src/main/java/org/baeldung/web/rest/StudentDirectoryRestController.java @@ -0,0 +1,29 @@ +package org.baeldung.web.rest; + +import org.baeldung.web.entity.Student; +import org.baeldung.web.exception.MyResourceNotFoundException; +import org.baeldung.web.service.StudentService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +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.RestController; + +@RestController +public class StudentDirectoryRestController { + + @Autowired + private StudentService service; + + @RequestMapping(value = "/student/get", params = { "page", "size" }, method = RequestMethod.GET, produces = "application/json") + public Page findPaginated(@RequestParam("page") int page, @RequestParam("size") int size) { + + Page resultPage = service.findPaginated(page, size); + if (page > resultPage.getTotalPages()) { + throw new MyResourceNotFoundException(); + } + return resultPage; + } + +} diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/service/IOperations.java b/spring-rest-angular/src/main/java/org/baeldung/web/service/IOperations.java new file mode 100644 index 0000000000..2176c0bb70 --- /dev/null +++ b/spring-rest-angular/src/main/java/org/baeldung/web/service/IOperations.java @@ -0,0 +1,9 @@ +package org.baeldung.web.service; + +import org.springframework.data.domain.Page; + +public interface IOperations { + + public Page findPaginated(final int page, final int size); + +} diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/service/StudentService.java b/spring-rest-angular/src/main/java/org/baeldung/web/service/StudentService.java new file mode 100644 index 0000000000..1b194f76e2 --- /dev/null +++ b/spring-rest-angular/src/main/java/org/baeldung/web/service/StudentService.java @@ -0,0 +1,7 @@ +package org.baeldung.web.service; + +import org.baeldung.web.entity.Student; + +public interface StudentService extends IOperations { + +} diff --git a/spring-rest-angular/src/main/java/org/baeldung/web/service/StudentServiceImpl.java b/spring-rest-angular/src/main/java/org/baeldung/web/service/StudentServiceImpl.java new file mode 100644 index 0000000000..c7bcdc5bd5 --- /dev/null +++ b/spring-rest-angular/src/main/java/org/baeldung/web/service/StudentServiceImpl.java @@ -0,0 +1,21 @@ +package org.baeldung.web.service; + +import org.baeldung.web.dao.StudentRepository; +import org.baeldung.web.entity.Student; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; + +@Service +public class StudentServiceImpl implements StudentService { + + @Autowired + private StudentRepository dao; + + @Override + public Page findPaginated(int page, int size) { + return dao.findAll(new PageRequest(page, size)); + } + +} diff --git a/spring-rest-angular/src/main/resources/application.properties b/spring-rest-angular/src/main/resources/application.properties new file mode 100644 index 0000000000..e24db89c8f --- /dev/null +++ b/spring-rest-angular/src/main/resources/application.properties @@ -0,0 +1,4 @@ +server.contextPath=/ +spring.h2.console.enabled=true +logging.level.org.hibernate.SQL=info +spring.jpa.hibernate.ddl-auto=none \ No newline at end of file diff --git a/spring-rest-angular/src/main/resources/db/sql/data.sql b/spring-rest-angular/src/main/resources/db/sql/data.sql new file mode 100644 index 0000000000..418381a681 --- /dev/null +++ b/spring-rest-angular/src/main/resources/db/sql/data.sql @@ -0,0 +1,47 @@ +CREATE TABLE student ( + id INTEGER PRIMARY KEY, + name VARCHAR(30), + gender VARCHAR(10), + age INTEGER +); + +INSERT INTO student (id,name,gender,age) +VALUES (1,'Bryan', 'Male',20); +INSERT INTO student (id,name,gender,age) +VALUES (2, 'Ben', 'Male', 22); +INSERT INTO student (id,name,gender,age) +VALUES (3,'Lisa', 'Female',24); +INSERT INTO student (id,name,gender,age) +VALUES (4,'Sarah', 'Female',20); +INSERT INTO student (id,name,gender,age) +VALUES (5,'Jay', 'Male',20); +INSERT INTO student (id,name,gender,age) +VALUES (6,'John', 'Male',22); +INSERT INTO student (id,name,gender,age) +VALUES (7,'Jordan', 'Male',24); +INSERT INTO student (id,name,gender,age) +VALUES (8,'Rob', 'Male',26); +INSERT INTO student (id,name,gender,age) +VALUES (9,'Will', 'Male',20); +INSERT INTO student (id,name,gender,age) +VALUES (10,'Shawn', 'Male',22); +INSERT INTO student (id,name,gender,age) +VALUES (11,'Taylor', 'Female',24); +INSERT INTO student (id,name,gender,age) +VALUES (12,'Venus', 'Female',26); +INSERT INTO student (id,name,gender,age) +VALUES (13,'Vince', 'Male',20); +INSERT INTO student (id,name,gender,age) +VALUES (14,'Carol', 'Female',22); +INSERT INTO student (id,name,gender,age) +VALUES (15,'Joana', 'Female',24); +INSERT INTO student (id,name,gender,age) +VALUES (16,'Dion', 'Male',26); +INSERT INTO student (id,name,gender,age) +VALUES (17,'Evans', 'Male',20); +INSERT INTO student (id,name,gender,age) +VALUES (18,'Bart', 'Male',22); +INSERT INTO student (id,name,gender,age) +VALUES (19,'Jenny', 'Female',24); +INSERT INTO student (id,name,gender,age) +VALUES (20,'Kristine', 'Female',26); \ No newline at end of file diff --git a/spring-rest-angular/src/main/webapp/WEB-INF/web.xml b/spring-rest-angular/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..6adf31503f --- /dev/null +++ b/spring-rest-angular/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,11 @@ + + + + + index.html + + + \ No newline at end of file diff --git a/spring-rest-angular/src/main/webapp/index.html b/spring-rest-angular/src/main/webapp/index.html new file mode 100644 index 0000000000..49e0d6393d --- /dev/null +++ b/spring-rest-angular/src/main/webapp/index.html @@ -0,0 +1,17 @@ + + + + + + + + + +
    +
    +
    + + \ No newline at end of file diff --git a/spring-rest-angular/src/main/webapp/view/app.js b/spring-rest-angular/src/main/webapp/view/app.js new file mode 100644 index 0000000000..a41026d2c3 --- /dev/null +++ b/spring-rest-angular/src/main/webapp/view/app.js @@ -0,0 +1,56 @@ +var app = angular.module('app', ['ui.grid','ui.grid.pagination']); + +app.controller('StudentCtrl', ['$scope','StudentService', function ($scope,StudentService) { + var paginationOptions = { + pageNumber: 1, + pageSize: 5, + sort: null + }; + + StudentService.getStudents(paginationOptions.pageNumber, + paginationOptions.pageSize).success(function(data){ + $scope.gridOptions.data = data.content; + $scope.gridOptions.totalItems = data.totalElements; + }); + + $scope.gridOptions = { + paginationPageSizes: [5, 10, 20], + paginationPageSize: paginationOptions.pageSize, + enableColumnMenus:false, + useExternalPagination: true, + columnDefs: [ + { name: 'id' }, + { name: 'name' }, + { name: 'gender' }, + { name: 'age' } + ], + onRegisterApi: function(gridApi) { + $scope.gridApi = gridApi; + gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) { + paginationOptions.pageNumber = newPage; + paginationOptions.pageSize = pageSize; + StudentService.getStudents(newPage,pageSize).success(function(data){ + $scope.gridOptions.data = data.content; + $scope.gridOptions.totalItems = data.totalElements; + }); + }); + } + }; + +}]); + +app.service('StudentService',['$http', function ($http) { + + function getStudents(pageNumber,size) { + pageNumber = pageNumber > 0?pageNumber - 1:0; + return $http({ + method: 'GET', + url: 'student/get?page='+pageNumber+'&size='+size + }); + } + + return { + getStudents:getStudents + }; + +}]); \ No newline at end of file diff --git a/spring-rest-angular/src/test/java/org/baeldung/web/service/StudentServiceTest.java b/spring-rest-angular/src/test/java/org/baeldung/web/service/StudentServiceTest.java new file mode 100644 index 0000000000..1199f15ab3 --- /dev/null +++ b/spring-rest-angular/src/test/java/org/baeldung/web/service/StudentServiceTest.java @@ -0,0 +1,65 @@ +package org.baeldung.web.service; + +import org.apache.commons.lang3.RandomStringUtils; +import org.baeldung.web.main.Application; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import static io.restassured.RestAssured.*; +import static org.hamcrest.core.IsCollectionContaining.*; +import static org.hamcrest.core.Is.*; +import static org.hamcrest.core.IsEqual.*; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@IntegrationTest("server.port:8888") +public class StudentServiceTest { + + private static final String ENDPOINT = "http://localhost:8888/student/get"; + + @Test + public void givenRequestForStudents_whenPageIsOne_expectContainsNames() { + given().params("page", "0", "size", "2").get(ENDPOINT).then().assertThat().body("content.name", hasItems("Bryan", "Ben")); + } + + @Test + public void givenRequestForStudents_whenSizeIsTwo_expectTwoItems() { + given().params("page", "0", "size", "2").get(ENDPOINT).then().assertThat().body("size", equalTo(2)); + } + + @Test + public void givenRequestForStudents_whenSizeIsTwo_expectNumberOfElementsTwo() { + given().params("page", "0", "size", "2").get(ENDPOINT).then().assertThat().body("numberOfElements", equalTo(2)); + } + + @Test + public void givenRequestForStudents_whenResourcesAreRetrievedPaged_thenExpect200() { + given().params("page", "0", "size", "2").get(ENDPOINT).then().statusCode(200); + } + + @Test + public void givenRequestForStudents_whenPageOfResourcesAreRetrievedOutOfBounds_thenExpect500() { + given().params("page", "1000", "size", "2").get(ENDPOINT).then().statusCode(500); + } + + @Test + public void givenRequestForStudents_whenPageNotValid_thenExpect500() { + given().params("page", RandomStringUtils.randomNumeric(5), "size", "2").get(ENDPOINT).then().statusCode(500); + } + + @Test + public void givenRequestForStudents_whenPageSizeIsFive_expectFiveItems() { + given().params("page", "0", "size", "5").get(ENDPOINT).then().body("content.size()", is(5)); + } + + @Test + public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources() { + given().params("page", "0", "size", "2").get(ENDPOINT).then().assertThat().body("first", equalTo(true)); + } + +} diff --git a/spring-rest-docs/README.MD b/spring-rest-docs/README.MD new file mode 100644 index 0000000000..2a87b46021 --- /dev/null +++ b/spring-rest-docs/README.MD @@ -0,0 +1,2 @@ +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring diff --git a/spring-rest-docs/pom.xml b/spring-rest-docs/pom.xml new file mode 100644 index 0000000000..04ee11d0de --- /dev/null +++ b/spring-rest-docs/pom.xml @@ -0,0 +1,97 @@ + + + 4.0.0 + + com.example + demo + 0.0.1-SNAPSHOT + jar + + spring-rest-docs + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + UTF-8 + 1.8 + ${project.build.directory}/generated-snippets + + + + + org.springframework.boot + spring-boot-starter-hateoas + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.restdocs + spring-restdocs-mockmvc + 1.0.1.RELEASE + test + + + com.jayway.jsonpath + json-path + 2.0.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*Documentation.java + + + + + org.asciidoctor + asciidoctor-maven-plugin + 1.5.2 + + + generate-docs + package + + process-asciidoc + + + html + book + + ${snippetsDirectory} + + src/docs/asciidocs + target/generated-docs + + + + + + + + + diff --git a/spring-rest-docs/src/docs/asciidocs/api-guide.adoc b/spring-rest-docs/src/docs/asciidocs/api-guide.adoc new file mode 100644 index 0000000000..9fbe74c072 --- /dev/null +++ b/spring-rest-docs/src/docs/asciidocs/api-guide.adoc @@ -0,0 +1,203 @@ += RESTful Notes API Guide +Baeldung; +:doctype: book +:icons: font +:source-highlighter: highlightjs +:toc: left +:toclevels: 4 +:sectlinks: + +[[overview]] += Overview + +[[overview-http-verbs]] +== HTTP verbs + +RESTful notes tries to adhere as closely as possible to standard HTTP and REST conventions in its +use of HTTP verbs. + +|=== +| Verb | Usage + +| `GET` +| Used to retrieve a resource + +| `POST` +| Used to create a new resource + +| `PATCH` +| Used to update an existing resource, including partial updates + +| `DELETE` +| Used to delete an existing resource +|=== + +RESTful notes tries to adhere as closely as possible to standard HTTP and REST conventions in its +use of HTTP status codes. + +|=== +| Status code | Usage + +| `200 OK` +| The request completed successfully + +| `201 Created` +| A new resource has been created successfully. The resource's URI is available from the response's +`Location` header + +| `204 No Content` +| An update to an existing resource has been applied successfully + +| `400 Bad Request` +| The request was malformed. The response body will include an error providing further information + +| `404 Not Found` +| The requested resource did not exist +|=== + +[[overview-headers]] +== Headers + +Every response has the following header(s): + +include::{snippets}/headers-example/response-headers.adoc[] + +[[overview-hypermedia]] +== Hypermedia + +RESTful Notes uses hypermedia and resources include links to other resources in their +responses. Responses are in http://stateless.co/hal_specification.html[Hypertext Application +from resource to resource. +Language (HAL)] format. Links can be found beneath the `_links` key. Users of the API should +not create URIs themselves, instead they should use the above-described links to navigate + +[[resources]] += Resources + + + +[[resources-index]] +== Index + +The index provides the entry point into the service. + +[[resources-index-access]] +=== Accessing the index + +A `GET` request is used to access the index + +==== Response structure + +include::{snippets}/index-example/http-response.adoc[] + +==== Example response + +include::{snippets}/index-example/http-response.adoc[] + +==== Example request + +include::{snippets}/index-example/http-request.adoc[] + +==== CURL request + +include::{snippets}/index-example/curl-request.adoc[] + +[[resources-index-links]] +==== Links + +include::{snippets}/index-example/links.adoc[] + + +[[resources-CRUD]] +== CRUD REST Service + +The CRUD provides the entry point into the service. + +[[resources-crud-access]] +=== Accessing the crud GET + +A `GET` request is used to access the CRUD read + +==== Response structure + +include::{snippets}/crud-get-example/http-request.adoc[] + +==== Example response + +include::{snippets}/crud-get-example/http-response.adoc[] + +==== CURL request + +include::{snippets}/crud-get-example/curl-request.adoc[] + +[[resources-crud-access]] +=== Accessing the crud POST + +A `POST` request is used to access the CRUD create + +==== Response structure + +include::{snippets}/crud-create-example/http-request.adoc[] + +==== Example response + +include::{snippets}/crud-create-example/http-response.adoc[] + +==== CURL request + +include::{snippets}/crud-create-example/curl-request.adoc[] + +[[resources-crud-access]] +=== Accessing the crud DELETE + +A `DELETE` request is used to access the CRUD create + +==== Response structure + +include::{snippets}/crud-delete-example/http-request.adoc[] + +==== Example response + +include::{snippets}/crud-delete-example/http-response.adoc[] + +==== CURL request + +include::{snippets}/crud-delete-example/curl-request.adoc[] + +[[resources-crud-access]] +=== Accessing the crud PATCH + +A `PATCH` request is used to access the CRUD create + +==== Response structure + +include::{snippets}/crud-patch-example/http-request.adoc[] + +==== Example response + +include::{snippets}/crud-patch-example/http-response.adoc[] + +==== CURL request + +include::{snippets}/crud-patch-example/curl-request.adoc[] + +[[resources-crud-access]] +=== Accessing the crud PUT + +A `PUT` request is used to access the CRUD create + +==== Response structure + +include::{snippets}/crud-put-example/http-request.adoc[] + +==== Example response + +include::{snippets}/crud-put-example/http-response.adoc[] + +==== CURL request + +include::{snippets}/crud-put-example/curl-request.adoc[] + + + + diff --git a/spring-rest-docs/src/main/java/com/example/CRUDController.java b/spring-rest-docs/src/main/java/com/example/CRUDController.java new file mode 100644 index 0000000000..ff8c91d6cd --- /dev/null +++ b/spring-rest-docs/src/main/java/com/example/CRUDController.java @@ -0,0 +1,55 @@ +package com.example; + +import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/crud") +public class CRUDController { + + @RequestMapping(method = RequestMethod.GET) + @ResponseStatus(HttpStatus.OK) + public List read(@RequestBody CrudInput crudInput) { + List returnList = new ArrayList(); + returnList.add(crudInput); + return returnList; + } + + @ResponseStatus(HttpStatus.CREATED) + @RequestMapping(method = RequestMethod.POST) + public HttpHeaders save(@RequestBody CrudInput crudInput) { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setLocation(linkTo(CRUDController.class).slash(crudInput.getTitle()).toUri()); + return httpHeaders; + } + + @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) + @ResponseStatus(HttpStatus.OK) + HttpHeaders delete(@RequestBody CrudInput crudInput) { + HttpHeaders httpHeaders = new HttpHeaders(); + return httpHeaders; + } + + @RequestMapping(value = "/{id}", method = RequestMethod.PUT) + @ResponseStatus(HttpStatus.ACCEPTED) + void put(@PathVariable("id") long id, @RequestBody CrudInput crudInput) { + + } + + @RequestMapping(value = "/{id}", method = RequestMethod.PATCH) + @ResponseStatus(HttpStatus.NO_CONTENT) + void patch(@PathVariable("id") long id, @RequestBody CrudInput crudInput) { + + } +} diff --git a/spring-rest-docs/src/main/java/com/example/CrudInput.java b/spring-rest-docs/src/main/java/com/example/CrudInput.java new file mode 100644 index 0000000000..36ad67eb21 --- /dev/null +++ b/spring-rest-docs/src/main/java/com/example/CrudInput.java @@ -0,0 +1,41 @@ +package com.example; + +import java.net.URI; +import java.util.Collections; +import java.util.List; + +import org.hibernate.validator.constraints.NotBlank; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CrudInput { + + // @NotBlank + private final String title; + + private final String body; + + private final List tagUris; + + @JsonCreator + public CrudInput(@JsonProperty("title") String title, @JsonProperty("body") String body, @JsonProperty("tags") List tagUris) { + this.title = title; + this.body = body; + this.tagUris = tagUris == null ? Collections. emptyList() : tagUris; + } + + public String getTitle() { + return title; + } + + public String getBody() { + return body; + } + + @JsonProperty("tags") + public List getTagUris() { + return this.tagUris; + } + +} \ No newline at end of file diff --git a/spring-rest-docs/src/main/java/com/example/IndexController.java b/spring-rest-docs/src/main/java/com/example/IndexController.java new file mode 100644 index 0000000000..6b896da416 --- /dev/null +++ b/spring-rest-docs/src/main/java/com/example/IndexController.java @@ -0,0 +1,21 @@ +package com.example; + +import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; + +import org.springframework.hateoas.ResourceSupport; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/") +public class IndexController { + + @RequestMapping(method = RequestMethod.GET) + public ResourceSupport index() { + ResourceSupport index = new ResourceSupport(); + index.add(linkTo(CRUDController.class).withRel("crud")); + return index; + } + +} \ No newline at end of file diff --git a/spring-rest-docs/src/main/java/com/example/SpringRestDocsApplication.java b/spring-rest-docs/src/main/java/com/example/SpringRestDocsApplication.java new file mode 100644 index 0000000000..da09f9accc --- /dev/null +++ b/spring-rest-docs/src/main/java/com/example/SpringRestDocsApplication.java @@ -0,0 +1,12 @@ +package com.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringRestDocsApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringRestDocsApplication.class, args); + } +} diff --git a/spring-rest-docs/src/main/resources/application.properties b/spring-rest-docs/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-rest-docs/src/test/java/com/example/ApiDocumentation.java b/spring-rest-docs/src/test/java/com/example/ApiDocumentation.java new file mode 100644 index 0000000000..5b753aff0c --- /dev/null +++ b/spring-rest-docs/src/test/java/com/example/ApiDocumentation.java @@ -0,0 +1,172 @@ +package com.example; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.hateoas.MediaTypes; +import org.springframework.restdocs.RestDocumentation; +import org.springframework.restdocs.constraints.ConstraintDescriptions; +import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; +import org.springframework.restdocs.payload.FieldDescriptor; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import java.util.HashMap; +import java.util.Map; + +import static java.util.Collections.singletonList; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.responseHeaders; +import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel; +import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; +import static org.springframework.restdocs.snippet.Attributes.key; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.util.StringUtils.collectionToDelimitedString; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SpringRestDocsApplication.class) +@WebAppConfiguration +public class ApiDocumentation { + + @Rule + public final RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets"); + + @Autowired + private WebApplicationContext context; + + @Autowired + private ObjectMapper objectMapper; + + private RestDocumentationResultHandler document; + + private MockMvc mockMvc; + + @Before + public void setUp() { + this.document = document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())); + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).apply(documentationConfiguration(this.restDocumentation)).alwaysDo(this.document).build(); + } + + @Test + public void headersExample() throws Exception { + this.document.snippets(responseHeaders(headerWithName("Content-Type").description("The Content-Type of the payload, e.g. `application/hal+json`"))); + this.mockMvc.perform(get("/")).andExpect(status().isOk()); + } + + @Test + public void indexExample() throws Exception { + this.document.snippets(links(linkWithRel("crud").description("The <>")), responseFields(fieldWithPath("_links").description("<> to other resources"))); + this.mockMvc.perform(get("/")).andExpect(status().isOk()); + } + + @Test + public void crudGetExample() throws Exception { + + Map tag = new HashMap<>(); + tag.put("name", "GET"); + + String tagLocation = this.mockMvc.perform(get("/crud").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(tag))).andExpect(status().isOk()).andReturn().getResponse().getHeader("Location"); + + Map crud = new HashMap<>(); + crud.put("title", "Sample Model"); + crud.put("body", "http://www.baeldung.com/"); + crud.put("tags", singletonList(tagLocation)); + + this.mockMvc.perform(get("/crud").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(crud))).andExpect(status().isOk()); + } + + @Test + public void crudCreateExample() throws Exception { + Map tag = new HashMap<>(); + tag.put("name", "CREATE"); + + String tagLocation = this.mockMvc.perform(post("/crud").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(tag))).andExpect(status().isCreated()).andReturn().getResponse().getHeader("Location"); + + Map crud = new HashMap<>(); + crud.put("title", "Sample Model"); + crud.put("body", "http://www.baeldung.com/"); + crud.put("tags", singletonList(tagLocation)); + + ConstrainedFields fields = new ConstrainedFields(CrudInput.class); + this.document.snippets(requestFields(fields.withPath("title").description("The title of the note"), fields.withPath("body").description("The body of the note"), fields.withPath("tags").description("An array of tag resource URIs"))); + this.mockMvc.perform(post("/crud").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(crud))).andExpect(status().isCreated()); + + } + + @Test + public void crudDeleteExample() throws Exception { + + Map tag = new HashMap<>(); + tag.put("name", "DELETE"); + + String tagLocation = this.mockMvc.perform(delete("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(tag))).andExpect(status().isOk()).andReturn().getResponse().getHeader("Location"); + + Map crud = new HashMap<>(); + crud.put("title", "Sample Model"); + crud.put("body", "http://www.baeldung.com/"); + crud.put("tags", singletonList(tagLocation)); + + this.mockMvc.perform(delete("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(crud))).andExpect(status().isOk()); + } + + @Test + public void crudPatchExample() throws Exception { + + Map tag = new HashMap<>(); + tag.put("name", "PATCH"); + + String tagLocation = this.mockMvc.perform(patch("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(tag))).andExpect(status().isNoContent()).andReturn().getResponse().getHeader("Location"); + + Map crud = new HashMap<>(); + crud.put("title", "Sample Model"); + crud.put("body", "http://www.baeldung.com/"); + crud.put("tags", singletonList(tagLocation)); + + this.mockMvc.perform(patch("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(crud))).andExpect(status().isNoContent()); + } + + @Test + public void crudPutExample() throws Exception { + Map tag = new HashMap<>(); + tag.put("name", "PUT"); + + String tagLocation = this.mockMvc.perform(put("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(tag))).andExpect(status().isAccepted()).andReturn().getResponse().getHeader("Location"); + + Map crud = new HashMap<>(); + crud.put("title", "Sample Model"); + crud.put("body", "http://www.baeldung.com/"); + crud.put("tags", singletonList(tagLocation)); + + this.mockMvc.perform(put("/crud/10").contentType(MediaTypes.HAL_JSON).content(this.objectMapper.writeValueAsString(crud))).andExpect(status().isAccepted()); + } + + @Test + public void contextLoads() { + } + + private static class ConstrainedFields { + + private final ConstraintDescriptions constraintDescriptions; + + ConstrainedFields(Class input) { + this.constraintDescriptions = new ConstraintDescriptions(input); + } + + private FieldDescriptor withPath(String path) { + return fieldWithPath(path).attributes(key("constraints").value(collectionToDelimitedString(this.constraintDescriptions.descriptionsForProperty(path), ". "))); + } + } + +} diff --git a/spring-rest-docs/src/test/java/com/example/GettingStartedDocumentation.java b/spring-rest-docs/src/test/java/com/example/GettingStartedDocumentation.java new file mode 100644 index 0000000000..7aea9d303c --- /dev/null +++ b/spring-rest-docs/src/test/java/com/example/GettingStartedDocumentation.java @@ -0,0 +1,150 @@ +package com.example; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jayway.jsonpath.JsonPath; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.hateoas.MediaTypes; +import org.springframework.restdocs.RestDocumentation; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.Matchers.*; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SpringRestDocsApplication.class) +@WebAppConfiguration +public class GettingStartedDocumentation { + + @Rule + public final RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets"); + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private WebApplicationContext context; + + private MockMvc mockMvc; + + @Before + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).apply(documentationConfiguration(this.restDocumentation)).alwaysDo(document("{method-name}/{step}/", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()))).build(); + } + + @Test + public void index() throws Exception { + this.mockMvc.perform(get("/").accept(MediaTypes.HAL_JSON)).andExpect(status().isOk()).andExpect(jsonPath("_links.crud", is(notNullValue()))).andExpect(jsonPath("_links.crud", is(notNullValue()))); + } + + // String createNote() throws Exception { + // Map note = new HashMap(); + // note.put("title", "Note creation with cURL"); + // note.put("body", "An example of how to create a note using curl"); + // String noteLocation = this.mockMvc.perform(post("/crud") + // .contentType(MediaTypes.HAL_JSON) + // .content(objectMapper.writeValueAsString(note))) + // .andExpect(status().isCreated()) + // .andExpect(header().string("Location", notNullValue())) + // .andReturn() + // .getResponse() + // .getHeader("Location"); + // return noteLocation; + // } + // + // MvcResult getNote(String noteLocation) throws Exception { + // return this.mockMvc.perform(get(noteLocation)) + // .andExpect(status().isOk()) + // .andExpect(jsonPath("title", is(notNullValue()))) + // .andExpect(jsonPath("body", is(notNullValue()))) + // .andExpect(jsonPath("_links.crud", is(notNullValue()))) + // .andReturn(); + // } + // + // + // String createTag() throws Exception, JsonProcessingException { + // Map tag = new HashMap(); + // tag.put("name", "getting-started"); + // String tagLocation = this.mockMvc.perform(post("/crud") + // .contentType(MediaTypes.HAL_JSON) + // .content(objectMapper.writeValueAsString(tag))) + // .andExpect(status().isCreated()) + // .andExpect(header().string("Location", notNullValue())) + // .andReturn() + // .getResponse() + // .getHeader("Location"); + // return tagLocation; + // } + // + // void getTag(String tagLocation) throws Exception { + // this.mockMvc.perform(get(tagLocation)).andExpect(status().isOk()) + // .andExpect(jsonPath("name", is(notNullValue()))) + // .andExpect(jsonPath("_links.tagged-notes", is(notNullValue()))); + // } + // + // String createTaggedNote(String tag) throws Exception { + // Map note = new HashMap(); + // note.put("title", "Tagged note creation with cURL"); + // note.put("body", "An example of how to create a tagged note using cURL"); + // note.put("tags", Arrays.asList(tag)); + // + // String noteLocation = this.mockMvc.perform(post("/notes") + // .contentType(MediaTypes.HAL_JSON) + // .content(objectMapper.writeValueAsString(note))) + // .andExpect(status().isCreated()) + // .andExpect(header().string("Location", notNullValue())) + // .andReturn() + // .getResponse() + // .getHeader("Location"); + // return noteLocation; + // } + // + // void getTags(String noteTagsLocation) throws Exception { + // this.mockMvc.perform(get(noteTagsLocation)) + // .andExpect(status().isOk()) + // .andExpect(jsonPath("_embedded.tags", hasSize(1))); + // } + // + // void tagExistingNote(String noteLocation, String tagLocation) throws Exception { + // Map update = new HashMap(); + // update.put("tags", Arrays.asList(tagLocation)); + // this.mockMvc.perform(patch(noteLocation) + // .contentType(MediaTypes.HAL_JSON) + // .content(objectMapper.writeValueAsString(update))) + // .andExpect(status().isNoContent()); + // } + // + // MvcResult getTaggedExistingNote(String noteLocation) throws Exception { + // return this.mockMvc.perform(get(noteLocation)).andExpect(status().isOk()).andReturn(); + // } + // + // void getTagsForExistingNote(String noteTagsLocation) throws Exception { + // this.mockMvc.perform(get(noteTagsLocation)) + // .andExpect(status().isOk()).andExpect(jsonPath("_embedded.tags", hasSize(1))); + // } + // + // private String getLink(MvcResult result, String rel) + // throws UnsupportedEncodingException { + // return JsonPath.parse(result.getResponse().getContentAsString()).read("_links." + rel + ".href"); + // } + +} diff --git a/spring-rest/.classpath b/spring-rest/.classpath deleted file mode 100644 index 6b533711d3..0000000000 --- a/spring-rest/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-rest/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-rest/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-rest/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-rest/.project b/spring-rest/.project deleted file mode 100644 index 894841d690..0000000000 --- a/spring-rest/.project +++ /dev/null @@ -1,43 +0,0 @@ - - - spring-rest - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-rest/.settings/.jsdtscope b/spring-rest/.settings/.jsdtscope deleted file mode 100644 index b46b9207a8..0000000000 --- a/spring-rest/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-rest/.settings/org.eclipse.jdt.core.prefs b/spring-rest/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/spring-rest/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-rest/.settings/org.eclipse.jdt.ui.prefs b/spring-rest/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-rest/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-rest/.settings/org.eclipse.m2e.core.prefs b/spring-rest/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-rest/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-rest/.settings/org.eclipse.m2e.wtp.prefs b/spring-rest/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-rest/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-rest/.settings/org.eclipse.wst.common.component b/spring-rest/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 8bb4ef127a..0000000000 --- a/spring-rest/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-rest/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-rest/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index b9386231e6..0000000000 --- a/spring-rest/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/spring-rest/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-rest/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-rest/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-rest/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-rest/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-rest/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-rest/.settings/org.eclipse.wst.validation.prefs b/spring-rest/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-rest/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-rest/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-rest/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-rest/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-rest/.springBeans b/spring-rest/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/spring-rest/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/spring-rest/README.md b/spring-rest/README.md index 3b93b06d66..7d993b38b8 100644 --- a/spring-rest/README.md +++ b/spring-rest/README.md @@ -2,8 +2,11 @@ ## Spring REST Example Project +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Spring @RequestMapping](http://www.baeldung.com/spring-requestmapping) - [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) - [Redirect in Spring](http://www.baeldung.com/spring-redirect-and-forward) +- [Returning Custom Status Codes from Spring Controllers](http://www.baeldung.com/spring-mvc-controller-custom-http-status-code) diff --git a/spring-rest/pom.xml b/spring-rest/pom.xml index e2cf9d7c3e..18cb1dc72a 100644 --- a/spring-rest/pom.xml +++ b/spring-rest/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-rest 0.1-SNAPSHOT spring-rest @@ -9,16 +9,13 @@ org.springframework.boot spring-boot-starter-parent - 1.2.4.RELEASE + 1.3.5.RELEASE - - org.springframework.boot - spring-boot-starter-security - + org.springframework.boot spring-boot-starter-thymeleaf @@ -33,7 +30,6 @@ org.springframework spring-web - ${org.springframework.version} commons-logging @@ -44,12 +40,10 @@ org.springframework spring-webmvc - ${org.springframework.version} org.springframework spring-oxm - ${org.springframework.version} @@ -62,7 +56,6 @@ javax.servlet javax.servlet-api - 3.0.1 provided @@ -78,6 +71,11 @@ com.fasterxml.jackson.core jackson-databind + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + com.thoughtworks.xstream @@ -104,24 +102,20 @@ org.slf4j slf4j-api - ${org.slf4j.version} ch.qos.logback logback-classic - ${logback.version} org.slf4j jcl-over-slf4j - ${org.slf4j.version} org.slf4j log4j-over-slf4j - ${org.slf4j.version} @@ -129,36 +123,49 @@ junit junit - ${junit.version} test org.hamcrest hamcrest-core - ${org.hamcrest.version} test org.hamcrest hamcrest-library - ${org.hamcrest.version} test org.mockito mockito-core - ${mockito.version} test org.springframework spring-test - ${spring.version} + + com.jayway.restassured + rest-assured + ${rest-assured.version} + + + + + com.google.protobuf + protobuf-java + 2.6.1 + + + + com.esotericsoftware + kryo + 4.0.0 + @@ -175,7 +182,6 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.version} 1.8 1.8 @@ -185,16 +191,14 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} - + **/*LiveTest.java @@ -209,7 +213,7 @@ true - jetty8x + tomcat8x embedded @@ -227,18 +231,67 @@ + + + live + + + + org.codehaus.cargo + cargo-maven2-plugin + + + start-server + pre-integration-test + + start + + + + stop-server + post-integration-test + + stop + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + none + + + **/*LiveTest.java + + + cargo + + + + + + + + + + + - 4.2.4.RELEASE - 4.0.3.RELEASE 4.3.11.Final - 5.1.37 - - - - 2.5.5 + 5.1.39 5.2.2.Final @@ -255,18 +308,18 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 1.7.13 1.1.3 - 3.3 + 3.5.1 2.6 - 2.18.1 - 1.4.15 + 2.19.1 + 1.6.0 - \ No newline at end of file +
    diff --git a/spring-rest/src/main/java/org/baeldung/config/WebConfig.java b/spring-rest/src/main/java/org/baeldung/config/WebConfig.java index 999f890ebb..d116148f09 100644 --- a/spring-rest/src/main/java/org/baeldung/config/WebConfig.java +++ b/spring-rest/src/main/java/org/baeldung/config/WebConfig.java @@ -1,50 +1,58 @@ -package org.baeldung.config; - -import java.text.SimpleDateFormat; -import java.util.List; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; -import org.springframework.oxm.xstream.XStreamMarshaller; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; - -@Configuration -@EnableWebMvc -@ComponentScan({ "org.baeldung.web" }) -public class WebConfig extends WebMvcConfigurerAdapter { - - public WebConfig() { - super(); - } - - // - - @Override - public void configureMessageConverters(final List> messageConverters) { - messageConverters.add(createXmlHttpMessageConverter()); - // messageConverters.add(new MappingJackson2HttpMessageConverter()); - - final Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); - builder.indentOutput(true).dateFormat(new SimpleDateFormat("dd-MM-yyyy hh:mm")); - messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build())); - // messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); - - super.configureMessageConverters(messageConverters); - } - - private HttpMessageConverter createXmlHttpMessageConverter() { - final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); - - final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); - xmlConverter.setMarshaller(xstreamMarshaller); - xmlConverter.setUnmarshaller(xstreamMarshaller); - - return xmlConverter; - } - -} +package org.baeldung.config; + +import java.text.SimpleDateFormat; +import java.util.List; + +import org.baeldung.config.converter.KryoHttpMessageConverter; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter; +import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; +import org.springframework.oxm.xstream.XStreamMarshaller; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +/* + * Please note that main web configuration is in src/main/webapp/WEB-INF/api-servlet.xml + * + */ + +@Configuration +@EnableWebMvc +@ComponentScan({ "org.baeldung.web" }) +public class WebConfig extends WebMvcConfigurerAdapter { + + public WebConfig() { + super(); + } + + // + + @Override + public void configureMessageConverters(final List> messageConverters) { + messageConverters.add(createXmlHttpMessageConverter()); + // messageConverters.add(new MappingJackson2HttpMessageConverter()); + + final Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); + builder.indentOutput(true).dateFormat(new SimpleDateFormat("dd-MM-yyyy hh:mm")); + messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build())); + // messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); + messageConverters.add(new ProtobufHttpMessageConverter()); + messageConverters.add(new KryoHttpMessageConverter()); + super.configureMessageConverters(messageConverters); + } + + private HttpMessageConverter createXmlHttpMessageConverter() { + final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); + + final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); + xmlConverter.setMarshaller(xstreamMarshaller); + xmlConverter.setUnmarshaller(xstreamMarshaller); + + return xmlConverter; + } + +} diff --git a/spring-rest/src/main/java/org/baeldung/config/converter/KryoHttpMessageConverter.java b/spring-rest/src/main/java/org/baeldung/config/converter/KryoHttpMessageConverter.java new file mode 100644 index 0000000000..7e63a3ba9e --- /dev/null +++ b/spring-rest/src/main/java/org/baeldung/config/converter/KryoHttpMessageConverter.java @@ -0,0 +1,57 @@ +package org.baeldung.config.converter; + +import java.io.IOException; + +import org.baeldung.web.dto.Foo; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; +import org.springframework.http.converter.AbstractHttpMessageConverter; + +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + +/** + * An {@code HttpMessageConverter} that can read and write Kryo messages. + */ +public class KryoHttpMessageConverter extends AbstractHttpMessageConverter { + + public static final MediaType KRYO = new MediaType("application", "x-kryo"); + + private static final ThreadLocal kryoThreadLocal = new ThreadLocal() { + @Override + protected Kryo initialValue() { + final Kryo kryo = new Kryo(); + kryo.register(Foo.class, 1); + return kryo; + } + }; + + public KryoHttpMessageConverter() { + super(KRYO); + } + + @Override + protected boolean supports(final Class clazz) { + return Object.class.isAssignableFrom(clazz); + } + + @Override + protected Object readInternal(final Class clazz, final HttpInputMessage inputMessage) throws IOException { + final Input input = new Input(inputMessage.getBody()); + return kryoThreadLocal.get().readClassAndObject(input); + } + + @Override + protected void writeInternal(final Object object, final HttpOutputMessage outputMessage) throws IOException { + final Output output = new Output(outputMessage.getBody()); + kryoThreadLocal.get().writeClassAndObject(output, object); + output.flush(); + } + + @Override + protected MediaType getDefaultContentType(final Object object) { + return KRYO; + } +} diff --git a/spring-rest/src/main/java/org/baeldung/web/controller/CompanyController.java b/spring-rest/src/main/java/org/baeldung/web/controller/CompanyController.java new file mode 100644 index 0000000000..d640ac671d --- /dev/null +++ b/spring-rest/src/main/java/org/baeldung/web/controller/CompanyController.java @@ -0,0 +1,16 @@ +package org.baeldung.web.controller; + +import org.baeldung.web.dto.Company; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class CompanyController { + + @RequestMapping(value = "/companyRest", produces = MediaType.APPLICATION_JSON_VALUE) + public Company getCompanyRest() { + final Company company = new Company(1, "Xpto"); + return company; + } +} diff --git a/spring-rest/src/main/java/org/baeldung/web/controller/FooController.java b/spring-rest/src/main/java/org/baeldung/web/controller/FooController.java index ed6b150403..dd1e3ca222 100644 --- a/spring-rest/src/main/java/org/baeldung/web/controller/FooController.java +++ b/spring-rest/src/main/java/org/baeldung/web/controller/FooController.java @@ -4,6 +4,7 @@ import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; import org.baeldung.web.dto.Foo; +import org.baeldung.web.dto.FooProtos; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; @@ -34,8 +35,12 @@ public class FooController { @ResponseStatus(HttpStatus.OK) @ResponseBody public Foo updateFoo(@PathVariable("id") final String id, @RequestBody final Foo foo) { - System.out.println(foo); return foo; } + @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}", produces = { "application/x-protobuf" }) + @ResponseBody + public FooProtos.Foo findProtoById(@PathVariable final long id) { + return FooProtos.Foo.newBuilder().setId(1).setName("Foo Name").build(); + } } diff --git a/spring-rest/src/main/java/org/baeldung/web/controller/advice/JsonpControllerAdvice.java b/spring-rest/src/main/java/org/baeldung/web/controller/advice/JsonpControllerAdvice.java new file mode 100644 index 0000000000..7d62cc0c66 --- /dev/null +++ b/spring-rest/src/main/java/org/baeldung/web/controller/advice/JsonpControllerAdvice.java @@ -0,0 +1,13 @@ +package org.baeldung.web.controller.advice; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice; + +@ControllerAdvice +public class JsonpControllerAdvice extends AbstractJsonpResponseBodyAdvice { + + public JsonpControllerAdvice() { + super("callback"); + } + +} diff --git a/spring-rest/src/main/java/org/baeldung/web/controller/status/ExampleController.java b/spring-rest/src/main/java/org/baeldung/web/controller/status/ExampleController.java new file mode 100644 index 0000000000..ceda138768 --- /dev/null +++ b/spring-rest/src/main/java/org/baeldung/web/controller/status/ExampleController.java @@ -0,0 +1,24 @@ +package org.baeldung.web.controller.status; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class ExampleController { + + @RequestMapping(value = "/controller", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity sendViaResponseEntity() { + return new ResponseEntity(HttpStatus.NOT_ACCEPTABLE); + } + + @RequestMapping(value = "/exception", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity sendViaException() { + throw new ForbiddenException(); + } +} diff --git a/spring-rest/src/main/java/org/baeldung/web/controller/status/ForbiddenException.java b/spring-rest/src/main/java/org/baeldung/web/controller/status/ForbiddenException.java new file mode 100644 index 0000000000..348ee6d596 --- /dev/null +++ b/spring-rest/src/main/java/org/baeldung/web/controller/status/ForbiddenException.java @@ -0,0 +1,10 @@ +package org.baeldung.web.controller.status; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.FORBIDDEN, reason="To show an example of a custom message") +public class ForbiddenException extends RuntimeException { + private static final long serialVersionUID = 6826605655586311552L; + +} diff --git a/spring-rest/src/main/java/org/baeldung/web/dto/Company.java b/spring-rest/src/main/java/org/baeldung/web/dto/Company.java new file mode 100644 index 0000000000..c7d0718140 --- /dev/null +++ b/spring-rest/src/main/java/org/baeldung/web/dto/Company.java @@ -0,0 +1,38 @@ +package org.baeldung.web.dto; + +public class Company { + + private long id; + private String name; + + public Company() { + super(); + } + + public Company(final long id, final String name) { + this.id = id; + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + @Override + public String toString() { + return "Company [id=" + id + ", name=" + name + "]"; + } + +} diff --git a/spring-rest/src/main/java/org/baeldung/web/dto/FooProtos.java b/spring-rest/src/main/java/org/baeldung/web/dto/FooProtos.java new file mode 100644 index 0000000000..61251ea33a --- /dev/null +++ b/spring-rest/src/main/java/org/baeldung/web/dto/FooProtos.java @@ -0,0 +1,620 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: FooProtos.proto + +package org.baeldung.web.dto; + +public final class FooProtos { + private FooProtos() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + } + public interface FooOrBuilder extends + // @@protoc_insertion_point(interface_extends:baeldung.Foo) + com.google.protobuf.MessageOrBuilder { + + /** + * required int64 id = 1; + */ + boolean hasId(); + /** + * required int64 id = 1; + */ + long getId(); + + /** + * required string name = 2; + */ + boolean hasName(); + /** + * required string name = 2; + */ + java.lang.String getName(); + /** + * required string name = 2; + */ + com.google.protobuf.ByteString + getNameBytes(); + } + /** + * Protobuf type {@code baeldung.Foo} + */ + public static final class Foo extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:baeldung.Foo) + FooOrBuilder { + // Use Foo.newBuilder() to construct. + private Foo(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private Foo(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } + + private static final Foo defaultInstance; + public static Foo getDefaultInstance() { + return defaultInstance; + } + + public Foo getDefaultInstanceForType() { + return defaultInstance; + } + + private final com.google.protobuf.UnknownFieldSet unknownFields; + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Foo( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 8: { + bitField0_ |= 0x00000001; + id_ = input.readInt64(); + break; + } + case 18: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000002; + name_ = bs; + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.baeldung.web.dto.FooProtos.internal_static_baeldung_Foo_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.baeldung.web.dto.FooProtos.internal_static_baeldung_Foo_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.baeldung.web.dto.FooProtos.Foo.class, org.baeldung.web.dto.FooProtos.Foo.Builder.class); + } + + public static com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + public Foo parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Foo(input, extensionRegistry); + } + }; + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + public static final int ID_FIELD_NUMBER = 1; + private long id_; + /** + * required int64 id = 1; + */ + public boolean hasId() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required int64 id = 1; + */ + public long getId() { + return id_; + } + + public static final int NAME_FIELD_NUMBER = 2; + private java.lang.Object name_; + /** + * required string name = 2; + */ + public boolean hasName() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * required string name = 2; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + name_ = s; + } + return s; + } + } + /** + * required string name = 2; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private void initFields() { + id_ = 0L; + name_ = ""; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + if (!hasId()) { + memoizedIsInitialized = 0; + return false; + } + if (!hasName()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeInt64(1, id_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeBytes(2, getNameBytes()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, id_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(2, getNameBytes()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static org.baeldung.web.dto.FooProtos.Foo parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.baeldung.web.dto.FooProtos.Foo parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.baeldung.web.dto.FooProtos.Foo parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.baeldung.web.dto.FooProtos.Foo parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.baeldung.web.dto.FooProtos.Foo parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.baeldung.web.dto.FooProtos.Foo parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.baeldung.web.dto.FooProtos.Foo parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.baeldung.web.dto.FooProtos.Foo parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.baeldung.web.dto.FooProtos.Foo parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.baeldung.web.dto.FooProtos.Foo parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.baeldung.web.dto.FooProtos.Foo prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code baeldung.Foo} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:baeldung.Foo) + org.baeldung.web.dto.FooProtos.FooOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.baeldung.web.dto.FooProtos.internal_static_baeldung_Foo_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.baeldung.web.dto.FooProtos.internal_static_baeldung_Foo_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.baeldung.web.dto.FooProtos.Foo.class, org.baeldung.web.dto.FooProtos.Foo.Builder.class); + } + + // Construct using org.baeldung.web.dto.FooProtos.Foo.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + id_ = 0L; + bitField0_ = (bitField0_ & ~0x00000001); + name_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.baeldung.web.dto.FooProtos.internal_static_baeldung_Foo_descriptor; + } + + public org.baeldung.web.dto.FooProtos.Foo getDefaultInstanceForType() { + return org.baeldung.web.dto.FooProtos.Foo.getDefaultInstance(); + } + + public org.baeldung.web.dto.FooProtos.Foo build() { + org.baeldung.web.dto.FooProtos.Foo result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.baeldung.web.dto.FooProtos.Foo buildPartial() { + org.baeldung.web.dto.FooProtos.Foo result = new org.baeldung.web.dto.FooProtos.Foo(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.id_ = id_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.name_ = name_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.baeldung.web.dto.FooProtos.Foo) { + return mergeFrom((org.baeldung.web.dto.FooProtos.Foo)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.baeldung.web.dto.FooProtos.Foo other) { + if (other == org.baeldung.web.dto.FooProtos.Foo.getDefaultInstance()) return this; + if (other.hasId()) { + setId(other.getId()); + } + if (other.hasName()) { + bitField0_ |= 0x00000002; + name_ = other.name_; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public final boolean isInitialized() { + if (!hasId()) { + + return false; + } + if (!hasName()) { + + return false; + } + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.baeldung.web.dto.FooProtos.Foo parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.baeldung.web.dto.FooProtos.Foo) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private long id_ ; + /** + * required int64 id = 1; + */ + public boolean hasId() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required int64 id = 1; + */ + public long getId() { + return id_; + } + /** + * required int64 id = 1; + */ + public Builder setId(long value) { + bitField0_ |= 0x00000001; + id_ = value; + onChanged(); + return this; + } + /** + * required int64 id = 1; + */ + public Builder clearId() { + bitField0_ = (bitField0_ & ~0x00000001); + id_ = 0L; + onChanged(); + return this; + } + + private java.lang.Object name_ = ""; + /** + * required string name = 2; + */ + public boolean hasName() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * required string name = 2; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + name_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * required string name = 2; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * required string name = 2; + */ + public Builder setName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + name_ = value; + onChanged(); + return this; + } + /** + * required string name = 2; + */ + public Builder clearName() { + bitField0_ = (bitField0_ & ~0x00000002); + name_ = getDefaultInstance().getName(); + onChanged(); + return this; + } + /** + * required string name = 2; + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + name_ = value; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:baeldung.Foo) + } + + static { + defaultInstance = new Foo(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:baeldung.Foo) + } + + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_baeldung_Foo_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_baeldung_Foo_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\017FooProtos.proto\022\010baeldung\"\037\n\003Foo\022\n\n\002id" + + "\030\001 \002(\003\022\014\n\004name\030\002 \002(\tB!\n\024org.baeldung.web" + + ".dtoB\tFooProtos" + }; + com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = + new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { + public com.google.protobuf.ExtensionRegistry assignDescriptors( + com.google.protobuf.Descriptors.FileDescriptor root) { + descriptor = root; + return null; + } + }; + com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }, assigner); + internal_static_baeldung_Foo_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_baeldung_Foo_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_baeldung_Foo_descriptor, + new java.lang.String[] { "Id", "Name", }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml b/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml index 5afc637ece..21136b62c6 100644 --- a/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml +++ b/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml @@ -8,7 +8,24 @@ - + + + + + + + + + + + diff --git a/spring-rest/src/main/webapp/WEB-INF/company.html b/spring-rest/src/main/webapp/WEB-INF/company.html new file mode 100644 index 0000000000..d2072bfd3c --- /dev/null +++ b/spring-rest/src/main/webapp/WEB-INF/company.html @@ -0,0 +1,44 @@ + + + + + Company Data + + + + + + + +
    + + + \ No newline at end of file diff --git a/spring-rest/src/main/webapp/WEB-INF/web.xml b/spring-rest/src/main/webapp/WEB-INF/web.xml index 01e7620c44..a439de8a05 100644 --- a/spring-rest/src/main/webapp/WEB-INF/web.xml +++ b/spring-rest/src/main/webapp/WEB-INF/web.xml @@ -8,7 +8,7 @@ Spring MVC Application - + contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext @@ -18,7 +18,7 @@ contextConfigLocation org.baeldung.config - + org.springframework.web.context.ContextLoaderListener diff --git a/spring-rest/src/test/java/org/baeldung/web/controller/status/ExampleControllerTest.java b/spring-rest/src/test/java/org/baeldung/web/controller/status/ExampleControllerTest.java new file mode 100644 index 0000000000..1344d2d40e --- /dev/null +++ b/spring-rest/src/test/java/org/baeldung/web/controller/status/ExampleControllerTest.java @@ -0,0 +1,44 @@ +package org.baeldung.web.controller.status; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.baeldung.config.WebConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = WebConfig.class) +@WebAppConfiguration +public class ExampleControllerTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext webApplicationContext; + + @Before + public void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + } + + @Test + public void whenGetRequestSentToController_thenReturnsStatusNotAcceptable() throws Exception { + mockMvc.perform(get("/controller")) + .andExpect(status().isNotAcceptable()); + } + + @Test + public void whenGetRequestSentToException_thenReturnsStatusForbidden() throws Exception { + mockMvc.perform(get("/exception")) + .andExpect(status().isForbidden()); + } +} diff --git a/spring-rest/src/test/java/org/baeldung/web/test/RequestMappingLiveTest.java b/spring-rest/src/test/java/org/baeldung/web/test/RequestMappingLiveTest.java new file mode 100644 index 0000000000..3155b5cda9 --- /dev/null +++ b/spring-rest/src/test/java/org/baeldung/web/test/RequestMappingLiveTest.java @@ -0,0 +1,62 @@ +package org.baeldung.web.test; + +import static org.hamcrest.Matchers.equalTo; + +import org.junit.Test; + +import com.jayway.restassured.RestAssured; + +public class RequestMappingLiveTest { + private static String BASE_URI = "http://localhost:8082/spring-rest/ex/"; + + @Test + public void givenSimplePath_whenGetFoos_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "foos").then().assertThat().body(equalTo("Simple Get some Foos")); + } + + @Test + public void whenPostFoos_thenOk() { + RestAssured.given().accept("text/html").post(BASE_URI + "foos").then().assertThat().body(equalTo("Post some Foos")); + } + + @Test + public void givenOneHeader_whenGetFoos_thenOk() { + RestAssured.given().accept("text/html").header("key", "val").get(BASE_URI + "foos").then().assertThat().body(equalTo("Get some Foos with Header")); + } + + @Test + public void givenMultipleHeaders_whenGetFoos_thenOk() { + RestAssured.given().accept("text/html").headers("key1", "val1", "key2", "val2").get(BASE_URI + "foos").then().assertThat().body(equalTo("Get some Foos with Header")); + } + + @Test + public void givenAcceptHeader_whenGetFoos_thenOk() { + RestAssured.given().accept("application/json").get(BASE_URI + "foos").then().assertThat().body(equalTo("Get some Foos with Header New")); + } + + @Test + public void givenPathVariable_whenGetFoos_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "foos/1").then().assertThat().body(equalTo("Get a specific Foo with id=1")); + } + + @Test + public void givenMultiplePathVariable_whenGetFoos_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "foos/1/bar/2").then().assertThat().body(equalTo("Get a specific Bar with id=2 from a Foo with id=1")); + } + + @Test + public void givenPathVariable_whenGetBars_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "bars/1").then().assertThat().body(equalTo("Get a specific Bar with id=1")); + } + + @Test + public void givenParams_whenGetBars_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "bars?id=100&second=something").then().assertThat().body(equalTo("Get a specific Bar with id=100")); + } + + @Test + public void whenGetFoosOrBars_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "advanced/foos").then().assertThat().body(equalTo("Advanced - Get some Foos or Bars")); + RestAssured.given().accept("text/html").get(BASE_URI + "advanced/bars").then().assertThat().body(equalTo("Advanced - Get some Foos or Bars")); + } +} diff --git a/spring-rest/src/test/java/org/baeldung/web/test/SpringHttpMessageConvertersIntegrationTestsCase.java b/spring-rest/src/test/java/org/baeldung/web/test/SpringHttpMessageConvertersIntegrationTestsCase.java deleted file mode 100644 index c21641ca22..0000000000 --- a/spring-rest/src/test/java/org/baeldung/web/test/SpringHttpMessageConvertersIntegrationTestsCase.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.baeldung.web.test; - -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.baeldung.web.dto.Foo; -import org.junit.Assert; -import org.junit.Test; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; -import org.springframework.oxm.xstream.XStreamMarshaller; -import org.springframework.web.client.RestTemplate; - -/** - * Integration Test class. Tests methods hits the server's rest services. - */ -public class SpringHttpMessageConvertersIntegrationTestsCase { - - private static String BASE_URI = "http://localhost:8080/spring-rest/"; - - /** - * Without specifying Accept Header, uses the default response from the - * server (in this case json) - */ - @Test - public void whenRetrievingAFoo_thenCorrect() { - final String URI = BASE_URI + "foos/{id}"; - - final RestTemplate restTemplate = new RestTemplate(); - final Foo resource = restTemplate.getForObject(URI, Foo.class, "1"); - - assertThat(resource, notNullValue()); - } - - @Test - public void givenConsumingXml_whenReadingTheFoo_thenCorrect() { - final String URI = BASE_URI + "foos/{id}"; - - final RestTemplate restTemplate = new RestTemplate(); - restTemplate.setMessageConverters(getMessageConverters()); - - final HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML)); - final HttpEntity entity = new HttpEntity(headers); - - final ResponseEntity response = restTemplate.exchange(URI, HttpMethod.GET, entity, Foo.class, "1"); - final Foo resource = response.getBody(); - - assertThat(resource, notNullValue()); - } - - @Test - public void givenConsumingJson_whenReadingTheFoo_thenCorrect() { - final String URI = BASE_URI + "foos/{id}"; - - final RestTemplate restTemplate = new RestTemplate(); - restTemplate.setMessageConverters(getMessageConverters()); - - final HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); - final HttpEntity entity = new HttpEntity(headers); - - final ResponseEntity response = restTemplate.exchange(URI, HttpMethod.GET, entity, Foo.class, "1"); - final Foo resource = response.getBody(); - - assertThat(resource, notNullValue()); - } - - @Test - public void givenConsumingXml_whenWritingTheFoo_thenCorrect() { - final String URI = BASE_URI + "foos/{id}"; - final RestTemplate restTemplate = new RestTemplate(); - restTemplate.setMessageConverters(getMessageConverters()); - - final Foo resource = new Foo(4, "jason"); - final HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); - headers.setContentType((MediaType.APPLICATION_XML)); - final HttpEntity entity = new HttpEntity(resource, headers); - - final ResponseEntity response = restTemplate.exchange(URI, HttpMethod.PUT, entity, Foo.class, resource.getId()); - final Foo fooResponse = response.getBody(); - - Assert.assertEquals(resource.getId(), fooResponse.getId()); - } - - // UTIL - - private List> getMessageConverters() { - final List> converters = new ArrayList>(); - - final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); - final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); - xmlConverter.setMarshaller(xstreamMarshaller); - xmlConverter.setUnmarshaller(xstreamMarshaller); - - converters.add(xmlConverter); - converters.add(new MappingJackson2HttpMessageConverter()); - - return converters; - } - -} diff --git a/spring-rest/src/test/java/org/baeldung/web/test/SpringHttpMessageConvertersLiveTest.java b/spring-rest/src/test/java/org/baeldung/web/test/SpringHttpMessageConvertersLiveTest.java new file mode 100644 index 0000000000..7f250653ab --- /dev/null +++ b/spring-rest/src/test/java/org/baeldung/web/test/SpringHttpMessageConvertersLiveTest.java @@ -0,0 +1,123 @@ +package org.baeldung.web.test; + +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; + +import java.util.Arrays; + +import org.baeldung.config.converter.KryoHttpMessageConverter; +import org.baeldung.web.dto.Foo; +import org.baeldung.web.dto.FooProtos; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +/** + * Integration Test class. Tests methods hits the server's rest services. + */ +public class SpringHttpMessageConvertersLiveTest { + + private static String BASE_URI = "http://localhost:8082/spring-rest/"; + + /** + * Without specifying Accept Header, uses the default response from the + * server (in this case json) + */ + @Test + public void whenRetrievingAFoo_thenCorrect() { + final String URI = BASE_URI + "foos/{id}"; + + final RestTemplate restTemplate = new RestTemplate(); + final Foo resource = restTemplate.getForObject(URI, Foo.class, "1"); + + assertThat(resource, notNullValue()); + } + + @Test + public void givenConsumingXml_whenReadingTheFoo_thenCorrect() { + final String URI = BASE_URI + "foos/{id}"; + + final RestTemplate restTemplate = new RestTemplate(); + + final HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML)); + final HttpEntity entity = new HttpEntity(headers); + + final ResponseEntity response = restTemplate.exchange(URI, HttpMethod.GET, entity, Foo.class, "1"); + final Foo resource = response.getBody(); + + assertThat(resource, notNullValue()); + } + + @Test + public void givenConsumingJson_whenReadingTheFoo_thenCorrect() { + final String URI = BASE_URI + "foos/{id}"; + + final RestTemplate restTemplate = new RestTemplate(); + + final HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); + final HttpEntity entity = new HttpEntity(headers); + + final ResponseEntity response = restTemplate.exchange(URI, HttpMethod.GET, entity, Foo.class, "1"); + final Foo resource = response.getBody(); + + assertThat(resource, notNullValue()); + } + + @Test + public void givenConsumingXml_whenWritingTheFoo_thenCorrect() { + final String URI = BASE_URI + "foos/{id}"; + final RestTemplate restTemplate = new RestTemplate(); + + final Foo resource = new Foo(4, "jason"); + final HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); + headers.setContentType((MediaType.APPLICATION_XML)); + final HttpEntity entity = new HttpEntity(resource, headers); + + final ResponseEntity response = restTemplate.exchange(URI, HttpMethod.PUT, entity, Foo.class, resource.getId()); + final Foo fooResponse = response.getBody(); + + Assert.assertEquals(resource.getId(), fooResponse.getId()); + } + + @Test + public void givenConsumingProtobuf_whenReadingTheFoo_thenCorrect() { + final String URI = BASE_URI + "foos/{id}"; + + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setMessageConverters(Arrays.asList(new ProtobufHttpMessageConverter())); + final HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Arrays.asList(ProtobufHttpMessageConverter.PROTOBUF)); + final HttpEntity entity = new HttpEntity(headers); + + final ResponseEntity response = restTemplate.exchange(URI, HttpMethod.GET, entity, FooProtos.Foo.class, "1"); + final FooProtos.Foo resource = response.getBody(); + + assertThat(resource, notNullValue()); + } + + @Test + public void givenConsumingKryo_whenReadingTheFoo_thenCorrect() { + final String URI = BASE_URI + "foos/{id}"; + + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setMessageConverters(Arrays.asList(new KryoHttpMessageConverter())); + final HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Arrays.asList(KryoHttpMessageConverter.KRYO)); + final HttpEntity entity = new HttpEntity(headers); + + final ResponseEntity response = restTemplate.exchange(URI, HttpMethod.GET, entity, Foo.class, "1"); + final Foo resource = response.getBody(); + + assertThat(resource, notNullValue()); + } + +} diff --git a/spring-security-basic-auth/.classpath b/spring-security-basic-auth/.classpath deleted file mode 100644 index 5778c9435e..0000000000 --- a/spring-security-basic-auth/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-basic-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-security-basic-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-security-basic-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-basic-auth/.project b/spring-security-basic-auth/.project deleted file mode 100644 index 9126103207..0000000000 --- a/spring-security-basic-auth/.project +++ /dev/null @@ -1,42 +0,0 @@ - - - spring-security-mvc-basic-auth - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/spring-security-basic-auth/.settings/.jsdtscope b/spring-security-basic-auth/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/spring-security-basic-auth/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-basic-auth/.settings/org.eclipse.jdt.core.prefs b/spring-security-basic-auth/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index fb671a82a6..0000000000 --- a/spring-security-basic-auth/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-security-basic-auth/.settings/org.eclipse.jdt.ui.prefs b/spring-security-basic-auth/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-security-basic-auth/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-security-basic-auth/.settings/org.eclipse.m2e.core.prefs b/spring-security-basic-auth/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-security-basic-auth/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-security-basic-auth/.settings/org.eclipse.m2e.wtp.prefs b/spring-security-basic-auth/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-security-basic-auth/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-security-basic-auth/.settings/org.eclipse.wst.common.component b/spring-security-basic-auth/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 9a8276c85b..0000000000 --- a/spring-security-basic-auth/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-security-basic-auth/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-security-basic-auth/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f5888c1411..0000000000 --- a/spring-security-basic-auth/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-security-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-security-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-security-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-security-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-security-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-security-basic-auth/.settings/org.eclipse.wst.validation.prefs b/spring-security-basic-auth/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-security-basic-auth/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-security-basic-auth/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-security-basic-auth/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-security-basic-auth/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-security-basic-auth/.springBeans b/spring-security-basic-auth/.springBeans deleted file mode 100644 index 7623a7e888..0000000000 --- a/spring-security-basic-auth/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/spring-security-basic-auth/README.md b/spring-security-basic-auth/README.md index 95e45ae519..37ea545a9b 100644 --- a/spring-security-basic-auth/README.md +++ b/spring-security-basic-auth/README.md @@ -2,6 +2,8 @@ ## Spring Security with Basic Authentication Example Project +###The Course +The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Article: - [Spring Security - security none, filters none, access permitAll](http://www.baeldung.com/security-none-filters-none-access-permitAll) @@ -9,4 +11,4 @@ ### Notes -- the project includes both views as well as a REST layer \ No newline at end of file +- the project includes both views as well as a REST layer diff --git a/spring-security-basic-auth/pom.xml b/spring-security-basic-auth/pom.xml index 1e15cd5b53..009f5584bb 100644 --- a/spring-security-basic-auth/pom.xml +++ b/spring-security-basic-auth/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-mvc-basic-auth 0.1-SNAPSHOT @@ -225,12 +225,12 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 1.7.13 @@ -253,14 +253,14 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-security-client/README.MD b/spring-security-client/README.MD new file mode 100644 index 0000000000..5ac974203b --- /dev/null +++ b/spring-security-client/README.MD @@ -0,0 +1,2 @@ +###The Course +The "REST With Spring" Classes: http://github.learnspringsecurity.com diff --git a/spring-security-client/spring-security-jsp-authentication/pom.xml b/spring-security-client/spring-security-jsp-authentication/pom.xml new file mode 100644 index 0000000000..74de4d729b --- /dev/null +++ b/spring-security-client/spring-security-jsp-authentication/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + com.baeldung + spring-security-jsp-authentication + 0.0.1-SNAPSHOT + war + + spring-security-jsp-authenticate + Spring Security JSP Authentication tag sample + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.apache.tomcat.embed + tomcat-embed-jasper + provided + + + + javax.servlet + jstl + + + + org.springframework.security + spring-security-taglibs + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + + + diff --git a/spring-security-client/spring-security-jsp-authentication/src/main/java/org/baeldung/config/Application.java b/spring-security-client/spring-security-jsp-authentication/src/main/java/org/baeldung/config/Application.java new file mode 100644 index 0000000000..4057a85f13 --- /dev/null +++ b/spring-security-client/spring-security-jsp-authentication/src/main/java/org/baeldung/config/Application.java @@ -0,0 +1,20 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.web.SpringBootServletInitializer; + +@SpringBootApplication +public class Application extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(Application.class); + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-security-client/spring-security-jsp-authentication/src/main/java/org/baeldung/config/MvcConfig.java b/spring-security-client/spring-security-jsp-authentication/src/main/java/org/baeldung/config/MvcConfig.java new file mode 100644 index 0000000000..fa2a324146 --- /dev/null +++ b/spring-security-client/spring-security-jsp-authentication/src/main/java/org/baeldung/config/MvcConfig.java @@ -0,0 +1,23 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +public class MvcConfig extends WebMvcConfigurerAdapter { + + public MvcConfig() { + super(); + } + + // + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("forward:/index"); + registry.addViewController("/index"); + } + +} \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-authentication/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-client/spring-security-jsp-authentication/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..bd6c56d38a --- /dev/null +++ b/spring-security-client/spring-security-jsp-authentication/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,40 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.inMemoryAuthentication() + .withUser("john").password("123").roles("USER") + .and() + .withUser("tom").password("111").roles("ADMIN"); + // @formatter:on + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/login").permitAll() + .antMatchers("/admin").hasRole("ADMIN") + .anyRequest().authenticated() + .and().formLogin().permitAll() + ; + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-authentication/src/main/resources/application.properties b/spring-security-client/spring-security-jsp-authentication/src/main/resources/application.properties new file mode 100644 index 0000000000..26a80c79f3 --- /dev/null +++ b/spring-security-client/spring-security-jsp-authentication/src/main/resources/application.properties @@ -0,0 +1,3 @@ +server.port: 8081 +spring.mvc.view.prefix: /WEB-INF/jsp/ +spring.mvc.view.suffix: .jsp \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-authentication/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-security-client/spring-security-jsp-authentication/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 0000000000..90c00e980a --- /dev/null +++ b/spring-security-client/spring-security-jsp-authentication/src/main/webapp/WEB-INF/jsp/index.jsp @@ -0,0 +1,24 @@ + <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %> + + + + +Spring Security JSP Authorize + + + + + +
    + Current user name: +
    + Current user roles: +
    + + \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-authorize/pom.xml b/spring-security-client/spring-security-jsp-authorize/pom.xml new file mode 100644 index 0000000000..25bb21b663 --- /dev/null +++ b/spring-security-client/spring-security-jsp-authorize/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + com.baeldung + spring-security-jsp-authorize + 0.0.1-SNAPSHOT + war + + spring-security-jsp-authorize + Spring Security JSP Authorize tag sample + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.apache.tomcat.embed + tomcat-embed-jasper + provided + + + + javax.servlet + jstl + + + + org.springframework.security + spring-security-taglibs + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + + + diff --git a/spring-security-client/spring-security-jsp-authorize/src/main/java/org/baeldung/config/Application.java b/spring-security-client/spring-security-jsp-authorize/src/main/java/org/baeldung/config/Application.java new file mode 100644 index 0000000000..4057a85f13 --- /dev/null +++ b/spring-security-client/spring-security-jsp-authorize/src/main/java/org/baeldung/config/Application.java @@ -0,0 +1,20 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.web.SpringBootServletInitializer; + +@SpringBootApplication +public class Application extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(Application.class); + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-security-client/spring-security-jsp-authorize/src/main/java/org/baeldung/config/MvcConfig.java b/spring-security-client/spring-security-jsp-authorize/src/main/java/org/baeldung/config/MvcConfig.java new file mode 100644 index 0000000000..fa2a324146 --- /dev/null +++ b/spring-security-client/spring-security-jsp-authorize/src/main/java/org/baeldung/config/MvcConfig.java @@ -0,0 +1,23 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +public class MvcConfig extends WebMvcConfigurerAdapter { + + public MvcConfig() { + super(); + } + + // + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("forward:/index"); + registry.addViewController("/index"); + } + +} \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-authorize/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-client/spring-security-jsp-authorize/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..bd6c56d38a --- /dev/null +++ b/spring-security-client/spring-security-jsp-authorize/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,40 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.inMemoryAuthentication() + .withUser("john").password("123").roles("USER") + .and() + .withUser("tom").password("111").roles("ADMIN"); + // @formatter:on + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/login").permitAll() + .antMatchers("/admin").hasRole("ADMIN") + .anyRequest().authenticated() + .and().formLogin().permitAll() + ; + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-authorize/src/main/resources/application.properties b/spring-security-client/spring-security-jsp-authorize/src/main/resources/application.properties new file mode 100644 index 0000000000..26a80c79f3 --- /dev/null +++ b/spring-security-client/spring-security-jsp-authorize/src/main/resources/application.properties @@ -0,0 +1,3 @@ +server.port: 8081 +spring.mvc.view.prefix: /WEB-INF/jsp/ +spring.mvc.view.suffix: .jsp \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-authorize/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-security-client/spring-security-jsp-authorize/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 0000000000..08af845bd4 --- /dev/null +++ b/spring-security-client/spring-security-jsp-authorize/src/main/webapp/WEB-INF/jsp/index.jsp @@ -0,0 +1,33 @@ + <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %> + + + + +Spring Security JSP Authorize + + + + + +
    + + Only admins can see this message + + + + Only users can see this message + +
    + + + Only users who can call "/admin" URL can see this message + +
    + + \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-config/pom.xml b/spring-security-client/spring-security-jsp-config/pom.xml new file mode 100644 index 0000000000..2416552d7c --- /dev/null +++ b/spring-security-client/spring-security-jsp-config/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + com.baeldung + spring-security-jsp-config + 0.0.1-SNAPSHOT + war + + spring-security-jsp-config + Spring Security JSP configuration + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.apache.tomcat.embed + tomcat-embed-jasper + provided + + + + javax.servlet + jstl + + + + org.springframework.security + spring-security-taglibs + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + + + diff --git a/spring-security-client/spring-security-jsp-config/src/main/java/org/baeldung/config/Application.java b/spring-security-client/spring-security-jsp-config/src/main/java/org/baeldung/config/Application.java new file mode 100644 index 0000000000..4057a85f13 --- /dev/null +++ b/spring-security-client/spring-security-jsp-config/src/main/java/org/baeldung/config/Application.java @@ -0,0 +1,20 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.web.SpringBootServletInitializer; + +@SpringBootApplication +public class Application extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(Application.class); + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-security-client/spring-security-jsp-config/src/main/java/org/baeldung/config/MvcConfig.java b/spring-security-client/spring-security-jsp-config/src/main/java/org/baeldung/config/MvcConfig.java new file mode 100644 index 0000000000..fa2a324146 --- /dev/null +++ b/spring-security-client/spring-security-jsp-config/src/main/java/org/baeldung/config/MvcConfig.java @@ -0,0 +1,23 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +public class MvcConfig extends WebMvcConfigurerAdapter { + + public MvcConfig() { + super(); + } + + // + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("forward:/index"); + registry.addViewController("/index"); + } + +} \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-config/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-client/spring-security-jsp-config/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..bd6c56d38a --- /dev/null +++ b/spring-security-client/spring-security-jsp-config/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,40 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.inMemoryAuthentication() + .withUser("john").password("123").roles("USER") + .and() + .withUser("tom").password("111").roles("ADMIN"); + // @formatter:on + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/login").permitAll() + .antMatchers("/admin").hasRole("ADMIN") + .anyRequest().authenticated() + .and().formLogin().permitAll() + ; + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-config/src/main/resources/application.properties b/spring-security-client/spring-security-jsp-config/src/main/resources/application.properties new file mode 100644 index 0000000000..26a80c79f3 --- /dev/null +++ b/spring-security-client/spring-security-jsp-config/src/main/resources/application.properties @@ -0,0 +1,3 @@ +server.port: 8081 +spring.mvc.view.prefix: /WEB-INF/jsp/ +spring.mvc.view.suffix: .jsp \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-config/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-security-client/spring-security-jsp-config/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 0000000000..bd5ccb0c78 --- /dev/null +++ b/spring-security-client/spring-security-jsp-config/src/main/webapp/WEB-INF/jsp/index.jsp @@ -0,0 +1,21 @@ + + + + +Spring Security JSP + + + + + +
    + Welcome +
    + + \ No newline at end of file diff --git a/spring-security-client/spring-security-mvc/pom.xml b/spring-security-client/spring-security-mvc/pom.xml new file mode 100644 index 0000000000..ec3b1f1782 --- /dev/null +++ b/spring-security-client/spring-security-mvc/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + com.baeldung + spring-security-mvc + 0.0.1-SNAPSHOT + war + + spring-security-mvc + Spring Security MVC + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + + + diff --git a/spring-security-client/spring-security-mvc/src/main/java/org/baeldung/config/Application.java b/spring-security-client/spring-security-mvc/src/main/java/org/baeldung/config/Application.java new file mode 100644 index 0000000000..4057a85f13 --- /dev/null +++ b/spring-security-client/spring-security-mvc/src/main/java/org/baeldung/config/Application.java @@ -0,0 +1,20 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.web.SpringBootServletInitializer; + +@SpringBootApplication +public class Application extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(Application.class); + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-security-client/spring-security-mvc/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-client/spring-security-mvc/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..bd6c56d38a --- /dev/null +++ b/spring-security-client/spring-security-mvc/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,40 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.inMemoryAuthentication() + .withUser("john").password("123").roles("USER") + .and() + .withUser("tom").password("111").roles("ADMIN"); + // @formatter:on + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/login").permitAll() + .antMatchers("/admin").hasRole("ADMIN") + .anyRequest().authenticated() + .and().formLogin().permitAll() + ; + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-security-client/spring-security-mvc/src/main/resources/application.properties b/spring-security-client/spring-security-mvc/src/main/resources/application.properties new file mode 100644 index 0000000000..c2eee0d931 --- /dev/null +++ b/spring-security-client/spring-security-mvc/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port: 8081 \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-authentication/pom.xml b/spring-security-client/spring-security-thymeleaf-authentication/pom.xml new file mode 100644 index 0000000000..cdbe0946f4 --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authentication/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + com.baeldung + spring-security-thymeleaf-authentication + 0.0.1-SNAPSHOT + war + + spring-security-thymeleaf-authentication + Spring Security thymeleaf authentication tag sample + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity4 + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + + + diff --git a/spring-security-client/spring-security-thymeleaf-authentication/src/main/java/org/baeldung/config/Application.java b/spring-security-client/spring-security-thymeleaf-authentication/src/main/java/org/baeldung/config/Application.java new file mode 100644 index 0000000000..bea0194b40 --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authentication/src/main/java/org/baeldung/config/Application.java @@ -0,0 +1,13 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-security-client/spring-security-thymeleaf-authentication/src/main/java/org/baeldung/config/MvcConfig.java b/spring-security-client/spring-security-thymeleaf-authentication/src/main/java/org/baeldung/config/MvcConfig.java new file mode 100644 index 0000000000..9ade60e54c --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authentication/src/main/java/org/baeldung/config/MvcConfig.java @@ -0,0 +1,42 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +public class MvcConfig extends WebMvcConfigurerAdapter { + + public MvcConfig() { + super(); + } + + // + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Override + public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("forward:/index"); + registry.addViewController("/index"); + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } +} \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-authentication/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-client/spring-security-thymeleaf-authentication/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..bd6c56d38a --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authentication/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,40 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.inMemoryAuthentication() + .withUser("john").password("123").roles("USER") + .and() + .withUser("tom").password("111").roles("ADMIN"); + // @formatter:on + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/login").permitAll() + .antMatchers("/admin").hasRole("ADMIN") + .anyRequest().authenticated() + .and().formLogin().permitAll() + ; + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-authentication/src/main/resources/application.properties b/spring-security-client/spring-security-thymeleaf-authentication/src/main/resources/application.properties new file mode 100644 index 0000000000..bafddced85 --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authentication/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=8081 \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-authentication/src/main/resources/templates/index.html b/spring-security-client/spring-security-thymeleaf-authentication/src/main/resources/templates/index.html new file mode 100644 index 0000000000..c65b5f092b --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authentication/src/main/resources/templates/index.html @@ -0,0 +1,23 @@ + + + + +Spring Security Thymeleaf + + + + + +
    + Current user name: Bob +
    + Current user roles: [ROLE_USER, ROLE_ADMIN] +
    + + \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-authorize/pom.xml b/spring-security-client/spring-security-thymeleaf-authorize/pom.xml new file mode 100644 index 0000000000..5254f1db1a --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authorize/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + com.baeldung + spring-security-thymeleaf-authorize + 0.0.1-SNAPSHOT + war + + spring-security-thymeleaf-authorize + Spring Security thymeleaf authorize tag sample + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity4 + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + + + diff --git a/spring-security-client/spring-security-thymeleaf-authorize/src/main/java/org/baeldung/config/Application.java b/spring-security-client/spring-security-thymeleaf-authorize/src/main/java/org/baeldung/config/Application.java new file mode 100644 index 0000000000..bea0194b40 --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authorize/src/main/java/org/baeldung/config/Application.java @@ -0,0 +1,13 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-security-client/spring-security-thymeleaf-authorize/src/main/java/org/baeldung/config/MvcConfig.java b/spring-security-client/spring-security-thymeleaf-authorize/src/main/java/org/baeldung/config/MvcConfig.java new file mode 100644 index 0000000000..9ade60e54c --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authorize/src/main/java/org/baeldung/config/MvcConfig.java @@ -0,0 +1,42 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +public class MvcConfig extends WebMvcConfigurerAdapter { + + public MvcConfig() { + super(); + } + + // + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Override + public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("forward:/index"); + registry.addViewController("/index"); + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } +} \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-authorize/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-client/spring-security-thymeleaf-authorize/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..bd6c56d38a --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authorize/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,40 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.inMemoryAuthentication() + .withUser("john").password("123").roles("USER") + .and() + .withUser("tom").password("111").roles("ADMIN"); + // @formatter:on + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/login").permitAll() + .antMatchers("/admin").hasRole("ADMIN") + .anyRequest().authenticated() + .and().formLogin().permitAll() + ; + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-authorize/src/main/resources/application.properties b/spring-security-client/spring-security-thymeleaf-authorize/src/main/resources/application.properties new file mode 100644 index 0000000000..bafddced85 --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authorize/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=8081 \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-authorize/src/main/resources/templates/index.html b/spring-security-client/spring-security-thymeleaf-authorize/src/main/resources/templates/index.html new file mode 100644 index 0000000000..fcbbfb4957 --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-authorize/src/main/resources/templates/index.html @@ -0,0 +1,32 @@ + + + + +Spring Security Thymeleaf + + + + + +
    +
    + Only admins can see this message +
    + +
    + Only users can see this message +
    +
    + +
    + Only users who can call "/admin" URL can see this message +
    +
    + + \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-config/pom.xml b/spring-security-client/spring-security-thymeleaf-config/pom.xml new file mode 100644 index 0000000000..ec145a29c8 --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-config/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + com.baeldung + spring-security-thymeleaf-config + 0.0.1-SNAPSHOT + war + + spring-security-thymeleaf-config + Spring Security thymeleaf configuration sample project + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity4 + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + + + diff --git a/spring-security-client/spring-security-thymeleaf-config/src/main/java/org/baeldung/config/Application.java b/spring-security-client/spring-security-thymeleaf-config/src/main/java/org/baeldung/config/Application.java new file mode 100644 index 0000000000..bea0194b40 --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-config/src/main/java/org/baeldung/config/Application.java @@ -0,0 +1,13 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-security-client/spring-security-thymeleaf-config/src/main/java/org/baeldung/config/MvcConfig.java b/spring-security-client/spring-security-thymeleaf-config/src/main/java/org/baeldung/config/MvcConfig.java new file mode 100644 index 0000000000..9ade60e54c --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-config/src/main/java/org/baeldung/config/MvcConfig.java @@ -0,0 +1,42 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +public class MvcConfig extends WebMvcConfigurerAdapter { + + public MvcConfig() { + super(); + } + + // + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Override + public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("forward:/index"); + registry.addViewController("/index"); + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } +} \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-config/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-client/spring-security-thymeleaf-config/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..bd6c56d38a --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-config/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,40 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.inMemoryAuthentication() + .withUser("john").password("123").roles("USER") + .and() + .withUser("tom").password("111").roles("ADMIN"); + // @formatter:on + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/login").permitAll() + .antMatchers("/admin").hasRole("ADMIN") + .anyRequest().authenticated() + .and().formLogin().permitAll() + ; + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-config/src/main/resources/application.properties b/spring-security-client/spring-security-thymeleaf-config/src/main/resources/application.properties new file mode 100644 index 0000000000..bafddced85 --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-config/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=8081 \ No newline at end of file diff --git a/spring-security-client/spring-security-thymeleaf-config/src/main/resources/templates/index.html b/spring-security-client/spring-security-thymeleaf-config/src/main/resources/templates/index.html new file mode 100644 index 0000000000..8e7394ad6a --- /dev/null +++ b/spring-security-client/spring-security-thymeleaf-config/src/main/resources/templates/index.html @@ -0,0 +1,21 @@ + + + + +Spring Security Thymeleaf + + + + + +
    + Welcome +
    + + \ No newline at end of file diff --git a/spring-security-custom-permission/README.MD b/spring-security-custom-permission/README.MD new file mode 100644 index 0000000000..5ac974203b --- /dev/null +++ b/spring-security-custom-permission/README.MD @@ -0,0 +1,2 @@ +###The Course +The "REST With Spring" Classes: http://github.learnspringsecurity.com diff --git a/spring-security-custom-permission/pom.xml b/spring-security-custom-permission/pom.xml new file mode 100644 index 0000000000..6f460f1751 --- /dev/null +++ b/spring-security-custom-permission/pom.xml @@ -0,0 +1,107 @@ + + + 4.0.0 + + com.baeldung + spring-security-custom-permission + 0.0.1-SNAPSHOT + war + + spring-security-custom-permission + Spring Security custom permission + + + org.springframework.boot + spring-boot-starter-parent + 1.3.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.thymeleaf.extras + thymeleaf-extras-springsecurity4 + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + com.h2database + h2 + + + + + + junit + junit + test + + + + org.hamcrest + hamcrest-core + test + + + + org.hamcrest + hamcrest-library + test + + + + com.jayway.restassured + rest-assured + ${rest-assured.version} + test + + + commons-logging + commons-logging + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + 2.4.0 + + + diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/Application.java b/spring-security-custom-permission/src/main/java/org/baeldung/Application.java new file mode 100644 index 0000000000..a9d6f3b8b1 --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/Application.java @@ -0,0 +1,12 @@ +package org.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/config/MethodSecurityConfig.java b/spring-security-custom-permission/src/main/java/org/baeldung/config/MethodSecurityConfig.java new file mode 100644 index 0000000000..c4624e85e0 --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/config/MethodSecurityConfig.java @@ -0,0 +1,21 @@ +package org.baeldung.config; + +import org.baeldung.security.CustomMethodSecurityExpressionHandler; +import org.baeldung.security.CustomPermissionEvaluator; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; + +@Configuration +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { + + @Override + protected MethodSecurityExpressionHandler createExpressionHandler() { + // final DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); + final CustomMethodSecurityExpressionHandler expressionHandler = new CustomMethodSecurityExpressionHandler(); + expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator()); + return expressionHandler; + } +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/config/MvcConfig.java b/spring-security-custom-permission/src/main/java/org/baeldung/config/MvcConfig.java new file mode 100644 index 0000000000..9ade60e54c --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/config/MvcConfig.java @@ -0,0 +1,42 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +public class MvcConfig extends WebMvcConfigurerAdapter { + + public MvcConfig() { + super(); + } + + // + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Override + public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("forward:/index"); + registry.addViewController("/index"); + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } +} \ No newline at end of file diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-custom-permission/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..b365744bea --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,43 @@ +package org.baeldung.config; + +import org.baeldung.security.MyUserDetailsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +@ComponentScan("org.baeldung.security") +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private MyUserDetailsService userDetailsService; + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService); + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers("/login").permitAll() + .antMatchers("/admin").hasRole("ADMIN") + .anyRequest().authenticated() + .and().formLogin().permitAll() + .and().csrf().disable(); + ; + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/SetupData.java b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/SetupData.java new file mode 100644 index 0000000000..47616ca61a --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/SetupData.java @@ -0,0 +1,70 @@ +package org.baeldung.persistence; + +import java.util.Arrays; +import java.util.HashSet; + +import javax.annotation.PostConstruct; + +import org.baeldung.persistence.dao.OrganizationRepository; +import org.baeldung.persistence.dao.PrivilegeRepository; +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.model.Organization; +import org.baeldung.persistence.model.Privilege; +import org.baeldung.persistence.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SetupData { + @Autowired + private UserRepository userRepository; + + @Autowired + private PrivilegeRepository privilegeRepository; + + @Autowired + private OrganizationRepository organizationRepository; + + @PostConstruct + public void init() { + initPrivileges(); + initOrganizations(); + initUsers(); + } + + private void initUsers() { + final Privilege privilege1 = privilegeRepository.findByName("FOO_READ_PRIVILEGE"); + final Privilege privilege2 = privilegeRepository.findByName("FOO_WRITE_PRIVILEGE"); + // + final User user1 = new User(); + user1.setUsername("john"); + user1.setPassword("123"); + user1.setPrivileges(new HashSet(Arrays.asList(privilege1))); + user1.setOrganization(organizationRepository.findByName("FirstOrg")); + userRepository.save(user1); + // + final User user2 = new User(); + user2.setUsername("tom"); + user2.setPassword("111"); + user2.setPrivileges(new HashSet(Arrays.asList(privilege1, privilege2))); + user2.setOrganization(organizationRepository.findByName("SecondOrg")); + userRepository.save(user2); + } + + private void initOrganizations() { + final Organization org1 = new Organization("FirstOrg"); + organizationRepository.save(org1); + // + final Organization org2 = new Organization("SecondOrg"); + organizationRepository.save(org2); + + } + + private void initPrivileges() { + final Privilege privilege1 = new Privilege("FOO_READ_PRIVILEGE"); + privilegeRepository.save(privilege1); + // + final Privilege privilege2 = new Privilege("FOO_WRITE_PRIVILEGE"); + privilegeRepository.save(privilege2); + } +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/OrganizationRepository.java b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/OrganizationRepository.java new file mode 100644 index 0000000000..a20d24057b --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/OrganizationRepository.java @@ -0,0 +1,10 @@ +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.Organization; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface OrganizationRepository extends JpaRepository { + + public Organization findByName(String name); + +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java new file mode 100644 index 0000000000..edf9002c3d --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java @@ -0,0 +1,10 @@ +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.Privilege; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PrivilegeRepository extends JpaRepository { + + public Privilege findByName(String name); + +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/UserRepository.java b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/UserRepository.java new file mode 100644 index 0000000000..679dd6c363 --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/UserRepository.java @@ -0,0 +1,10 @@ +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + + User findByUsername(final String username); + +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Foo.java b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Foo.java new file mode 100644 index 0000000000..29c19cf22e --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Foo.java @@ -0,0 +1,94 @@ +package org.baeldung.persistence.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Foo { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column(nullable = false) + private String name; + + // + + public Foo() { + super(); + } + + public Foo(String name) { + super(); + this.name = name; + } + + // + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + // + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Foo [id=").append(id).append(", name=").append(name).append("]"); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + ((id == null) ? 0 : id.hashCode()); + result = (prime * result) + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Foo other = (Foo) obj; + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Organization.java b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Organization.java new file mode 100644 index 0000000000..645285b5e9 --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Organization.java @@ -0,0 +1,95 @@ +package org.baeldung.persistence.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Organization { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column(nullable = false, unique = true) + private String name; + + // + + public Organization() { + super(); + } + + public Organization(String name) { + super(); + this.name = name; + } + + // + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + // + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Organization [id=").append(id).append(", name=").append(name).append("]"); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + ((id == null) ? 0 : id.hashCode()); + result = (prime * result) + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Organization other = (Organization) obj; + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Privilege.java b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Privilege.java new file mode 100644 index 0000000000..ff3ae62c25 --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Privilege.java @@ -0,0 +1,95 @@ +package org.baeldung.persistence.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Privilege { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column(nullable = false, unique = true) + private String name; + + // + + public Privilege() { + super(); + } + + public Privilege(String name) { + super(); + this.name = name; + } + + // + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + // + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Privilege [id=").append(id).append(", name=").append(name).append("]"); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + ((id == null) ? 0 : id.hashCode()); + result = (prime * result) + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Privilege other = (Privilege) obj; + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/User.java b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/User.java new file mode 100644 index 0000000000..112d502105 --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/User.java @@ -0,0 +1,153 @@ +package org.baeldung.persistence.model; + +import java.util.Set; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; + +@Entity +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Column(nullable = false, unique = true) + private String username; + + private String password; + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable(name = "users_privileges", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "privilege_id", referencedColumnName = "id")) + private Set privileges; + + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "organization_id", referencedColumnName = "id") + private Organization organization; + + // + + public User() { + super(); + } + + // + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Set getPrivileges() { + return privileges; + } + + public void setPrivileges(Set privileges) { + this.privileges = privileges; + } + + public Organization getOrganization() { + return organization; + } + + public void setOrganization(Organization organization) { + this.organization = organization; + } + + // + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("User [id=").append(id).append(", username=").append(username).append(", password=").append(password).append(", privileges=").append(privileges).append(", organization=").append(organization).append("]"); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + ((id == null) ? 0 : id.hashCode()); + result = (prime * result) + ((organization == null) ? 0 : organization.hashCode()); + result = (prime * result) + ((password == null) ? 0 : password.hashCode()); + result = (prime * result) + ((privileges == null) ? 0 : privileges.hashCode()); + result = (prime * result) + ((username == null) ? 0 : username.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final User other = (User) obj; + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + if (organization == null) { + if (other.organization != null) { + return false; + } + } else if (!organization.equals(other.organization)) { + return false; + } + if (password == null) { + if (other.password != null) { + return false; + } + } else if (!password.equals(other.password)) { + return false; + } + if (privileges == null) { + if (other.privileges != null) { + return false; + } + } else if (!privileges.equals(other.privileges)) { + return false; + } + if (username == null) { + if (other.username != null) { + return false; + } + } else if (!username.equals(other.username)) { + return false; + } + return true; + } +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionHandler.java b/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionHandler.java new file mode 100644 index 0000000000..e040a0b109 --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionHandler.java @@ -0,0 +1,22 @@ +package org.baeldung.security; + +import org.aopalliance.intercept.MethodInvocation; +import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; +import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations; +import org.springframework.security.authentication.AuthenticationTrustResolver; +import org.springframework.security.authentication.AuthenticationTrustResolverImpl; +import org.springframework.security.core.Authentication; + +public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler { + private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl(); + + @Override + protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) { + // final CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication); + final MySecurityExpressionRoot root = new MySecurityExpressionRoot(authentication); + root.setPermissionEvaluator(getPermissionEvaluator()); + root.setTrustResolver(this.trustResolver); + root.setRoleHierarchy(getRoleHierarchy()); + return root; + } +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionRoot.java b/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionRoot.java new file mode 100644 index 0000000000..2d84536a14 --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionRoot.java @@ -0,0 +1,50 @@ +package org.baeldung.security; + +import org.baeldung.persistence.model.User; +import org.springframework.security.access.expression.SecurityExpressionRoot; +import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations; +import org.springframework.security.core.Authentication; + +public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations { + + private Object filterObject; + private Object returnObject; + + public CustomMethodSecurityExpressionRoot(Authentication authentication) { + super(authentication); + } + + // + public boolean isMember(Long OrganizationId) { + final User user = ((MyUserPrincipal) this.getPrincipal()).getUser(); + return user.getOrganization().getId().longValue() == OrganizationId.longValue(); + } + + // + + @Override + public Object getFilterObject() { + return this.filterObject; + } + + @Override + public Object getReturnObject() { + return this.returnObject; + } + + @Override + public Object getThis() { + return this; + } + + @Override + public void setFilterObject(Object obj) { + this.filterObject = obj; + } + + @Override + public void setReturnObject(Object obj) { + this.returnObject = obj; + } + +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomPermissionEvaluator.java b/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomPermissionEvaluator.java new file mode 100644 index 0000000000..5d96673a8f --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomPermissionEvaluator.java @@ -0,0 +1,40 @@ +package org.baeldung.security; + +import java.io.Serializable; + +import org.springframework.security.access.PermissionEvaluator; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; + +public class CustomPermissionEvaluator implements PermissionEvaluator { + + @Override + public boolean hasPermission(Authentication auth, Object targetDomainObject, Object permission) { + if ((auth == null) || (targetDomainObject == null) || !(permission instanceof String)) { + return false; + } + final String targetType = targetDomainObject.getClass().getSimpleName().toUpperCase(); + return hasPrivilege(auth, targetType, permission.toString().toUpperCase()); + } + + @Override + public boolean hasPermission(Authentication auth, Serializable targetId, String targetType, Object permission) { + if ((auth == null) || (targetType == null) || !(permission instanceof String)) { + return false; + } + return hasPrivilege(auth, targetType.toUpperCase(), permission.toString().toUpperCase()); + } + + private boolean hasPrivilege(Authentication auth, String targetType, String permission) { + for (final GrantedAuthority grantedAuth : auth.getAuthorities()) { + System.out.println("here " + grantedAuth); + if (grantedAuth.getAuthority().startsWith(targetType)) { + if (grantedAuth.getAuthority().contains(permission)) { + return true; + } + } + } + return false; + } + +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/MySecurityExpressionRoot.java b/spring-security-custom-permission/src/main/java/org/baeldung/security/MySecurityExpressionRoot.java new file mode 100644 index 0000000000..4d3561b325 --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/security/MySecurityExpressionRoot.java @@ -0,0 +1,203 @@ +package org.baeldung.security; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.baeldung.persistence.model.User; +import org.springframework.security.access.PermissionEvaluator; +import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations; +import org.springframework.security.access.hierarchicalroles.RoleHierarchy; +import org.springframework.security.authentication.AuthenticationTrustResolver; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; + +public class MySecurityExpressionRoot implements MethodSecurityExpressionOperations { + protected final Authentication authentication; + private AuthenticationTrustResolver trustResolver; + private RoleHierarchy roleHierarchy; + private Set roles; + private String defaultRolePrefix = "ROLE_"; + + public final boolean permitAll = true; + public final boolean denyAll = false; + private PermissionEvaluator permissionEvaluator; + public final String read = "read"; + public final String write = "write"; + public final String create = "create"; + public final String delete = "delete"; + public final String admin = "administration"; + + // + + private Object filterObject; + private Object returnObject; + + public MySecurityExpressionRoot(Authentication authentication) { + if (authentication == null) { + throw new IllegalArgumentException("Authentication object cannot be null"); + } + this.authentication = authentication; + } + + @Override + public final boolean hasAuthority(String authority) { + throw new RuntimeException("method hasAuthority() not allowed"); + } + + // + public boolean isMember(Long OrganizationId) { + final User user = ((MyUserPrincipal) this.getPrincipal()).getUser(); + return user.getOrganization().getId().longValue() == OrganizationId.longValue(); + } + + // + + @Override + public final boolean hasAnyAuthority(String... authorities) { + return hasAnyAuthorityName(null, authorities); + } + + @Override + public final boolean hasRole(String role) { + return hasAnyRole(role); + } + + @Override + public final boolean hasAnyRole(String... roles) { + return hasAnyAuthorityName(defaultRolePrefix, roles); + } + + private boolean hasAnyAuthorityName(String prefix, String... roles) { + final Set roleSet = getAuthoritySet(); + + for (final String role : roles) { + final String defaultedRole = getRoleWithDefaultPrefix(prefix, role); + if (roleSet.contains(defaultedRole)) { + return true; + } + } + + return false; + } + + @Override + public final Authentication getAuthentication() { + return authentication; + } + + @Override + public final boolean permitAll() { + return true; + } + + @Override + public final boolean denyAll() { + return false; + } + + @Override + public final boolean isAnonymous() { + return trustResolver.isAnonymous(authentication); + } + + @Override + public final boolean isAuthenticated() { + return !isAnonymous(); + } + + @Override + public final boolean isRememberMe() { + return trustResolver.isRememberMe(authentication); + } + + @Override + public final boolean isFullyAuthenticated() { + return !trustResolver.isAnonymous(authentication) && !trustResolver.isRememberMe(authentication); + } + + public Object getPrincipal() { + return authentication.getPrincipal(); + } + + public void setTrustResolver(AuthenticationTrustResolver trustResolver) { + this.trustResolver = trustResolver; + } + + public void setRoleHierarchy(RoleHierarchy roleHierarchy) { + this.roleHierarchy = roleHierarchy; + } + + public void setDefaultRolePrefix(String defaultRolePrefix) { + this.defaultRolePrefix = defaultRolePrefix; + } + + private Set getAuthoritySet() { + if (roles == null) { + roles = new HashSet(); + Collection userAuthorities = authentication.getAuthorities(); + + if (roleHierarchy != null) { + userAuthorities = roleHierarchy.getReachableGrantedAuthorities(userAuthorities); + } + + roles = AuthorityUtils.authorityListToSet(userAuthorities); + } + + return roles; + } + + @Override + public boolean hasPermission(Object target, Object permission) { + return permissionEvaluator.hasPermission(authentication, target, permission); + } + + @Override + public boolean hasPermission(Object targetId, String targetType, Object permission) { + return permissionEvaluator.hasPermission(authentication, (Serializable) targetId, targetType, permission); + } + + public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) { + this.permissionEvaluator = permissionEvaluator; + } + + private static String getRoleWithDefaultPrefix(String defaultRolePrefix, String role) { + if (role == null) { + return role; + } + if ((defaultRolePrefix == null) || (defaultRolePrefix.length() == 0)) { + return role; + } + if (role.startsWith(defaultRolePrefix)) { + return role; + } + return defaultRolePrefix + role; + } + + @Override + public Object getFilterObject() { + return this.filterObject; + } + + @Override + public Object getReturnObject() { + return this.returnObject; + } + + @Override + public Object getThis() { + return this; + } + + @Override + public void setFilterObject(Object obj) { + this.filterObject = obj; + } + + @Override + public void setReturnObject(Object obj) { + this.returnObject = obj; + } +} \ No newline at end of file diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/MyUserDetailsService.java b/spring-security-custom-permission/src/main/java/org/baeldung/security/MyUserDetailsService.java new file mode 100644 index 0000000000..685219728f --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/security/MyUserDetailsService.java @@ -0,0 +1,31 @@ +package org.baeldung.security; + +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +public class MyUserDetailsService implements UserDetailsService { + + @Autowired + private UserRepository userRepository; + + public MyUserDetailsService() { + super(); + } + + // API + + @Override + public UserDetails loadUserByUsername(final String username) { + final User user = userRepository.findByUsername(username); + if (user == null) { + throw new UsernameNotFoundException(username); + } + return new MyUserPrincipal(user); + } +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/MyUserPrincipal.java b/spring-security-custom-permission/src/main/java/org/baeldung/security/MyUserPrincipal.java new file mode 100644 index 0000000000..437bb02cdb --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/security/MyUserPrincipal.java @@ -0,0 +1,72 @@ +package org.baeldung.security; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.baeldung.persistence.model.Privilege; +import org.baeldung.persistence.model.User; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +public class MyUserPrincipal implements UserDetails { + + private static final long serialVersionUID = 1L; + + private final User user; + + // + + public MyUserPrincipal(User user) { + this.user = user; + } + + // + + @Override + public String getUsername() { + return user.getUsername(); + } + + @Override + public String getPassword() { + return user.getPassword(); + } + + @Override + public Collection getAuthorities() { + final List authorities = new ArrayList(); + for (final Privilege privilege : user.getPrivileges()) { + authorities.add(new SimpleGrantedAuthority(privilege.getName())); + } + return authorities; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + // + + public User getUser() { + return user; + } + +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/web/MainController.java b/spring-security-custom-permission/src/main/java/org/baeldung/web/MainController.java new file mode 100644 index 0000000000..4752f7bdd9 --- /dev/null +++ b/spring-security-custom-permission/src/main/java/org/baeldung/web/MainController.java @@ -0,0 +1,58 @@ +package org.baeldung.web; + +import org.baeldung.persistence.dao.OrganizationRepository; +import org.baeldung.persistence.model.Foo; +import org.baeldung.persistence.model.Organization; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +@Controller +public class MainController { + + @Autowired + private OrganizationRepository organizationRepository; + + // @PostAuthorize("hasPermission(returnObject, 'read')") + @PreAuthorize("hasPermission(#id, 'Foo', 'read')") + @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}") + @ResponseBody + public Foo findById(@PathVariable final long id) { + return new Foo("Sample"); + } + + @PreAuthorize("hasPermission(#foo, 'write')") + @RequestMapping(method = RequestMethod.POST, value = "/foos") + @ResponseStatus(HttpStatus.CREATED) + @ResponseBody + public Foo create(@RequestBody final Foo foo) { + return foo; + } + + // + + @PreAuthorize("hasAuthority('FOO_READ_PRIVILEGE')") + @RequestMapping(method = RequestMethod.GET, value = "/foos") + @ResponseBody + public Foo findFooByName(@RequestParam final String name) { + return new Foo(name); + } + + // + + @PreAuthorize("isMember(#id)") + @RequestMapping(method = RequestMethod.GET, value = "/organizations/{id}") + @ResponseBody + public Organization findOrgById(@PathVariable final long id) { + return organizationRepository.findOne(id); + } + +} diff --git a/spring-security-custom-permission/src/main/resources/application.properties b/spring-security-custom-permission/src/main/resources/application.properties new file mode 100644 index 0000000000..0b40f62fa9 --- /dev/null +++ b/spring-security-custom-permission/src/main/resources/application.properties @@ -0,0 +1,9 @@ +server.port=8081 +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:security_permission;DB_CLOSE_DELAY=-1 +spring.datasource.username=sa +spring.datasource.password= +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.database=H2 +spring.jpa.show-sql=false +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/spring-security-custom-permission/src/main/resources/templates/index.html b/spring-security-custom-permission/src/main/resources/templates/index.html new file mode 100644 index 0000000000..8e7394ad6a --- /dev/null +++ b/spring-security-custom-permission/src/main/resources/templates/index.html @@ -0,0 +1,21 @@ + + + + +Spring Security Thymeleaf + + + + + +
    + Welcome +
    + + \ No newline at end of file diff --git a/spring-security-custom-permission/src/test/java/org/baeldung/web/LiveTest.java b/spring-security-custom-permission/src/test/java/org/baeldung/web/LiveTest.java new file mode 100644 index 0000000000..80b1390083 --- /dev/null +++ b/spring-security-custom-permission/src/test/java/org/baeldung/web/LiveTest.java @@ -0,0 +1,67 @@ +package org.baeldung.web; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.baeldung.persistence.model.Foo; +import org.junit.Test; +import org.springframework.http.MediaType; + +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.authentication.FormAuthConfig; +import com.jayway.restassured.response.Response; +import com.jayway.restassured.specification.RequestSpecification; + +public class LiveTest { + + private final FormAuthConfig formAuthConfig = new FormAuthConfig("http://localhost:8081/login", "username", "password"); + + @Test + public void givenUserWithReadPrivilegeAndHasPermission_whenGetFooById_thenOK() { + final Response response = givenAuth("john", "123").get("http://localhost:8081/foos/1"); + assertEquals(200, response.getStatusCode()); + assertTrue(response.asString().contains("id")); + } + + @Test + public void givenUserWithNoWritePrivilegeAndHasPermission_whenPostFoo_thenForbidden() { + final Response response = givenAuth("john", "123").contentType(MediaType.APPLICATION_JSON_VALUE).body(new Foo("sample")).post("http://localhost:8081/foos"); + assertEquals(403, response.getStatusCode()); + } + + @Test + public void givenUserWithWritePrivilegeAndHasPermission_whenPostFoo_thenOk() { + final Response response = givenAuth("tom", "111").contentType(MediaType.APPLICATION_JSON_VALUE).body(new Foo("sample")).post("http://localhost:8081/foos"); + assertEquals(201, response.getStatusCode()); + assertTrue(response.asString().contains("id")); + } + + // + + @Test + public void givenUserMemberInOrganization_whenGetOrganization_thenOK() { + final Response response = givenAuth("john", "123").get("http://localhost:8081/organizations/1"); + assertEquals(200, response.getStatusCode()); + assertTrue(response.asString().contains("id")); + } + + @Test + public void givenUserMemberNotInOrganization_whenGetOrganization_thenForbidden() { + final Response response = givenAuth("john", "123").get("http://localhost:8081/organizations/2"); + assertEquals(403, response.getStatusCode()); + } + + // + + @Test + public void givenDisabledSecurityExpression_whenGetFooByName_thenError() { + final Response response = givenAuth("john", "123").get("http://localhost:8081/foos?name=sample"); + assertEquals(500, response.getStatusCode()); + assertTrue(response.asString().contains("method hasAuthority() not allowed")); + } + + // + private RequestSpecification givenAuth(String username, String password) { + return RestAssured.given().auth().form(username, password, formAuthConfig); + } +} \ No newline at end of file diff --git a/spring-security-login-and-registration/.classpath b/spring-security-login-and-registration/.classpath deleted file mode 100644 index 26981b6dd7..0000000000 --- a/spring-security-login-and-registration/.classpath +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-login-and-registration/.project b/spring-security-login-and-registration/.project deleted file mode 100644 index 2c3e86ed06..0000000000 --- a/spring-security-login-and-registration/.project +++ /dev/null @@ -1,60 +0,0 @@ - - - spring-security-login-and-registration - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.jboss.tools.jst.web.kb.kbbuilder - - - - - org.hibernate.eclipse.console.hibernateBuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - org.hibernate.eclipse.console.hibernateNature - org.jboss.tools.jst.web.kb.kbnature - - diff --git a/spring-security-login-and-registration/.springBeans b/spring-security-login-and-registration/.springBeans deleted file mode 100644 index 8096aa036b..0000000000 --- a/spring-security-login-and-registration/.springBeans +++ /dev/null @@ -1,15 +0,0 @@ - - - 1 - - - - - - - - - - - - diff --git a/spring-security-login-and-registration/README.md b/spring-security-login-and-registration/README.md deleted file mode 100644 index 1c5b16d6f6..0000000000 --- a/spring-security-login-and-registration/README.md +++ /dev/null @@ -1,29 +0,0 @@ -========= - -## Login and Registration Example Project with Spring Security - - -### Relevant Articles: -- [Spring Security Registration Tutorial](http://www.baeldung.com/spring-security-registration) - - - -### Build the Project -``` -mvn clean install -``` - - -### Set up MySQL -``` -mysql -u root -p -> CREATE USER 'tutorialuser'@'localhost' IDENTIFIED BY 'tutorialmy5ql'; -> GRANT ALL PRIVILEGES ON *.* TO 'tutorialuser'@'localhost'; -> FLUSH PRIVILEGES; -``` - - -### Set up Email - -You need to configure the email by renaming file "email.properties.sample" to "email.properties" and provide your own username and password. -You also need to use your own host, you can use Amazon or Google for example. diff --git a/spring-security-login-and-registration/pom.xml b/spring-security-login-and-registration/pom.xml deleted file mode 100644 index f5b62be553..0000000000 --- a/spring-security-login-and-registration/pom.xml +++ /dev/null @@ -1,353 +0,0 @@ - - - 4.0.0 - - org.baeldung - spring-security-login-and-registration - 1.0.1-SNAPSHOT - - spring-security-login-and-registration - war - - - - - - - - - org.springframework.security - spring-security-web - ${org.springframework.security.version} - - - org.springframework.security - spring-security-config - ${org.springframework.security.version} - - - org.springframework.security - spring-security-taglibs - ${org.springframework.security.version} - - - - - - org.springframework - spring-core - ${org.springframework.version} - - - commons-logging - commons-logging - - - - - org.springframework - spring-context - ${org.springframework.version} - - - org.springframework - spring-context-support - ${org.springframework.version} - - - org.springframework - spring-jdbc - ${org.springframework.version} - - - org.springframework - spring-beans - ${org.springframework.version} - - - org.springframework - spring-aop - ${org.springframework.version} - - - org.springframework - spring-tx - ${org.springframework.version} - - - org.springframework - spring-expression - ${org.springframework.version} - - - - org.springframework - spring-web - ${org.springframework.version} - - - org.springframework - spring-webmvc - ${org.springframework.version} - - - - - javax.servlet - javax.servlet-api - ${javax.servlet.version} - provided - - - - javax.servlet - jstl - ${jstl.version} - runtime - - - - - org.springframework - spring-test - ${org.springframework.version} - test - - - - - org.passay - passay - ${passay.version} - - - - - org.springframework.data - spring-data-jpa - ${spring-data-jpa.version} - - - org.hibernate - hibernate-entitymanager - ${hibernate.version} - - - - - - - - - org.hibernate - hibernate-validator - ${hibernate-validator.version} - - - - - mysql - mysql-connector-java - ${mysql-connector-java.version} - - - commons-dbcp - commons-dbcp - ${commons-dbcp.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - javax.mail - mail - ${javax.mail.version} - - - com.google.guava - guava - ${guava.version} - - - - - org.slf4j - slf4j-api - ${org.slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - - org.slf4j - jcl-over-slf4j - ${org.slf4j.version} - - - - org.slf4j - log4j-over-slf4j - ${org.slf4j.version} - - - - - junit - junit - ${junit.version} - test - - - - org.hamcrest - hamcrest-core - ${org.hamcrest.version} - test - - - org.hamcrest - hamcrest-library - ${org.hamcrest.version} - test - - - - com.jayway.restassured - rest-assured - ${rest-assured.version} - test - - - commons-logging - commons-logging - - - - - - javax.el - el-api - 2.2 - - - - - spring-security-login-and-registration - - - src/main/resources - true - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - - - - org.apache.maven.plugins - maven-war-plugin - ${maven-war-plugin.version} - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - - - - - - - - - - org.codehaus.cargo - cargo-maven2-plugin - ${cargo-maven2-plugin.version} - - true - - jetty8x - embedded - - - - - - - 8082 - - - - - - - - - - - 1.8 - - - 4.2.4.RELEASE - 4.0.3.RELEASE - - - 4.3.11.Final - 5.2.2.Final - 5.1.37 - 1.9.2.RELEASE - - - - 1.7.13 - 1.1.3 - - - 2.3.2-b01 - 3.0.1 - 1.2 - - - 1 - - - 1.8.2.RELEASE - - - 19.0 - - 1.3 - 4.12 - 1.0 - 2.4.0 - 1.4.7 - 2.6.4 - 1.4 - - - 1.4.17 - 3.3 - 2.6 - 2.18.1 - - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/PasswordResetTokenRepository.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/PasswordResetTokenRepository.java deleted file mode 100644 index a1c22998de..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/PasswordResetTokenRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.persistence.dao; - -import org.baeldung.persistence.model.PasswordResetToken; -import org.baeldung.persistence.model.User; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface PasswordResetTokenRepository extends JpaRepository { - - PasswordResetToken findByToken(String token); - - PasswordResetToken findByUser(User user); - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java deleted file mode 100644 index f728e171df..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.persistence.dao; - -import org.baeldung.persistence.model.Privilege; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface PrivilegeRepository extends JpaRepository { - - Privilege findByName(String name); - - @Override - void delete(Privilege privilege); - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/RoleRepository.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/RoleRepository.java deleted file mode 100644 index 3d6ba16d0f..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/RoleRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.persistence.dao; - -import org.baeldung.persistence.model.Role; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface RoleRepository extends JpaRepository { - - Role findByName(String name); - - @Override - void delete(Role role); - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/UserRepository.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/UserRepository.java deleted file mode 100644 index 680b6973fa..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/UserRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.baeldung.persistence.dao; - -import org.baeldung.persistence.model.User; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface UserRepository extends JpaRepository { - User findByEmail(String email); - - @Override - void delete(User user); - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/VerificationTokenRepository.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/VerificationTokenRepository.java deleted file mode 100644 index d40a843e88..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/dao/VerificationTokenRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.persistence.dao; - -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.model.VerificationToken; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface VerificationTokenRepository extends JpaRepository { - - VerificationToken findByToken(String token); - - VerificationToken findByUser(User user); - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/PasswordResetToken.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/PasswordResetToken.java deleted file mode 100644 index fdf5473764..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/PasswordResetToken.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.baeldung.persistence.model; - -import java.util.Calendar; -import java.util.Date; - -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; - -@Entity -public class PasswordResetToken { - - private static final int EXPIRATION = 60 * 24; - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String token; - - @OneToOne(targetEntity = User.class, fetch = FetchType.EAGER) - @JoinColumn(nullable = false, name = "user_id") - private User user; - - private Date expiryDate; - - public PasswordResetToken() { - super(); - } - - public PasswordResetToken(final String token) { - super(); - - this.token = token; - this.expiryDate = calculateExpiryDate(EXPIRATION); - } - - public PasswordResetToken(final String token, final User user) { - super(); - - this.token = token; - this.user = user; - this.expiryDate = calculateExpiryDate(EXPIRATION); - } - - // - - public String getToken() { - return token; - } - - public void setToken(final String token) { - this.token = token; - } - - public User getUser() { - return user; - } - - public void setUser(final User user) { - this.user = user; - } - - public Date getExpiryDate() { - return expiryDate; - } - - public void setExpiryDate(final Date expiryDate) { - this.expiryDate = expiryDate; - } - - private Date calculateExpiryDate(final int expiryTimeInMinutes) { - final Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(new Date().getTime()); - cal.add(Calendar.MINUTE, expiryTimeInMinutes); - return new Date(cal.getTime().getTime()); - } - - public void updateToken(final String token) { - this.token = token; - this.expiryDate = calculateExpiryDate(EXPIRATION); - } - - // - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((expiryDate == null) ? 0 : expiryDate.hashCode()); - result = prime * result + ((token == null) ? 0 : token.hashCode()); - result = prime * result + ((user == null) ? 0 : user.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final PasswordResetToken other = (PasswordResetToken) obj; - if (expiryDate == null) { - if (other.expiryDate != null) { - return false; - } - } else if (!expiryDate.equals(other.expiryDate)) { - return false; - } - if (token == null) { - if (other.token != null) { - return false; - } - } else if (!token.equals(other.token)) { - return false; - } - if (user == null) { - if (other.user != null) { - return false; - } - } else if (!user.equals(other.user)) { - return false; - } - return true; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Token [String=").append(token).append("]").append("[Expires").append(expiryDate).append("]"); - return builder.toString(); - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/Privilege.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/Privilege.java deleted file mode 100644 index 1331b1985d..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/Privilege.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.baeldung.persistence.model; - -import java.util.Collection; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.ManyToMany; - -@Entity -public class Privilege { - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String name; - - @ManyToMany(mappedBy = "privileges") - private Collection roles; - - public Privilege() { - super(); - } - - public Privilege(final String name) { - super(); - this.name = name; - } - - // - - public Long getId() { - return id; - } - - public void setId(final Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - public Collection getRoles() { - return roles; - } - - public void setRoles(final Collection roles) { - this.roles = roles; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Privilege privilege = (Privilege) obj; - if (!privilege.equals(privilege.name)) { - return false; - } - return true; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Privilege [name=").append(name).append("]").append("[id=").append(id).append("]"); - return builder.toString(); - } -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/Role.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/Role.java deleted file mode 100644 index 86680252d2..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/Role.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.baeldung.persistence.model; - -import java.util.Collection; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; - -@Entity -public class Role { - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - @ManyToMany(mappedBy = "roles") - private Collection users; - - @ManyToMany - @JoinTable(name = "roles_privileges", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id") , inverseJoinColumns = @JoinColumn(name = "privilege_id", referencedColumnName = "id") ) - private Collection privileges; - - private String name; - - public Role() { - super(); - } - - public Role(final String name) { - super(); - this.name = name; - } - - // - - public Long getId() { - return id; - } - - public void setId(final Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - - public Collection getUsers() { - return users; - } - - public void setUsers(final Collection users) { - this.users = users; - } - - public Collection getPrivileges() { - return privileges; - } - - public void setPrivileges(final Collection privileges) { - this.privileges = privileges; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Role role = (Role) obj; - if (!role.equals(role.name)) { - return false; - } - return true; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Role [name=").append(name).append("]").append("[id=").append(id).append("]"); - return builder.toString(); - } -} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/User.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/User.java deleted file mode 100644 index 9640ba079b..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/User.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.baeldung.persistence.model; - -import java.util.Collection; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; - -@Entity -public class User { - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String firstName; - - private String lastName; - - private String email; - - @Column(length = 60) - private String password; - - private boolean enabled; - - private boolean tokenExpired; - - // - - @ManyToMany - @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id") , inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id") ) - private Collection roles; - - public User() { - super(); - this.enabled = false; - this.tokenExpired = false; - } - - public Long getId() { - return id; - } - - public void setId(final Long id) { - this.id = id; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(final String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(final String lastName) { - this.lastName = lastName; - } - - public String getEmail() { - return email; - } - - public void setEmail(final String username) { - this.email = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(final String password) { - this.password = password; - } - - public Collection getRoles() { - return roles; - } - - public void setRoles(final Collection roles) { - this.roles = roles; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(final boolean enabled) { - this.enabled = enabled; - } - - public boolean isTokenExpired() { - return tokenExpired; - } - - public void setTokenExpired(final boolean expired) { - this.tokenExpired = expired; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((email == null) ? 0 : email.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final User user = (User) obj; - if (!email.equals(user.email)) { - return false; - } - return true; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("User [firstName=").append(firstName).append("]").append("[lastName=").append(lastName).append("]").append("[username").append(email).append("]"); - return builder.toString(); - } - -} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/VerificationToken.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/VerificationToken.java deleted file mode 100644 index a8eb49f672..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/model/VerificationToken.java +++ /dev/null @@ -1,141 +0,0 @@ -package org.baeldung.persistence.model; - -import java.util.Calendar; -import java.util.Date; - -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; - -@Entity -public class VerificationToken { - - private static final int EXPIRATION = 60 * 24; - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String token; - - @OneToOne(targetEntity = User.class, fetch = FetchType.EAGER) - @JoinColumn(nullable = false, name = "user_id") - private User user; - - private Date expiryDate; - - public VerificationToken() { - super(); - } - - public VerificationToken(final String token) { - super(); - - this.token = token; - this.expiryDate = calculateExpiryDate(EXPIRATION); - } - - public VerificationToken(final String token, final User user) { - super(); - - this.token = token; - this.user = user; - this.expiryDate = calculateExpiryDate(EXPIRATION); - } - - public String getToken() { - return token; - } - - public void setToken(final String token) { - this.token = token; - } - - public User getUser() { - return user; - } - - public void setUser(final User user) { - this.user = user; - } - - public Date getExpiryDate() { - return expiryDate; - } - - public void setExpiryDate(final Date expiryDate) { - this.expiryDate = expiryDate; - } - - private Date calculateExpiryDate(final int expiryTimeInMinutes) { - final Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(new Date().getTime()); - cal.add(Calendar.MINUTE, expiryTimeInMinutes); - return new Date(cal.getTime().getTime()); - } - - public void updateToken(final String token) { - this.token = token; - this.expiryDate = calculateExpiryDate(EXPIRATION); - } - - // - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((expiryDate == null) ? 0 : expiryDate.hashCode()); - result = prime * result + ((token == null) ? 0 : token.hashCode()); - result = prime * result + ((user == null) ? 0 : user.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final VerificationToken other = (VerificationToken) obj; - if (expiryDate == null) { - if (other.expiryDate != null) { - return false; - } - } else if (!expiryDate.equals(other.expiryDate)) { - return false; - } - if (token == null) { - if (other.token != null) { - return false; - } - } else if (!token.equals(other.token)) { - return false; - } - if (user == null) { - if (other.user != null) { - return false; - } - } else if (!user.equals(other.user)) { - return false; - } - return true; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Token [String=").append(token).append("]").append("[Expires").append(expiryDate).append("]"); - return builder.toString(); - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/service/IUserService.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/service/IUserService.java deleted file mode 100644 index 9fa97395fa..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/service/IUserService.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.baeldung.persistence.service; - -import org.baeldung.persistence.model.PasswordResetToken; -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.model.VerificationToken; -import org.baeldung.validation.EmailExistsException; - -public interface IUserService { - - User registerNewUserAccount(UserDto accountDto) throws EmailExistsException; - - User getUser(String verificationToken); - - void saveRegisteredUser(User user); - - void deleteUser(User user); - - void createVerificationTokenForUser(User user, String token); - - VerificationToken getVerificationToken(String VerificationToken); - - VerificationToken generateNewVerificationToken(String token); - - void createPasswordResetTokenForUser(User user, String token); - - User findUserByEmail(String email); - - PasswordResetToken getPasswordResetToken(String token); - - User getUserByPasswordResetToken(String token); - - User getUserByID(long id); - - void changeUserPassword(User user, String password); - - boolean checkIfValidOldPassword(User user, String password); - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/service/UserDto.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/service/UserDto.java deleted file mode 100644 index 627aac81c4..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/service/UserDto.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.baeldung.persistence.service; - -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -import org.baeldung.validation.PasswordMatches; -import org.baeldung.validation.ValidEmail; -import org.baeldung.validation.ValidPassword; - -@PasswordMatches -public class UserDto { - @NotNull - @Size(min = 1) - private String firstName; - - @NotNull - @Size(min = 1) - private String lastName; - - @ValidPassword - private String password; - - @NotNull - @Size(min = 1) - private String matchingPassword; - - @ValidEmail - @NotNull - @Size(min = 1) - private String email; - - public String getEmail() { - return email; - } - - public void setEmail(final String email) { - this.email = email; - } - - private Integer role; - - public Integer getRole() { - return role; - } - - public void setRole(final Integer role) { - this.role = role; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(final String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(final String lastName) { - this.lastName = lastName; - } - - public String getPassword() { - return password; - } - - public void setPassword(final String password) { - this.password = password; - } - - public String getMatchingPassword() { - return matchingPassword; - } - - public void setMatchingPassword(final String matchingPassword) { - this.matchingPassword = matchingPassword; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("User [firstName=").append(firstName).append("]").append("[lastName=").append(lastName).append("]").append("[email").append(email).append("]").append("[password").append(password).append("]"); - return builder.toString(); - } -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/service/UserService.java b/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/service/UserService.java deleted file mode 100644 index fafe52953f..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/persistence/service/UserService.java +++ /dev/null @@ -1,136 +0,0 @@ -package org.baeldung.persistence.service; - -import java.util.Arrays; -import java.util.UUID; - -import javax.transaction.Transactional; - -import org.baeldung.persistence.dao.PasswordResetTokenRepository; -import org.baeldung.persistence.dao.RoleRepository; -import org.baeldung.persistence.dao.UserRepository; -import org.baeldung.persistence.dao.VerificationTokenRepository; -import org.baeldung.persistence.model.PasswordResetToken; -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.model.VerificationToken; -import org.baeldung.validation.EmailExistsException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; - -@Service -@Transactional -public class UserService implements IUserService { - @Autowired - private UserRepository repository; - - @Autowired - private VerificationTokenRepository tokenRepository; - - @Autowired - private PasswordResetTokenRepository passwordTokenRepository; - - @Autowired - private PasswordEncoder passwordEncoder; - - @Autowired - private RoleRepository roleRepository; - - // API - - @Override - public User registerNewUserAccount(final UserDto accountDto) throws EmailExistsException { - if (emailExist(accountDto.getEmail())) { - throw new EmailExistsException("There is an account with that email adress: " + accountDto.getEmail()); - } - final User user = new User(); - - user.setFirstName(accountDto.getFirstName()); - user.setLastName(accountDto.getLastName()); - user.setPassword(passwordEncoder.encode(accountDto.getPassword())); - user.setEmail(accountDto.getEmail()); - - user.setRoles(Arrays.asList(roleRepository.findByName("ROLE_USER"))); - return repository.save(user); - } - - @Override - public User getUser(final String verificationToken) { - final User user = tokenRepository.findByToken(verificationToken).getUser(); - return user; - } - - @Override - public VerificationToken getVerificationToken(final String VerificationToken) { - return tokenRepository.findByToken(VerificationToken); - } - - @Override - public void saveRegisteredUser(final User user) { - repository.save(user); - } - - @Override - public void deleteUser(final User user) { - repository.delete(user); - } - - @Override - public void createVerificationTokenForUser(final User user, final String token) { - final VerificationToken myToken = new VerificationToken(token, user); - tokenRepository.save(myToken); - } - - @Override - public VerificationToken generateNewVerificationToken(final String existingVerificationToken) { - VerificationToken vToken = tokenRepository.findByToken(existingVerificationToken); - vToken.updateToken(UUID.randomUUID().toString()); - vToken = tokenRepository.save(vToken); - return vToken; - } - - @Override - public void createPasswordResetTokenForUser(final User user, final String token) { - final PasswordResetToken myToken = new PasswordResetToken(token, user); - passwordTokenRepository.save(myToken); - } - - @Override - public User findUserByEmail(final String email) { - return repository.findByEmail(email); - } - - @Override - public PasswordResetToken getPasswordResetToken(final String token) { - return passwordTokenRepository.findByToken(token); - } - - @Override - public User getUserByPasswordResetToken(final String token) { - return passwordTokenRepository.findByToken(token).getUser(); - } - - @Override - public User getUserByID(final long id) { - return repository.findOne(id); - } - - @Override - public void changeUserPassword(final User user, final String password) { - user.setPassword(passwordEncoder.encode(password)); - repository.save(user); - } - - @Override - public boolean checkIfValidOldPassword(final User user, final String oldPassword) { - return passwordEncoder.matches(oldPassword, user.getPassword()); - } - - private boolean emailExist(final String email) { - final User user = repository.findByEmail(email); - if (user != null) { - return true; - } - return false; - } - -} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/registration/OnRegistrationCompleteEvent.java b/spring-security-login-and-registration/src/main/java/org/baeldung/registration/OnRegistrationCompleteEvent.java deleted file mode 100644 index 75433f1286..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/registration/OnRegistrationCompleteEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.baeldung.registration; - -import java.util.Locale; - -import org.baeldung.persistence.model.User; -import org.springframework.context.ApplicationEvent; - -@SuppressWarnings("serial") -public class OnRegistrationCompleteEvent extends ApplicationEvent { - - private final String appUrl; - private final Locale locale; - private final User user; - - public OnRegistrationCompleteEvent(final User user, final Locale locale, final String appUrl) { - super(user); - this.user = user; - this.locale = locale; - this.appUrl = appUrl; - } - - // - - public String getAppUrl() { - return appUrl; - } - - public Locale getLocale() { - return locale; - } - - public User getUser() { - return user; - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/registration/listener/RegistrationListener.java b/spring-security-login-and-registration/src/main/java/org/baeldung/registration/listener/RegistrationListener.java deleted file mode 100644 index 0a3689f670..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/registration/listener/RegistrationListener.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.baeldung.registration.listener; - -import java.util.UUID; - -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.service.IUserService; -import org.baeldung.registration.OnRegistrationCompleteEvent; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationListener; -import org.springframework.context.MessageSource; -import org.springframework.core.env.Environment; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.stereotype.Component; - -@Component -public class RegistrationListener implements ApplicationListener { - @Autowired - private IUserService service; - - @Autowired - private MessageSource messages; - - @Autowired - private JavaMailSender mailSender; - - @Autowired - private Environment env; - - // API - - @Override - public void onApplicationEvent(final OnRegistrationCompleteEvent event) { - this.confirmRegistration(event); - } - - private void confirmRegistration(final OnRegistrationCompleteEvent event) { - final User user = event.getUser(); - final String token = UUID.randomUUID().toString(); - service.createVerificationTokenForUser(user, token); - - final SimpleMailMessage email = constructEmailMessage(event, user, token); - mailSender.send(email); - } - - // - - private final SimpleMailMessage constructEmailMessage(final OnRegistrationCompleteEvent event, final User user, final String token) { - final String recipientAddress = user.getEmail(); - final String subject = "Registration Confirmation"; - final String confirmationUrl = event.getAppUrl() + "/regitrationConfirm.html?token=" + token; - final String message = messages.getMessage("message.regSucc", null, event.getLocale()); - final SimpleMailMessage email = new SimpleMailMessage(); - email.setTo(recipientAddress); - email.setSubject(subject); - email.setText(message + " \r\n" + confirmationUrl); - email.setFrom(env.getProperty("support.email")); - return email; - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/security/AuthenticationFailureListener.java b/spring-security-login-and-registration/src/main/java/org/baeldung/security/AuthenticationFailureListener.java deleted file mode 100644 index aad26eebb7..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/security/AuthenticationFailureListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.security; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationListener; -import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent; -import org.springframework.security.web.authentication.WebAuthenticationDetails; -import org.springframework.stereotype.Component; - -@Component -public class AuthenticationFailureListener implements ApplicationListener { - - @Autowired - private LoginAttemptService loginAttemptService; - - @Override - public void onApplicationEvent(final AuthenticationFailureBadCredentialsEvent e) { - final WebAuthenticationDetails auth = (WebAuthenticationDetails) e.getAuthentication().getDetails(); - if (auth != null) { - loginAttemptService.loginFailed(auth.getRemoteAddress()); - } - } - -} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/security/AuthenticationSuccessEventListener.java b/spring-security-login-and-registration/src/main/java/org/baeldung/security/AuthenticationSuccessEventListener.java deleted file mode 100644 index bd4c69faa8..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/security/AuthenticationSuccessEventListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.security; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationListener; -import org.springframework.security.authentication.event.AuthenticationSuccessEvent; -import org.springframework.security.web.authentication.WebAuthenticationDetails; -import org.springframework.stereotype.Component; - -@Component -public class AuthenticationSuccessEventListener implements ApplicationListener { - - @Autowired - private LoginAttemptService loginAttemptService; - - @Override - public void onApplicationEvent(final AuthenticationSuccessEvent e) { - final WebAuthenticationDetails auth = (WebAuthenticationDetails) e.getAuthentication().getDetails(); - if (auth != null) { - loginAttemptService.loginSucceeded(auth.getRemoteAddress()); - } - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/security/CustomAuthenticationFailureHandler.java b/spring-security-login-and-registration/src/main/java/org/baeldung/security/CustomAuthenticationFailureHandler.java deleted file mode 100644 index 94440f8a89..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/security/CustomAuthenticationFailureHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.baeldung.security; - -import java.io.IOException; -import java.util.Locale; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.MessageSource; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.WebAttributes; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.LocaleResolver; - -@Component("authenticationFailureHandler") -public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { - - @Autowired - private MessageSource messages; - - @Autowired - private LocaleResolver localeResolver; - - @Override - public void onAuthenticationFailure(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException exception) throws IOException, ServletException { - setDefaultFailureUrl("/login.html?error=true"); - - super.onAuthenticationFailure(request, response, exception); - - final Locale locale = localeResolver.resolveLocale(request); - - String errorMessage = messages.getMessage("message.badCredentials", null, locale); - - if (exception.getMessage().equalsIgnoreCase("User is disabled")) { - errorMessage = messages.getMessage("auth.message.disabled", null, locale); - } else if (exception.getMessage().equalsIgnoreCase("User account has expired")) { - errorMessage = messages.getMessage("auth.message.expired", null, locale); - } else if (exception.getMessage().equalsIgnoreCase("blocked")) { - errorMessage = messages.getMessage("auth.message.blocked", null, locale); - } - - request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, errorMessage); - } -} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/security/LoginAttemptService.java b/spring-security-login-and-registration/src/main/java/org/baeldung/security/LoginAttemptService.java deleted file mode 100644 index 26eeee53f2..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/security/LoginAttemptService.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.baeldung.security; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -import org.springframework.stereotype.Service; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; - -@Service -public class LoginAttemptService { - - private final int MAX_ATTEMPT = 10; - private LoadingCache attemptsCache; - - public LoginAttemptService() { - super(); - attemptsCache = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.DAYS).build(new CacheLoader() { - @Override - public Integer load(final String key) { - return 0; - } - }); - } - - // - - public void loginSucceeded(final String key) { - attemptsCache.invalidate(key); - } - - public void loginFailed(final String key) { - int attempts = 0; - try { - attempts = attemptsCache.get(key); - } catch (final ExecutionException e) { - attempts = 0; - } - attempts++; - attemptsCache.put(key, attempts); - } - - public boolean isBlocked(final String key) { - try { - return attemptsCache.get(key) >= MAX_ATTEMPT; - } catch (final ExecutionException e) { - return false; - } - } -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java b/spring-security-login-and-registration/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java deleted file mode 100644 index 37703d9a09..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.baeldung.security; - -import java.io.IOException; -import java.util.Collection; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.web.DefaultRedirectStrategy; -import org.springframework.security.web.RedirectStrategy; -import org.springframework.security.web.WebAttributes; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import org.springframework.stereotype.Component; - -@Component("myAuthenticationSuccessHandler") -public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler { - private final Logger logger = LoggerFactory.getLogger(getClass()); - - private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); - - @Override - public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws IOException { - handle(request, response, authentication); - final HttpSession session = request.getSession(false); - if (session != null) { - session.setMaxInactiveInterval(30 * 60); - } - clearAuthenticationAttributes(request); - } - - protected void handle(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws IOException { - final String targetUrl = determineTargetUrl(authentication); - - if (response.isCommitted()) { - logger.debug("Response has already been committed. Unable to redirect to " + targetUrl); - return; - } - - redirectStrategy.sendRedirect(request, response, targetUrl); - } - - protected String determineTargetUrl(final Authentication authentication) { - boolean isUser = false; - boolean isAdmin = false; - final Collection authorities = authentication.getAuthorities(); - for (final GrantedAuthority grantedAuthority : authorities) { - if (grantedAuthority.getAuthority().equals("READ_PRIVILEGE")) { - isUser = true; - } else if (grantedAuthority.getAuthority().equals("WRITE_PRIVILEGE")) { - isAdmin = true; - isUser = false; - break; - } - } - if (isUser) { - return "/homepage.html?user=" + authentication.getName(); - } else if (isAdmin) { - return "/console.html"; - } else { - throw new IllegalStateException(); - } - } - - protected void clearAuthenticationAttributes(final HttpServletRequest request) { - final HttpSession session = request.getSession(false); - if (session == null) { - return; - } - session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); - } - - public void setRedirectStrategy(final RedirectStrategy redirectStrategy) { - this.redirectStrategy = redirectStrategy; - } - - protected RedirectStrategy getRedirectStrategy() { - return redirectStrategy; - } -} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/security/MyUserDetailsService.java b/spring-security-login-and-registration/src/main/java/org/baeldung/security/MyUserDetailsService.java deleted file mode 100644 index d4b77878be..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/security/MyUserDetailsService.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.baeldung.security; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - -import org.baeldung.persistence.dao.UserRepository; -import org.baeldung.persistence.model.Privilege; -import org.baeldung.persistence.model.Role; -import org.baeldung.persistence.model.User; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service("userDetailsService") -@Transactional -public class MyUserDetailsService implements UserDetailsService { - - @Autowired - private UserRepository userRepository; - - @Autowired - private LoginAttemptService loginAttemptService; - - @Autowired - private HttpServletRequest request; - - public MyUserDetailsService() { - super(); - } - - // API - - @Override - public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException { - final String ip = getClientIP(); - if (loginAttemptService.isBlocked(ip)) { - throw new RuntimeException("blocked"); - } - - try { - final User user = userRepository.findByEmail(email); - if (user == null) { - throw new UsernameNotFoundException("No user found with username: " + email); - } - - return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), user.isEnabled(), true, true, true, getAuthorities(user.getRoles())); - } catch (final Exception e) { - throw new RuntimeException(e); - } - } - - // UTIL - - public final Collection getAuthorities(final Collection roles) { - return getGrantedAuthorities(getPrivileges(roles)); - } - - private final List getPrivileges(final Collection roles) { - final List privileges = new ArrayList(); - final List collection = new ArrayList(); - for (final Role role : roles) { - collection.addAll(role.getPrivileges()); - } - for (final Privilege item : collection) { - privileges.add(item.getName()); - } - return privileges; - } - - private final List getGrantedAuthorities(final List privileges) { - final List authorities = new ArrayList(); - for (final String privilege : privileges) { - authorities.add(new SimpleGrantedAuthority(privilege)); - } - return authorities; - } - - private String getClientIP() { - final String xfHeader = request.getHeader("X-Forwarded-For"); - if (xfHeader == null) { - return request.getRemoteAddr(); - } - return xfHeader.split(",")[0]; - } -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/AppConfig.java b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/AppConfig.java deleted file mode 100644 index cba2b25285..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/AppConfig.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.baeldung.spring; - -import java.util.Properties; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; -import org.springframework.core.env.Environment; -import org.springframework.mail.javamail.JavaMailSenderImpl; - -@Configuration -@ComponentScan(basePackages = { "org.baeldung.registration" }) -@PropertySource("classpath:email.properties") -public class AppConfig { - - @Autowired - private Environment env; - - // beans - - @Bean - public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() { - return new PropertySourcesPlaceholderConfigurer(); - } - - @Bean - public JavaMailSenderImpl javaMailSenderImpl() { - final JavaMailSenderImpl mailSenderImpl = new JavaMailSenderImpl(); - mailSenderImpl.setHost(env.getProperty("smtp.host")); - mailSenderImpl.setPort(env.getProperty("smtp.port", Integer.class)); - mailSenderImpl.setProtocol(env.getProperty("smtp.protocol")); - mailSenderImpl.setUsername(env.getProperty("smtp.username")); - mailSenderImpl.setPassword(env.getProperty("smtp.password")); - final Properties javaMailProps = new Properties(); - javaMailProps.put("mail.smtp.auth", true); - javaMailProps.put("mail.smtp.starttls.enable", true); - mailSenderImpl.setJavaMailProperties(javaMailProps); - return mailSenderImpl; - } - -} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java deleted file mode 100644 index 1234cde0d0..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.baeldung.spring; - -import java.util.Locale; - -import org.baeldung.validation.EmailValidator; -import org.baeldung.validation.PasswordMatchesValidator; -import org.springframework.context.MessageSource; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.ReloadableResourceBundleMessageSource; -import org.springframework.web.servlet.LocaleResolver; -import org.springframework.web.servlet.ViewResolver; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -import org.springframework.web.servlet.i18n.CookieLocaleResolver; -import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; -import org.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.JstlView; - -@Configuration -@ComponentScan(basePackages = { "org.baeldung.web" }) -@EnableWebMvc -public class MvcConfig extends WebMvcConfigurerAdapter { - - public MvcConfig() { - super(); - } - - // - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); - registry.addViewController("/login"); - registry.addViewController("/registration.html"); - registry.addViewController("/logout.html"); - registry.addViewController("/homepage.html"); - registry.addViewController("/expiredAccount.html"); - registry.addViewController("/badUser.html"); - registry.addViewController("/emailError.html"); - registry.addViewController("/home.html"); - registry.addViewController("/invalidSession.html"); - registry.addViewController("/console.html"); - registry.addViewController("/admin.html"); - registry.addViewController("/successRegister.html"); - registry.addViewController("/forgetPassword.html"); - registry.addViewController("/updatePassword.html"); - registry.addViewController("/changePassword.html"); - } - - @Override - public void addResourceHandlers(final ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**").addResourceLocations("/", "/resources/"); - } - - @Override - public void addInterceptors(final InterceptorRegistry registry) { - final LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); - localeChangeInterceptor.setParamName("lang"); - registry.addInterceptor(localeChangeInterceptor); - } - - // beans - - @Bean - public ViewResolver viewResolver() { - final InternalResourceViewResolver bean = new InternalResourceViewResolver(); - bean.setViewClass(JstlView.class); - bean.setPrefix("/WEB-INF/view/"); - bean.setSuffix(".jsp"); - return bean; - } - - @Bean - public LocaleResolver localeResolver() { - final CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver(); - cookieLocaleResolver.setDefaultLocale(Locale.ENGLISH); - return cookieLocaleResolver; - } - - @Bean - public MessageSource messageSource() { - final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); - messageSource.setBasename("classpath:messages"); - messageSource.setUseCodeAsDefaultMessage(true); - messageSource.setDefaultEncoding("UTF-8"); - messageSource.setCacheSeconds(0); - return messageSource; - } - - @Bean - public EmailValidator usernameValidator() { - return new EmailValidator(); - } - - @Bean - public PasswordMatchesValidator passwordMatchesValidator() { - return new PasswordMatchesValidator(); - } - -} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/PersistenceJPAConfig.java b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/PersistenceJPAConfig.java deleted file mode 100644 index cb00353fe8..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/PersistenceJPAConfig.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.baeldung.spring; - -import java.util.Properties; - -import javax.sql.DataSource; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -import org.springframework.core.env.Environment; -import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; -import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -@Configuration -@EnableTransactionManagement -@PropertySource({ "classpath:persistence.properties" }) -@ComponentScan({ "org.baeldung.persistence" }) -@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao") -public class PersistenceJPAConfig { - - @Autowired - private Environment env; - - public PersistenceJPAConfig() { - super(); - } - - // - - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); - em.setDataSource(dataSource()); - em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); - final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); - em.setJpaVendorAdapter(vendorAdapter); - em.setJpaProperties(additionalProperties()); - return em; - } - - @Bean - public DataSource dataSource() { - final DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); - dataSource.setUrl(env.getProperty("jdbc.url")); - dataSource.setUsername(env.getProperty("jdbc.user")); - dataSource.setPassword(env.getProperty("jdbc.pass")); - return dataSource; - } - - @Bean - public JpaTransactionManager transactionManager() { - final JpaTransactionManager transactionManager = new JpaTransactionManager(); - transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); - return transactionManager; - } - - @Bean - public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { - return new PersistenceExceptionTranslationPostProcessor(); - } - - final Properties additionalProperties() { - final Properties hibernateProperties = new Properties(); - hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); - hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); - return hibernateProperties; - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/SecSecurityConfig.java b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/SecSecurityConfig.java deleted file mode 100644 index 9ae8f6e78b..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/SecSecurityConfig.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.baeldung.spring; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.dao.DaoAuthenticationProvider; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.builders.WebSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.authentication.AuthenticationFailureHandler; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; - -@Configuration -@ComponentScan(basePackages = { "org.baeldung.security" }) -// @ImportResource({ "classpath:webSecurityConfig.xml" }) -@EnableWebSecurity -public class SecSecurityConfig extends WebSecurityConfigurerAdapter { - - @Autowired - private UserDetailsService userDetailsService; - - @Autowired - private AuthenticationSuccessHandler myAuthenticationSuccessHandler; - - @Autowired - private AuthenticationFailureHandler authenticationFailureHandler; - - public SecSecurityConfig() { - super(); - } - - @Override - protected void configure(final AuthenticationManagerBuilder auth) throws Exception { - auth.authenticationProvider(authProvider()); - } - - @Override - public void configure(final WebSecurity web) throws Exception { - web.ignoring().antMatchers("/resources/**"); - } - - @Override - protected void configure(final HttpSecurity http) throws Exception { - // @formatter:off - http - .csrf().disable() - .authorizeRequests() - .antMatchers("/login*","/login*", "/logout*", "/signin/**", "/signup/**", - "/user/registration*", "/regitrationConfirm*", "/expiredAccount*", "/registration*", - "/badUser*", "/user/resendRegistrationToken*" ,"/forgetPassword*", "/user/resetPassword*", - "/user/changePassword*", "/emailError*", "/resources/**","/old/user/registration*","/successRegister*").permitAll() - .antMatchers("/invalidSession*").anonymous() - .anyRequest().authenticated() - .and() - .formLogin() - .loginPage("/login") - .defaultSuccessUrl("/homepage.html") - .failureUrl("/login?error=true") - .successHandler(myAuthenticationSuccessHandler) - .failureHandler(authenticationFailureHandler) - .permitAll() - .and() - .sessionManagement() - .invalidSessionUrl("/invalidSession.html") - .sessionFixation().none() - .and() - .logout() - .invalidateHttpSession(false) - .logoutSuccessUrl("/logout.html?logSucc=true") - .deleteCookies("JSESSIONID") - .permitAll(); - // @formatter:on - } - - // beans - - @Bean - public DaoAuthenticationProvider authProvider() { - final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); - authProvider.setUserDetailsService(userDetailsService); - authProvider.setPasswordEncoder(encoder()); - return authProvider; - } - - @Bean - public PasswordEncoder encoder() { - return new BCryptPasswordEncoder(11); - } - -} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/SetupDataLoader.java b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/SetupDataLoader.java deleted file mode 100644 index 9f785b3239..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/SetupDataLoader.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.baeldung.spring; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import org.baeldung.persistence.dao.PrivilegeRepository; -import org.baeldung.persistence.dao.RoleRepository; -import org.baeldung.persistence.dao.UserRepository; -import org.baeldung.persistence.model.Privilege; -import org.baeldung.persistence.model.Role; -import org.baeldung.persistence.model.User; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -@Component -public class SetupDataLoader implements ApplicationListener { - - private boolean alreadySetup = false; - - @Autowired - private UserRepository userRepository; - - @Autowired - private RoleRepository roleRepository; - - @Autowired - private PrivilegeRepository privilegeRepository; - - @Autowired - private PasswordEncoder passwordEncoder; - - // API - - @Override - @Transactional - public void onApplicationEvent(final ContextRefreshedEvent event) { - if (alreadySetup) { - return; - } - - // == create initial privileges - final Privilege readPrivilege = createPrivilegeIfNotFound("READ_PRIVILEGE"); - final Privilege writePrivilege = createPrivilegeIfNotFound("WRITE_PRIVILEGE"); - - // == create initial roles - final List adminPrivileges = Arrays.asList(readPrivilege, writePrivilege); - createRoleIfNotFound("ROLE_ADMIN", adminPrivileges); - createRoleIfNotFound("ROLE_USER", Arrays.asList(readPrivilege)); - - final Role adminRole = roleRepository.findByName("ROLE_ADMIN"); - final User user = new User(); - user.setFirstName("Test"); - user.setLastName("Test"); - user.setPassword(passwordEncoder.encode("test")); - user.setEmail("test@test.com"); - user.setRoles(Arrays.asList(adminRole)); - user.setEnabled(true); - userRepository.save(user); - - alreadySetup = true; - } - - @Transactional - private final Privilege createPrivilegeIfNotFound(final String name) { - Privilege privilege = privilegeRepository.findByName(name); - if (privilege == null) { - privilege = new Privilege(name); - privilegeRepository.save(privilege); - } - return privilege; - } - - @Transactional - private final Role createRoleIfNotFound(final String name, final Collection privileges) { - Role role = roleRepository.findByName(name); - if (role == null) { - role = new Role(name); - role.setPrivileges(privileges); - roleRepository.save(role); - } - return role; - } - -} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/test/TestConfig.java b/spring-security-login-and-registration/src/main/java/org/baeldung/test/TestConfig.java deleted file mode 100644 index 97b2c20632..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/test/TestConfig.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.baeldung.test; - -import org.baeldung.spring.PersistenceJPAConfig; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; - -@ComponentScan({ "org.baeldung.persistence.dao" }) -public class TestConfig extends PersistenceJPAConfig { - - @Bean - public PasswordEncoder encoder() { - return new BCryptPasswordEncoder(11); - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/EmailExistsException.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/EmailExistsException.java deleted file mode 100644 index 554dfe7cbc..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/EmailExistsException.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.baeldung.validation; - -@SuppressWarnings("serial") -public class EmailExistsException extends Throwable { - - public EmailExistsException(final String message) { - super(message); - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/EmailValidator.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/EmailValidator.java deleted file mode 100644 index ee2801eba0..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/EmailValidator.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.baeldung.validation; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -public class EmailValidator implements ConstraintValidator { - private Pattern pattern; - private Matcher matcher; - private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; - - @Override - public void initialize(final ValidEmail constraintAnnotation) { - } - - @Override - public boolean isValid(final String username, final ConstraintValidatorContext context) { - return (validateEmail(username)); - } - - private boolean validateEmail(final String email) { - pattern = Pattern.compile(EMAIL_PATTERN); - matcher = pattern.matcher(email); - return matcher.matches(); - } -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordConstraintValidator.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordConstraintValidator.java deleted file mode 100644 index 80d06a0f69..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordConstraintValidator.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.baeldung.validation; - -import java.util.Arrays; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -import org.passay.DigitCharacterRule; -import org.passay.LengthRule; -import org.passay.PasswordData; -import org.passay.PasswordValidator; -import org.passay.RuleResult; -import org.passay.SpecialCharacterRule; -import org.passay.UppercaseCharacterRule; -import org.passay.WhitespaceRule; - -import com.google.common.base.Joiner; - -public class PasswordConstraintValidator implements ConstraintValidator { - - @Override - public void initialize(final ValidPassword arg0) { - - } - - @Override - public boolean isValid(final String password, final ConstraintValidatorContext context) { - final PasswordValidator validator = new PasswordValidator(Arrays.asList(new LengthRule(8, 30), new UppercaseCharacterRule(1), new DigitCharacterRule(1), new SpecialCharacterRule(1), new WhitespaceRule())); - final RuleResult result = validator.validate(new PasswordData(password)); - if (result.isValid()) { - return true; - } - context.disableDefaultConstraintViolation(); - context.buildConstraintViolationWithTemplate(Joiner.on("\n").join(validator.getMessages(result))).addConstraintViolation(); - return false; - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordMatches.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordMatches.java deleted file mode 100644 index fcc7e228a7..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordMatches.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.baeldung.validation; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; - -@Target({ TYPE, ANNOTATION_TYPE }) -@Retention(RUNTIME) -@Constraint(validatedBy = PasswordMatchesValidator.class) -@Documented -public @interface PasswordMatches { - - String message() default "Passwords don't match"; - - Class[] groups() default {}; - - Class[] payload() default {}; - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordMatchesValidator.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordMatchesValidator.java deleted file mode 100644 index a103b91e90..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordMatchesValidator.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.baeldung.validation; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -import org.baeldung.persistence.service.UserDto; - -public class PasswordMatchesValidator implements ConstraintValidator { - - @Override - public void initialize(final PasswordMatches constraintAnnotation) { - // - } - - @Override - public boolean isValid(final Object obj, final ConstraintValidatorContext context) { - final UserDto user = (UserDto) obj; - return user.getPassword().equals(user.getMatchingPassword()); - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/UserValidator.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/UserValidator.java deleted file mode 100644 index 76348bee7e..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/UserValidator.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.validation; - -import org.baeldung.persistence.service.UserDto; -import org.springframework.validation.Errors; -import org.springframework.validation.ValidationUtils; -import org.springframework.validation.Validator; - -public class UserValidator implements Validator { - - @Override - public boolean supports(final Class clazz) { - return UserDto.class.isAssignableFrom(clazz); - } - - @Override - public void validate(final Object obj, final Errors errors) { - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "message.firstName", "Firstname is required."); - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "message.lastName", "LastName is required."); - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "message.password", "LastName is required."); - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "message.username", "UserName is required."); - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidEmail.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidEmail.java deleted file mode 100644 index a520a45b0c..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidEmail.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.baeldung.validation; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; - -@Target({ TYPE, FIELD, ANNOTATION_TYPE }) -@Retention(RUNTIME) -@Constraint(validatedBy = EmailValidator.class) -@Documented -public @interface ValidEmail { - - String message() default "Invalid Email"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidPassword.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidPassword.java deleted file mode 100644 index 37b217213a..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidPassword.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.baeldung.validation; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.validation.Constraint; -import javax.validation.Payload; - -@Documented -@Constraint(validatedBy = PasswordConstraintValidator.class) -@Target({ TYPE, FIELD, ANNOTATION_TYPE }) -@Retention(RUNTIME) -public @interface ValidPassword { - - String message() default "Invalid Password"; - - Class[] groups() default {}; - - Class[] payload() default {}; - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/web/controller/OldRegistrationController.java b/spring-security-login-and-registration/src/main/java/org/baeldung/web/controller/OldRegistrationController.java deleted file mode 100644 index dc14ad70a1..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/web/controller/OldRegistrationController.java +++ /dev/null @@ -1,237 +0,0 @@ -package org.baeldung.web.controller; - -import java.util.Calendar; -import java.util.Locale; -import java.util.UUID; - -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; - -import org.baeldung.persistence.model.PasswordResetToken; -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.model.VerificationToken; -import org.baeldung.persistence.service.IUserService; -import org.baeldung.persistence.service.UserDto; -import org.baeldung.registration.OnRegistrationCompleteEvent; -import org.baeldung.validation.EmailExistsException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.MessageSource; -import org.springframework.core.env.Environment; -import org.springframework.mail.MailAuthenticationException; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.validation.Errors; -import org.springframework.web.bind.annotation.ModelAttribute; -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.servlet.ModelAndView; - -@Controller -@RequestMapping(value = "/old") -public class OldRegistrationController { - private final Logger LOGGER = LoggerFactory.getLogger(getClass()); - - @Autowired - private IUserService userService; - - @Autowired - private MessageSource messages; - - @Autowired - private JavaMailSender mailSender; - - @Autowired - private ApplicationEventPublisher eventPublisher; - - @Autowired - private UserDetailsService userDetailsService; - - @Autowired - private Environment env; - - public OldRegistrationController() { - super(); - } - - // API - - @RequestMapping(value = "/user/registration", method = RequestMethod.GET) - public String showRegistrationForm(final HttpServletRequest request, final Model model) { - LOGGER.debug("Rendering registration page."); - final UserDto accountDto = new UserDto(); - model.addAttribute("user", accountDto); - return "registration"; - } - - @RequestMapping(value = "/regitrationConfirm", method = RequestMethod.GET) - public String confirmRegistration(final HttpServletRequest request, final Model model, @RequestParam("token") final String token) { - final Locale locale = request.getLocale(); - - final VerificationToken verificationToken = userService.getVerificationToken(token); - if (verificationToken == null) { - final String message = messages.getMessage("auth.message.invalidToken", null, locale); - model.addAttribute("message", message); - return "redirect:/badUser.html?lang=" + locale.getLanguage(); - } - - final User user = verificationToken.getUser(); - final Calendar cal = Calendar.getInstance(); - if ((verificationToken.getExpiryDate().getTime() - cal.getTime().getTime()) <= 0) { - model.addAttribute("message", messages.getMessage("auth.message.expired", null, locale)); - model.addAttribute("expired", true); - model.addAttribute("token", token); - return "redirect:/badUser.html?lang=" + locale.getLanguage(); - } - - user.setEnabled(true); - userService.saveRegisteredUser(user); - model.addAttribute("message", messages.getMessage("message.accountVerified", null, locale)); - return "redirect:/login.html?lang=" + locale.getLanguage(); - } - - @RequestMapping(value = "/user/registration", method = RequestMethod.POST) - public ModelAndView registerUserAccount(@ModelAttribute("user") @Valid final UserDto userDto, final HttpServletRequest request, final Errors errors) { - LOGGER.debug("Registering user account with information: {}", userDto); - - final User registered = createUserAccount(userDto); - if (registered == null) { - // result.rejectValue("email", "message.regError"); - return new ModelAndView("registration", "user", userDto); - } - try { - final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); - eventPublisher.publishEvent(new OnRegistrationCompleteEvent(registered, request.getLocale(), appUrl)); - } catch (final Exception ex) { - LOGGER.warn("Unable to register user", ex); - return new ModelAndView("emailError", "user", userDto); - } - return new ModelAndView("successRegister", "user", userDto); - } - - @RequestMapping(value = "/user/resendRegistrationToken", method = RequestMethod.GET) - public String resendRegistrationToken(final HttpServletRequest request, final Model model, @RequestParam("token") final String existingToken) { - final Locale locale = request.getLocale(); - final VerificationToken newToken = userService.generateNewVerificationToken(existingToken); - final User user = userService.getUser(newToken.getToken()); - try { - final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); - final SimpleMailMessage email = constructResetVerificationTokenEmail(appUrl, request.getLocale(), newToken, user); - mailSender.send(email); - } catch (final MailAuthenticationException e) { - LOGGER.debug("MailAuthenticationException", e); - return "redirect:/emailError.html?lang=" + locale.getLanguage(); - } catch (final Exception e) { - LOGGER.debug(e.getLocalizedMessage(), e); - model.addAttribute("message", e.getLocalizedMessage()); - return "redirect:/login.html?lang=" + locale.getLanguage(); - } - model.addAttribute("message", messages.getMessage("message.resendToken", null, locale)); - return "redirect:/login.html?lang=" + locale.getLanguage(); - } - - @RequestMapping(value = "/user/resetPassword", method = RequestMethod.POST) - public String resetPassword(final HttpServletRequest request, final Model model, @RequestParam("email") final String userEmail) { - final User user = userService.findUserByEmail(userEmail); - if (user == null) { - model.addAttribute("message", messages.getMessage("message.userNotFound", null, request.getLocale())); - return "redirect:/login.html?lang=" + request.getLocale().getLanguage(); - } - - final String token = UUID.randomUUID().toString(); - userService.createPasswordResetTokenForUser(user, token); - try { - final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); - final SimpleMailMessage email = constructResetTokenEmail(appUrl, request.getLocale(), token, user); - mailSender.send(email); - } catch (final MailAuthenticationException e) { - LOGGER.debug("MailAuthenticationException", e); - return "redirect:/emailError.html?lang=" + request.getLocale().getLanguage(); - } catch (final Exception e) { - LOGGER.debug(e.getLocalizedMessage(), e); - model.addAttribute("message", e.getLocalizedMessage()); - return "redirect:/login.html?lang=" + request.getLocale().getLanguage(); - } - model.addAttribute("message", messages.getMessage("message.resetPasswordEmail", null, request.getLocale())); - return "redirect:/login.html?lang=" + request.getLocale().getLanguage(); - } - - @RequestMapping(value = "/user/changePassword", method = RequestMethod.GET) - public String changePassword(final HttpServletRequest request, final Model model, @RequestParam("id") final long id, @RequestParam("token") final String token) { - final Locale locale = request.getLocale(); - - final PasswordResetToken passToken = userService.getPasswordResetToken(token); - final User user = passToken.getUser(); - if (passToken == null || user.getId() != id) { - final String message = messages.getMessage("auth.message.invalidToken", null, locale); - model.addAttribute("message", message); - return "redirect:/login.html?lang=" + locale.getLanguage(); - } - - final Calendar cal = Calendar.getInstance(); - if ((passToken.getExpiryDate().getTime() - cal.getTime().getTime()) <= 0) { - model.addAttribute("message", messages.getMessage("auth.message.expired", null, locale)); - return "redirect:/login.html?lang=" + locale.getLanguage(); - } - - final Authentication auth = new UsernamePasswordAuthenticationToken(user, null, userDetailsService.loadUserByUsername(user.getEmail()).getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(auth); - - return "redirect:/updatePassword.html?lang=" + locale.getLanguage(); - } - - @RequestMapping(value = "/user/savePassword", method = RequestMethod.POST) - @PreAuthorize("hasRole('READ_PRIVILEGE')") - public String savePassword(final HttpServletRequest request, final Model model, @RequestParam("password") final String password) { - final Locale locale = request.getLocale(); - - final User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - userService.changeUserPassword(user, password); - model.addAttribute("message", messages.getMessage("message.resetPasswordSuc", null, locale)); - return "redirect:/login.html?lang=" + locale; - } - - // NON-API - - private final SimpleMailMessage constructResetVerificationTokenEmail(final String contextPath, final Locale locale, final VerificationToken newToken, final User user) { - final String confirmationUrl = contextPath + "/old/regitrationConfirm.html?token=" + newToken.getToken(); - final String message = messages.getMessage("message.resendToken", null, locale); - final SimpleMailMessage email = new SimpleMailMessage(); - email.setSubject("Resend Registration Token"); - email.setText(message + " \r\n" + confirmationUrl); - email.setTo(user.getEmail()); - email.setFrom(env.getProperty("support.email")); - return email; - } - - private final SimpleMailMessage constructResetTokenEmail(final String contextPath, final Locale locale, final String token, final User user) { - final String url = contextPath + "/old/user/changePassword?id=" + user.getId() + "&token=" + token; - final String message = messages.getMessage("message.resetPassword", null, locale); - final SimpleMailMessage email = new SimpleMailMessage(); - email.setTo(user.getEmail()); - email.setSubject("Reset Password"); - email.setText(message + " \r\n" + url); - email.setFrom(env.getProperty("support.email")); - return email; - } - - private User createUserAccount(final UserDto accountDto) { - User registered = null; - try { - registered = userService.registerNewUserAccount(accountDto); - } catch (final EmailExistsException e) { - return null; - } - return registered; - } -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/web/controller/RegistrationController.java b/spring-security-login-and-registration/src/main/java/org/baeldung/web/controller/RegistrationController.java deleted file mode 100644 index ca13d7f21e..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/web/controller/RegistrationController.java +++ /dev/null @@ -1,218 +0,0 @@ -package org.baeldung.web.controller; - -import java.util.Calendar; -import java.util.Locale; -import java.util.UUID; - -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; - -import org.baeldung.persistence.model.PasswordResetToken; -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.model.VerificationToken; -import org.baeldung.persistence.service.IUserService; -import org.baeldung.persistence.service.UserDto; -import org.baeldung.registration.OnRegistrationCompleteEvent; -import org.baeldung.validation.EmailExistsException; -import org.baeldung.web.error.InvalidOldPasswordException; -import org.baeldung.web.error.UserAlreadyExistException; -import org.baeldung.web.error.UserNotFoundException; -import org.baeldung.web.util.GenericResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.MessageSource; -import org.springframework.core.env.Environment; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -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; - -@Controller -public class RegistrationController { - private final Logger LOGGER = LoggerFactory.getLogger(getClass()); - - @Autowired - private IUserService userService; - - @Autowired - private MessageSource messages; - - @Autowired - private JavaMailSender mailSender; - - @Autowired - private ApplicationEventPublisher eventPublisher; - - @Autowired - private UserDetailsService userDetailsService; - - @Autowired - private Environment env; - - public RegistrationController() { - super(); - } - - // Registration - - @RequestMapping(value = "/user/registration", method = RequestMethod.POST) - @ResponseBody - public GenericResponse registerUserAccount(@Valid final UserDto accountDto, final HttpServletRequest request) { - LOGGER.debug("Registering user account with information: {}", accountDto); - - final User registered = createUserAccount(accountDto); - if (registered == null) { - throw new UserAlreadyExistException(); - } - final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); - eventPublisher.publishEvent(new OnRegistrationCompleteEvent(registered, request.getLocale(), appUrl)); - - return new GenericResponse("success"); - } - - @RequestMapping(value = "/regitrationConfirm", method = RequestMethod.GET) - public String confirmRegistration(final Locale locale, final Model model, @RequestParam("token") final String token) { - final VerificationToken verificationToken = userService.getVerificationToken(token); - if (verificationToken == null) { - final String message = messages.getMessage("auth.message.invalidToken", null, locale); - model.addAttribute("message", message); - return "redirect:/badUser.html?lang=" + locale.getLanguage(); - } - - final User user = verificationToken.getUser(); - final Calendar cal = Calendar.getInstance(); - if ((verificationToken.getExpiryDate().getTime() - cal.getTime().getTime()) <= 0) { - model.addAttribute("message", messages.getMessage("auth.message.expired", null, locale)); - model.addAttribute("expired", true); - model.addAttribute("token", token); - return "redirect:/badUser.html?lang=" + locale.getLanguage(); - } - - user.setEnabled(true); - userService.saveRegisteredUser(user); - model.addAttribute("message", messages.getMessage("message.accountVerified", null, locale)); - return "redirect:/login.html?lang=" + locale.getLanguage(); - } - - // user activation - verification - - @RequestMapping(value = "/user/resendRegistrationToken", method = RequestMethod.GET) - @ResponseBody - public GenericResponse resendRegistrationToken(final HttpServletRequest request, @RequestParam("token") final String existingToken) { - final VerificationToken newToken = userService.generateNewVerificationToken(existingToken); - final User user = userService.getUser(newToken.getToken()); - final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); - final SimpleMailMessage email = constructResendVerificationTokenEmail(appUrl, request.getLocale(), newToken, user); - mailSender.send(email); - - return new GenericResponse(messages.getMessage("message.resendToken", null, request.getLocale())); - } - - // Reset password - - @RequestMapping(value = "/user/resetPassword", method = RequestMethod.POST) - @ResponseBody - public GenericResponse resetPassword(final HttpServletRequest request, @RequestParam("email") final String userEmail) { - final User user = userService.findUserByEmail(userEmail); - if (user == null) { - throw new UserNotFoundException(); - } - - final String token = UUID.randomUUID().toString(); - userService.createPasswordResetTokenForUser(user, token); - final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); - final SimpleMailMessage email = constructResetTokenEmail(appUrl, request.getLocale(), token, user); - mailSender.send(email); - return new GenericResponse(messages.getMessage("message.resetPasswordEmail", null, request.getLocale())); - } - - @RequestMapping(value = "/user/changePassword", method = RequestMethod.GET) - public String showChangePasswordPage(final Locale locale, final Model model, @RequestParam("id") final long id, @RequestParam("token") final String token) { - final PasswordResetToken passToken = userService.getPasswordResetToken(token); - final User user = passToken.getUser(); - if (passToken == null || user.getId() != id) { - final String message = messages.getMessage("auth.message.invalidToken", null, locale); - model.addAttribute("message", message); - return "redirect:/login.html?lang=" + locale.getLanguage(); - } - - final Calendar cal = Calendar.getInstance(); - if ((passToken.getExpiryDate().getTime() - cal.getTime().getTime()) <= 0) { - model.addAttribute("message", messages.getMessage("auth.message.expired", null, locale)); - return "redirect:/login.html?lang=" + locale.getLanguage(); - } - - final Authentication auth = new UsernamePasswordAuthenticationToken(user, null, userDetailsService.loadUserByUsername(user.getEmail()).getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(auth); - - return "redirect:/updatePassword.html?lang=" + locale.getLanguage(); - } - - @RequestMapping(value = "/user/savePassword", method = RequestMethod.POST) - @PreAuthorize("hasRole('READ_PRIVILEGE')") - @ResponseBody - public GenericResponse savePassword(final Locale locale, @RequestParam("password") final String password) { - final User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - userService.changeUserPassword(user, password); - return new GenericResponse(messages.getMessage("message.resetPasswordSuc", null, locale)); - } - - // change user password - - @RequestMapping(value = "/user/updatePassword", method = RequestMethod.POST) - @PreAuthorize("hasRole('READ_PRIVILEGE')") - @ResponseBody - public GenericResponse changeUserPassword(final Locale locale, @RequestParam("password") final String password, @RequestParam("oldpassword") final String oldPassword) { - final User user = userService.findUserByEmail(SecurityContextHolder.getContext().getAuthentication().getName()); - if (!userService.checkIfValidOldPassword(user, oldPassword)) { - throw new InvalidOldPasswordException(); - } - userService.changeUserPassword(user, password); - return new GenericResponse(messages.getMessage("message.updatePasswordSuc", null, locale)); - } - - // NON-API - - private final SimpleMailMessage constructResendVerificationTokenEmail(final String contextPath, final Locale locale, final VerificationToken newToken, final User user) { - final String confirmationUrl = contextPath + "/regitrationConfirm.html?token=" + newToken.getToken(); - final String message = messages.getMessage("message.resendToken", null, locale); - final SimpleMailMessage email = new SimpleMailMessage(); - email.setSubject("Resend Registration Token"); - email.setText(message + " \r\n" + confirmationUrl); - email.setTo(user.getEmail()); - email.setFrom(env.getProperty("support.email")); - return email; - } - - private final SimpleMailMessage constructResetTokenEmail(final String contextPath, final Locale locale, final String token, final User user) { - final String url = contextPath + "/user/changePassword?id=" + user.getId() + "&token=" + token; - final String message = messages.getMessage("message.resetPassword", null, locale); - final SimpleMailMessage email = new SimpleMailMessage(); - email.setTo(user.getEmail()); - email.setSubject("Reset Password"); - email.setText(message + " \r\n" + url); - email.setFrom(env.getProperty("support.email")); - return email; - } - - private User createUserAccount(final UserDto accountDto) { - User registered = null; - try { - registered = userService.registerNewUserAccount(accountDto); - } catch (final EmailExistsException e) { - return null; - } - return registered; - } -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/InvalidOldPasswordException.java b/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/InvalidOldPasswordException.java deleted file mode 100644 index 74b4e04c1a..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/InvalidOldPasswordException.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.web.error; - -public final class InvalidOldPasswordException extends RuntimeException { - - private static final long serialVersionUID = 5861310537366287163L; - - public InvalidOldPasswordException() { - super(); - } - - public InvalidOldPasswordException(final String message, final Throwable cause) { - super(message, cause); - } - - public InvalidOldPasswordException(final String message) { - super(message); - } - - public InvalidOldPasswordException(final Throwable cause) { - super(cause); - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java deleted file mode 100644 index c74cf25c2b..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.baeldung.web.error; - -import org.baeldung.web.util.GenericResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.MessageSource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.mail.MailAuthenticationException; -import org.springframework.validation.BindException; -import org.springframework.validation.BindingResult; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; - -@ControllerAdvice -public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { - - @Autowired - private MessageSource messages; - - public RestResponseEntityExceptionHandler() { - super(); - } - - // API - - // 400 - @Override - protected ResponseEntity handleBindException(final BindException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { - logger.error("400 Status Code", ex); - final BindingResult result = ex.getBindingResult(); - final GenericResponse bodyOfResponse = new GenericResponse(result.getFieldErrors(), result.getGlobalErrors()); - return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); - } - - @Override - protected ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { - logger.error("400 Status Code", ex); - final BindingResult result = ex.getBindingResult(); - final GenericResponse bodyOfResponse = new GenericResponse(result.getFieldErrors(), result.getGlobalErrors()); - return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); - } - - @ExceptionHandler({ InvalidOldPasswordException.class }) - public ResponseEntity handleInvalidOldPassword(final RuntimeException ex, final WebRequest request) { - logger.error("400 Status Code", ex); - final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.invalidOldPassword", null, request.getLocale()), "InvalidOldEmail"); - return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); - } - - // 404 - @ExceptionHandler({ UserNotFoundException.class }) - public ResponseEntity handleUserNotFound(final RuntimeException ex, final WebRequest request) { - logger.error("404 Status Code", ex); - final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.userNotFound", null, request.getLocale()), "UserNotFound"); - return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request); - } - - // 409 - @ExceptionHandler({ UserAlreadyExistException.class }) - public ResponseEntity handleUserAlreadyExist(final RuntimeException ex, final WebRequest request) { - logger.error("409 Status Code", ex); - final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.regError", null, request.getLocale()), "UserAlreadyExist"); - return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request); - } - - // 500 - @ExceptionHandler({ MailAuthenticationException.class }) - public ResponseEntity handleMail(final RuntimeException ex, final WebRequest request) { - logger.error("500 Status Code", ex); - final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.email.config.error", null, request.getLocale()), "MailError"); - return new ResponseEntity(bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR); - } - - @ExceptionHandler({ Exception.class }) - public ResponseEntity handleInternal(final RuntimeException ex, final WebRequest request) { - logger.error("500 Status Code", ex); - final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.error", null, request.getLocale()), "InternalError"); - return new ResponseEntity(bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR); - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/UserAlreadyExistException.java b/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/UserAlreadyExistException.java deleted file mode 100644 index d9c112c3f5..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/UserAlreadyExistException.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.web.error; - -public final class UserAlreadyExistException extends RuntimeException { - - private static final long serialVersionUID = 5861310537366287163L; - - public UserAlreadyExistException() { - super(); - } - - public UserAlreadyExistException(final String message, final Throwable cause) { - super(message, cause); - } - - public UserAlreadyExistException(final String message) { - super(message); - } - - public UserAlreadyExistException(final Throwable cause) { - super(cause); - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/UserNotFoundException.java b/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/UserNotFoundException.java deleted file mode 100644 index 4f45e0f978..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/web/error/UserNotFoundException.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.web.error; - -public final class UserNotFoundException extends RuntimeException { - - private static final long serialVersionUID = 5861310537366287163L; - - public UserNotFoundException() { - super(); - } - - public UserNotFoundException(final String message, final Throwable cause) { - super(message, cause); - } - - public UserNotFoundException(final String message) { - super(message); - } - - public UserNotFoundException(final Throwable cause) { - super(cause); - } - -} diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/web/util/GenericResponse.java b/spring-security-login-and-registration/src/main/java/org/baeldung/web/util/GenericResponse.java deleted file mode 100644 index 076c481580..0000000000 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/web/util/GenericResponse.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.baeldung.web.util; - -import java.util.List; - -import org.springframework.validation.FieldError; -import org.springframework.validation.ObjectError; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -public class GenericResponse { - private String message; - private String error; - - public GenericResponse(final String message) { - super(); - this.message = message; - } - - public GenericResponse(final String message, final String error) { - super(); - this.message = message; - this.error = error; - } - - public GenericResponse(final List fieldErrors, final List globalErrors) { - super(); - final ObjectMapper mapper = new ObjectMapper(); - try { - this.message = mapper.writeValueAsString(fieldErrors); - this.error = mapper.writeValueAsString(globalErrors); - } catch (final JsonProcessingException e) { - this.message = ""; - this.error = ""; - } - } - - public String getMessage() { - return message; - } - - public void setMessage(final String message) { - this.message = message; - } - - public String getError() { - return error; - } - - public void setError(final String error) { - this.error = error; - } - -} diff --git a/spring-security-login-and-registration/src/main/resources/.gitignore b/spring-security-login-and-registration/src/main/resources/.gitignore deleted file mode 100644 index ec4a72ea93..0000000000 --- a/spring-security-login-and-registration/src/main/resources/.gitignore +++ /dev/null @@ -1 +0,0 @@ -email.properties \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/resources/email.properties.sample b/spring-security-login-and-registration/src/main/resources/email.properties.sample deleted file mode 100644 index 8e8207d7ab..0000000000 --- a/spring-security-login-and-registration/src/main/resources/email.properties.sample +++ /dev/null @@ -1,7 +0,0 @@ -################### JavaMail Configuration ########################## -smtp.host=email-smtp.us-east-1.amazonaws.com -smtp.port=465 -smtp.protocol=smtps -smtp.username=AKIAJIKXZAQFFJDXI4VQ -smtp.password= -support.email=eugen@baeldung.com diff --git a/spring-security-login-and-registration/src/main/resources/logback.xml b/spring-security-login-and-registration/src/main/resources/logback.xml deleted file mode 100644 index 1146dade63..0000000000 --- a/spring-security-login-and-registration/src/main/resources/logback.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - web - %date [%thread] %-5level %logger{36} - %message%n - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/resources/messages_en.properties b/spring-security-login-and-registration/src/main/resources/messages_en.properties deleted file mode 100644 index c522f1305f..0000000000 --- a/spring-security-login-and-registration/src/main/resources/messages_en.properties +++ /dev/null @@ -1,79 +0,0 @@ -message.username=Username required -message.password=Password required -message.unauth=Unauthorized Access !! -message.badCredentials=Invalid Username or Password -message.sessionExpired=Session Timed Out -message.logoutError=Sorry, error logging out -message.logoutSucc=You logged out successfully -message.regSucc=You registered successfully. We will send you a confirmation message to your email account. -message.regError=An account for that username/email already exists. Please enter a different username. -message.lastName=Last name is required -message.firstName=First name required -message.badEmail=Invalid email address -message.email.config.error=Error in java mail configuration -token.message=Your token is: -auth.message.disabled=Your account is disabled please check your mail and click on the confirmation link -auth.message.expired=Your registration token has expired. Please register again. -auth.message.invalidUser=This username is invalid, or does not exist. -auth.message.invalidToken=Invalid account confirmation token. -label.user.email=Email: -label.user.firstName=First name: -label.user.lastName=Last name: -label.user.password=Password: -label.user.confirmPass=Confirm password -label.form.submit=Submit -label.form.title=Registration Form -label.form.loginLink=Back to login -label.login=Login here -label.form.loginTitle=Login -label.form.loginEmail=Email -label.form.loginPass=Password -label.form.loginEnglish=English -label.form.loginSpanish=Spanish -label.form.loginSignUp=Sign up -label.pages.logout=Logout -label.pages.admin=Administrator -label.pages.home.title=Home -label.pages.home.message=Welcome Home -label.pages.admin.message=Welcome Admin -label.pages.user.message=Welcome User -label.successRegister.title=Registration Success -label.badUser.title=Invalid Link -ValidEmail.user.email=Invalid email address! -UniqueUsername.user.username=An account with that username/email already exists -NotNull.user.firstName=First name required -NotEmpty.user.firstName=First name required -NotNull.user.lastName=Last name required -NotEmpty.user.lastName=Last name required -NotNull.user.username=Username(Email) required -NotEmpty.user.username=Username(Email) required -NotNull.user.password=Password required -NotEmpty.user.password=Password required -NotNull.user.matchingPassword=Required -NotEmpty.user.matchingPassword=Required -PasswordMatches.user:Password does not match! -Email.user.email=Invalid Username (Email) -label.form.resendRegistrationToken=Re-send Token -message.resendToken=We will send an email with a new registration token to your email account -message.forgetPassword=Forget Password -message.resetPassword=Reset Password -message.updatePassword=Update Password -message.userNotFound=User Not Found -auth.message.blocked=This ip is blocked for 24 hours -message.accountVerified=Your account verified successfully -message.resetPasswordSuc=Password reset successfully -message.resetYourPassword=Reset your password -message.resetPasswordEmail=You should receive an Password Reset Email shortly -message.error=Error Occurred -message.updatePasswordSuc=Password updated successfully -message.changePassword=Change Password -message.invalidOldPassword=Invalid Old Password -label.user.newPassword=New Password -label.user.oldPassword=Old Password -error.wordLength=Your password is too short -error.wordNotEmail=Do not use your email as your password -error.wordSequences=Your password contains sequences -error.wordLowercase=Use lower case characters -error.wordUppercase=Use upper case characters -error.wordOneNumber=Use numbers -error.wordOneSpecialChar=Use special characters \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/resources/messages_es_ES.properties b/spring-security-login-and-registration/src/main/resources/messages_es_ES.properties deleted file mode 100644 index 58ed951891..0000000000 --- a/spring-security-login-and-registration/src/main/resources/messages_es_ES.properties +++ /dev/null @@ -1,79 +0,0 @@ -message.username=Por favor ingrese el nombre de usuario -message.password=Por favor ingrese una clave -message.unauth=Acceso denegado !! -message.badCredentials=Usuario o clave invalida -message.sessionExpired=La sesion expiro -message.logoutError=Lo sentimos, hubo problemas al salir -message.logoutSucc=Salida con exito -message.regSucc=Se registro correctamente. Le enviaremos un mensaje de confirmacion a su direccion de email. -message.regError=Ya existe una cuenta con ese nombre de usuario. Ingrese un nombre de usuario diferente. -message.lastName=Por favor ingrese su apellido -message.firstName=Por favor ingrese su nombre -message.badEmail=Direccion de correo no es valida -message.email.config.error=Error en configuracion de java mail -token.message=Su token es: -auth.message.disabled=Su cuenta no esta habilitada. Hemos enviado a su correo un link para habilitar su cuenta. -auth.message.expired=Su ficha de registro ha caducado, por favor registrese de nuevo. -auth.message.invalidUser=Este nombre de usuario es invalido o no existe. -auth.message.invalidToken=Codigo de confirmacion incorrecto. -label.user.email=Correo Electronico: -label.user.firstName=Nombre: -label.user.lastName=Apellido: -label.user.password=Contrasenia: -label.user.confirmPass=Confirme la contrasenia -label.form.submit=Enviar -label.form.title=Formulario de Registro -label.login=Autehtifiquese aqui -label.form.loginTitle=Ingreso -label.form.loginLink=Regrese a autentificacion -label.form.loginEmail=Correo Electronico -label.form.loginPass=Contrasenia -label.form.loginEnglish=Ingles -label.form.loginSpanish=Espaniol -label.form.loginSignUp=Registrese -label.pages.logout=Salir -label.pages.admin=Administrador -label.pages.home.title=Inicio -label.pages.home.message=Bienveni@ a Casa -label.pages.admin.message=Bienvenid@ Admin -label.pages.user.message=Bienvenid@ Usuari@ -label.successRegister.title=Registro Exitoso -label.badUser.title=Enlace Invalido -ValidEmail.user.email=Cuenta correo invlida! -UniqueUsername.user.username=Ya existe una cuenta con ese nombre de usuario -NotNull.user.firstName=Por favor ingrese su nombre -NotEmpty.user.firstName=Por favor ingrese su nombre -NotNull.user.lastName=Por favor ingrese su apellido -NotEmpty.user.lastName=Por favor ingrese su apellido -NotNull.user.username=Por favor ingrese su cuenta de email -NotEmpty.user.username=Por favor ingrese su cuenta de email -NotNull.user.password=Por favor ingrese su clave -NotEmpty.user.password=Por favor ingrese su contraseña -NotNull.user.matchingPassword=Campo obligatirio -NotEmpty.user.matchingPassword=Campo obligatrio -PasswordMatches.user:Las claves no coinciden! -Email.user.email=Email no es valido -label.form.resendRegistrationToken=Reenviar mensaje de emergencia -message.resendToken=Te enviaremos un correo electrónico con un nuevo token de registro en su cuenta de correo electrónico -message.forgetPassword=Olvide la contraseña -message.resetPassword=Restablecer contraseña -message.updatePassword=Actualizar contraseña -message.userNotFound=Usuario no encontrado -auth.message.blocked=Esta IP se bloquea durante 24 horas -message.accountVerified=Su cuenta verificada con éxito -message.resetPasswordSuc=Contraseña reajusta correctamente -message.resetYourPassword=Restablecer su contraseña -message.resetPasswordEmail=Te enviaremos un correo electrónico para restablecer su contraseña -message.error=Se produjo un error -message.updatePasswordSuc=Contraseña actualizado correctamente -message.changePassword=Cambiar La Contraseña -message.invalidOldPassword=Inválida contraseña antigua -label.user.newPassword=Nueva Contraseña -label.user.oldPassword=Contraseña Anterior -error.wordLength=Tu contraseña es demasiado corta -error.wordNotEmail=No utilice su dirección de correo electrónico como contraseña -error.wordSequences=Su contraseña contiene secuencias -error.wordLowercase=Utilice caracteres en minúsculas -error.wordUppercase=Utilice mayúsculas -error.wordOneNumber=Utilice números -error.wordOneSpecialChar=Utilice los caracteres especiales \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/resources/persistence.properties b/spring-security-login-and-registration/src/main/resources/persistence.properties deleted file mode 100644 index 06b2528f64..0000000000 --- a/spring-security-login-and-registration/src/main/resources/persistence.properties +++ /dev/null @@ -1,10 +0,0 @@ -################### DataSource Configuration ########################## -jdbc.driverClassName=com.mysql.jdbc.Driver -jdbc.url=jdbc:mysql://localhost:3306/registration_02?createDatabaseIfNotExist=true -jdbc.user=tutorialuser -jdbc.pass=tutorialmy5ql -init-db=false -################### Hibernate Configuration ########################## -hibernate.dialect=org.hibernate.dialect.MySQLDialect -hibernate.show_sql=false -hibernate.hbm2ddl.auto=create-drop diff --git a/spring-security-login-and-registration/src/main/resources/webSecurityConfig-basic.xml b/spring-security-login-and-registration/src/main/resources/webSecurityConfig-basic.xml deleted file mode 100644 index bf85a09b62..0000000000 --- a/spring-security-login-and-registration/src/main/resources/webSecurityConfig-basic.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/resources/webSecurityConfig.xml b/spring-security-login-and-registration/src/main/resources/webSecurityConfig.xml deleted file mode 100644 index 4e67a1200f..0000000000 --- a/spring-security-login-and-registration/src/main/resources/webSecurityConfig.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/META-INF/MANIFEST.MF b/spring-security-login-and-registration/src/main/webapp/META-INF/MANIFEST.MF deleted file mode 100644 index 5e9495128c..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-security-login-and-registration/src/main/webapp/WEB-INF/mvc-servlet.xml deleted file mode 100644 index 99e19b0558..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/mvc-servlet.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/admin.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/admin.jsp deleted file mode 100644 index ad0a8231ad..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/admin.jsp +++ /dev/null @@ -1,34 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - - - -<spring:message code="label.pages.home.title"></spring:message> - - - - -
    - - - - -

    - -

    -
    -
    - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/badUser.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/badUser.jsp deleted file mode 100644 index c2ad64ec6a..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/badUser.jsp +++ /dev/null @@ -1,54 +0,0 @@ -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> - -<%@ page session="true"%> - - - - <spring:message -code="label.badUser.title"></spring:message> - - -
    -

    - ${param.message} -

    -
    -"> - - -
    -

    ${label.form.resendRegistrationToken}

    - - - - -
    -
    - - diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/changePassword.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/changePassword.jsp deleted file mode 100644 index 88836e96f5..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/changePassword.jsp +++ /dev/null @@ -1,70 +0,0 @@ - -<%@ page contentType="text/html;charset=UTF-8" language="java"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> -<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> -<%@ page session="false"%> - - - - -<spring:message code="message.changePassword"></spring:message> - - - -
    -
    - -

    -
    -
    - - - - -

    - - - -

    - - - - -

    - -
    - -
    -
    - - - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/console.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/console.jsp deleted file mode 100644 index e06cdd39f0..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/console.jsp +++ /dev/null @@ -1,42 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - - - - - - -
    - -
    -${param.message} -
    -
    -

    This is the landing page for the admin

    - - This text is only visible to a user -
    -
    - - This text is only visible to an admin -
    -
    - "> - - "> -
    - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/emailError.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/emailError.jsp deleted file mode 100644 index ed25d1f2cd..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/emailError.jsp +++ /dev/null @@ -1,17 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - - -<spring:message code="label.pages.home.title"></spring:message> - - -
    -

    - -

    - -
    - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/expiredAccount.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/expiredAccount.jsp deleted file mode 100644 index e829daaa61..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/expiredAccount.jsp +++ /dev/null @@ -1,24 +0,0 @@ -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> - -<%@ page session="true"%> - - - - - <spring:message code="label.pages.home.title"></spring:message> - - -
    -

    - -

    -
    -"> -
    - - diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/forgetPassword.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/forgetPassword.jsp deleted file mode 100644 index cff325846d..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/forgetPassword.jsp +++ /dev/null @@ -1,55 +0,0 @@ - -<%@ page contentType="text/html;charset=UTF-8" language="java"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> -<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@ page session="false"%> - - - - -<spring:message code="message.resetPassword"></spring:message> - - -
    -

    -
    -
    - - - -
    - -
    -"> -

    -"> - -
    - - - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/home.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/home.jsp deleted file mode 100644 index 027f583d61..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/home.jsp +++ /dev/null @@ -1,29 +0,0 @@ -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> -<%@ page session="true"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - - - -<spring:message code="label.pages.home.title"></spring:message> - - - -
    -

    - -

    -
    - - - - diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/homepage.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/homepage.jsp deleted file mode 100644 index af931ac66f..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/homepage.jsp +++ /dev/null @@ -1,38 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ page session="true"%> - - - -<spring:message code="label.pages.home.title"></spring:message> - - - - -
    - - - -
    -
    - - - -
    -
    - ${param.user} - "> -
    - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/invalidSession.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/invalidSession.jsp deleted file mode 100644 index 50891a216f..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/invalidSession.jsp +++ /dev/null @@ -1,18 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - - -<spring:message code="label.pages.home.title"></spring:message> - - -
    -

    - -

    - "> -
    - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/login.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/login.jsp deleted file mode 100644 index a71fe9dc3a..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/login.jsp +++ /dev/null @@ -1,88 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> - -<%@ page session="true"%> - - - - - - - -<spring:message code="label.pages.home.title"></spring:message> - - - - - -
    -${param.message} -
    -
    - - - -
    -${SPRING_SECURITY_LAST_EXCEPTION} -
    -
    - -
    -
    -

    - -

    - - | -

    - -
    - - - - -

    - - - -

    - /> - -
    -
    Current Locale : ${pageContext.response.locale}

    - "> -

    - "> -
    -
    - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/logout.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/logout.jsp deleted file mode 100644 index 95602d58a8..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/logout.jsp +++ /dev/null @@ -1,31 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - - - - -

    - -

    -
    - -<spring:message code="label.pages.home.title"></spring:message> - - - -
    - - -

    - -

    -
    - "> -
    - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/registration.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/registration.jsp deleted file mode 100644 index cf64291be6..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/registration.jsp +++ /dev/null @@ -1,139 +0,0 @@ - -<%@ page contentType="text/html;charset=UTF-8" language="java"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> -<%@ page session="false"%> - - - - - - - -<spring:message code="label.form.title"></spring:message> - - -
    -
    -

    - -

    -
    -
    -
    - - - - -
    -
    - - - - -
    -
    - - - - -
    -
    - - - -
    -
    - - - -
    -
    - -
    -
    - "> -
    -
    - - - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/regitrationConfirm.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/regitrationConfirm.jsp deleted file mode 100644 index 08d3f4ab70..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/regitrationConfirm.jsp +++ /dev/null @@ -1,23 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> - -<%@ page session="true"%> - - - - - - - -<spring:message code="label.pages.home.title"></spring:message> - - -
    -

    - "> -
    - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/successRegister.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/successRegister.jsp deleted file mode 100644 index ea6e031fb9..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/successRegister.jsp +++ /dev/null @@ -1,25 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> - -<%@ page session="true"%> - - - - - - -<spring:message code="label.pages.home.title"></spring:message> - - -
    -

    - -

    - "> -
    - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/updatePassword.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/updatePassword.jsp deleted file mode 100644 index 859c0a9be4..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/updatePassword.jsp +++ /dev/null @@ -1,60 +0,0 @@ - -<%@ page contentType="text/html;charset=UTF-8" language="java"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> -<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@ page session="false"%> - - - - -<spring:message code="message.updatePassword"></spring:message> - - - -
    -
    -

    -
    -
    - - - - -

    - - - - -

    - -
    - -
    -
    - - - -
    - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/web.xml b/spring-security-login-and-registration/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 9ef57810f8..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - contextClass - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - contextConfigLocation - org.baeldung.spring - - - - org.springframework.web.context.ContextLoaderListener - - - - org.springframework.web.context.request.RequestContextListener - - - - mvc - org.springframework.web.servlet.DispatcherServlet - 1 - - - mvc - / - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - springSecurityFilterChain - /* - - - localizationFilter - org.springframework.web.filter.RequestContextFilter - - - localizationFilter - /* - - - \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/resources/bootstrap.css b/spring-security-login-and-registration/src/main/webapp/resources/bootstrap.css deleted file mode 100644 index a5b7ccc211..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/resources/bootstrap.css +++ /dev/null @@ -1,6167 +0,0 @@ -/*! - * Bootstrap v2.3.2 - * - * Copyright 2013 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world by @mdo and @fat. - */ - -.clearfix { - *zoom: 1; -} - -.clearfix:before, -.clearfix:after { - display: table; - line-height: 0; - content: ""; -} - -.clearfix:after { - clear: both; -} - -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} - -.input-block-level { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section { - display: block; -} - -audio, -canvas, -video { - display: inline-block; - *display: inline; - *zoom: 1; -} - -audio:not([controls]) { - display: none; -} - -html { - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -a:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -a:hover, -a:active { - outline: 0; -} - -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -img { - width: auto\9; - height: auto; - max-width: 100%; - vertical-align: middle; - border: 0; - -ms-interpolation-mode: bicubic; -} - -#map_canvas img, -.google-maps img { - max-width: none; -} - -button, -input, -select, -textarea { - margin: 0; - font-size: 100%; - vertical-align: middle; -} - -button, -input { - *overflow: visible; - line-height: normal; -} - -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} - -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} - -label, -select, -button, -input[type="button"], -input[type="reset"], -input[type="submit"], -input[type="radio"], -input[type="checkbox"] { - cursor: pointer; -} - -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} - -input[type="search"]::-webkit-search-decoration, -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; -} - -textarea { - overflow: auto; - vertical-align: top; -} - -@media print { - * { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - .ir a:after, - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - @page { - margin: 0.5cm; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } -} - -body { - margin: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 20px; - color: #333333; - background-color: #ffffff; -} - -a { - color: #0088cc; - text-decoration: none; -} - -a:hover, -a:focus { - color: #005580; - text-decoration: underline; -} - -.img-rounded { - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.img-polaroid { - padding: 4px; - background-color: #fff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -.img-circle { - -webkit-border-radius: 500px; - -moz-border-radius: 500px; - border-radius: 500px; -} - -.row { - margin-left: -20px; - *zoom: 1; -} - -.row:before, -.row:after { - display: table; - line-height: 0; - content: ""; -} - -.row:after { - clear: both; -} - -[class*="span"] { - float: left; - min-height: 1px; - margin-left: 20px; -} - -.container, -.navbar-static-top .container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} - -.span12 { - width: 940px; -} - -.span11 { - width: 860px; -} - -.span10 { - width: 780px; -} - -.span9 { - width: 700px; -} - -.span8 { - width: 620px; -} - -.span7 { - width: 540px; -} - -.span6 { - width: 460px; -} - -.span5 { - width: 380px; -} - -.span4 { - width: 300px; -} - -.span3 { - width: 220px; -} - -.span2 { - width: 140px; -} - -.span1 { - width: 60px; -} - -.offset12 { - margin-left: 980px; -} - -.offset11 { - margin-left: 900px; -} - -.offset10 { - margin-left: 820px; -} - -.offset9 { - margin-left: 740px; -} - -.offset8 { - margin-left: 660px; -} - -.offset7 { - margin-left: 580px; -} - -.offset6 { - margin-left: 500px; -} - -.offset5 { - margin-left: 420px; -} - -.offset4 { - margin-left: 340px; -} - -.offset3 { - margin-left: 260px; -} - -.offset2 { - margin-left: 180px; -} - -.offset1 { - margin-left: 100px; -} - -.row-fluid { - width: 100%; - *zoom: 1; -} - -.row-fluid:before, -.row-fluid:after { - display: table; - line-height: 0; - content: ""; -} - -.row-fluid:after { - clear: both; -} - -.row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 30px; - margin-left: 2.127659574468085%; - *margin-left: 2.074468085106383%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.row-fluid [class*="span"]:first-child { - margin-left: 0; -} - -.row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.127659574468085%; -} - -.row-fluid .span12 { - width: 100%; - *width: 99.94680851063829%; -} - -.row-fluid .span11 { - width: 91.48936170212765%; - *width: 91.43617021276594%; -} - -.row-fluid .span10 { - width: 82.97872340425532%; - *width: 82.92553191489361%; -} - -.row-fluid .span9 { - width: 74.46808510638297%; - *width: 74.41489361702126%; -} - -.row-fluid .span8 { - width: 65.95744680851064%; - *width: 65.90425531914893%; -} - -.row-fluid .span7 { - width: 57.44680851063829%; - *width: 57.39361702127659%; -} - -.row-fluid .span6 { - width: 48.93617021276595%; - *width: 48.88297872340425%; -} - -.row-fluid .span5 { - width: 40.42553191489362%; - *width: 40.37234042553192%; -} - -.row-fluid .span4 { - width: 31.914893617021278%; - *width: 31.861702127659576%; -} - -.row-fluid .span3 { - width: 23.404255319148934%; - *width: 23.351063829787233%; -} - -.row-fluid .span2 { - width: 14.893617021276595%; - *width: 14.840425531914894%; -} - -.row-fluid .span1 { - width: 6.382978723404255%; - *width: 6.329787234042553%; -} - -.row-fluid .offset12 { - margin-left: 104.25531914893617%; - *margin-left: 104.14893617021275%; -} - -.row-fluid .offset12:first-child { - margin-left: 102.12765957446808%; - *margin-left: 102.02127659574467%; -} - -.row-fluid .offset11 { - margin-left: 95.74468085106382%; - *margin-left: 95.6382978723404%; -} - -.row-fluid .offset11:first-child { - margin-left: 93.61702127659574%; - *margin-left: 93.51063829787232%; -} - -.row-fluid .offset10 { - margin-left: 87.23404255319149%; - *margin-left: 87.12765957446807%; -} - -.row-fluid .offset10:first-child { - margin-left: 85.1063829787234%; - *margin-left: 84.99999999999999%; -} - -.row-fluid .offset9 { - margin-left: 78.72340425531914%; - *margin-left: 78.61702127659572%; -} - -.row-fluid .offset9:first-child { - margin-left: 76.59574468085106%; - *margin-left: 76.48936170212764%; -} - -.row-fluid .offset8 { - margin-left: 70.2127659574468%; - *margin-left: 70.10638297872339%; -} - -.row-fluid .offset8:first-child { - margin-left: 68.08510638297872%; - *margin-left: 67.9787234042553%; -} - -.row-fluid .offset7 { - margin-left: 61.70212765957446%; - *margin-left: 61.59574468085106%; -} - -.row-fluid .offset7:first-child { - margin-left: 59.574468085106375%; - *margin-left: 59.46808510638297%; -} - -.row-fluid .offset6 { - margin-left: 53.191489361702125%; - *margin-left: 53.085106382978715%; -} - -.row-fluid .offset6:first-child { - margin-left: 51.063829787234035%; - *margin-left: 50.95744680851063%; -} - -.row-fluid .offset5 { - margin-left: 44.68085106382979%; - *margin-left: 44.57446808510638%; -} - -.row-fluid .offset5:first-child { - margin-left: 42.5531914893617%; - *margin-left: 42.4468085106383%; -} - -.row-fluid .offset4 { - margin-left: 36.170212765957444%; - *margin-left: 36.06382978723405%; -} - -.row-fluid .offset4:first-child { - margin-left: 34.04255319148936%; - *margin-left: 33.93617021276596%; -} - -.row-fluid .offset3 { - margin-left: 27.659574468085104%; - *margin-left: 27.5531914893617%; -} - -.row-fluid .offset3:first-child { - margin-left: 25.53191489361702%; - *margin-left: 25.425531914893618%; -} - -.row-fluid .offset2 { - margin-left: 19.148936170212764%; - *margin-left: 19.04255319148936%; -} - -.row-fluid .offset2:first-child { - margin-left: 17.02127659574468%; - *margin-left: 16.914893617021278%; -} - -.row-fluid .offset1 { - margin-left: 10.638297872340425%; - *margin-left: 10.53191489361702%; -} - -.row-fluid .offset1:first-child { - margin-left: 8.51063829787234%; - *margin-left: 8.404255319148938%; -} - -[class*="span"].hide, -.row-fluid [class*="span"].hide { - display: none; -} - -[class*="span"].pull-right, -.row-fluid [class*="span"].pull-right { - float: right; -} - -.container { - margin-right: auto; - margin-left: auto; - *zoom: 1; -} - -.container:before, -.container:after { - display: table; - line-height: 0; - content: ""; -} - -.container:after { - clear: both; -} - -.container-fluid { - padding-right: 20px; - padding-left: 20px; - *zoom: 1; -} - -.container-fluid:before, -.container-fluid:after { - display: table; - line-height: 0; - content: ""; -} - -.container-fluid:after { - clear: both; -} - -p { - margin: 0 0 10px; -} - -.lead { - margin-bottom: 20px; - font-size: 21px; - font-weight: 200; - line-height: 30px; -} - -small { - font-size: 85%; -} - -strong { - font-weight: bold; -} - -em { - font-style: italic; -} - -cite { - font-style: normal; -} - -.muted { - color: #999999; -} - -a.muted:hover, -a.muted:focus { - color: #808080; -} - -.text-warning { - color: #c09853; -} - -a.text-warning:hover, -a.text-warning:focus { - color: #a47e3c; -} - -.text-error { - color: #b94a48; -} - -a.text-error:hover, -a.text-error:focus { - color: #953b39; -} - -.text-info { - color: #3a87ad; -} - -a.text-info:hover, -a.text-info:focus { - color: #2d6987; -} - -.text-success { - color: #468847; -} - -a.text-success:hover, -a.text-success:focus { - color: #356635; -} - -.text-left { - text-align: left; -} - -.text-right { - text-align: right; -} - -.text-center { - text-align: center; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 10px 0; - font-family: inherit; - font-weight: bold; - line-height: 20px; - color: inherit; - text-rendering: optimizelegibility; -} - -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small { - font-weight: normal; - line-height: 1; - color: #999999; -} - -h1, -h2, -h3 { - line-height: 40px; -} - -h1 { - font-size: 38.5px; -} - -h2 { - font-size: 31.5px; -} - -h3 { - font-size: 24.5px; -} - -h4 { - font-size: 17.5px; -} - -h5 { - font-size: 14px; -} - -h6 { - font-size: 11.9px; -} - -h1 small { - font-size: 24.5px; -} - -h2 small { - font-size: 17.5px; -} - -h3 small { - font-size: 14px; -} - -h4 small { - font-size: 14px; -} - -.page-header { - padding-bottom: 9px; - margin: 20px 0 30px; - border-bottom: 1px solid #eeeeee; -} - -ul, -ol { - padding: 0; - margin: 0 0 10px 25px; -} - -ul ul, -ul ol, -ol ol, -ol ul { - margin-bottom: 0; -} - -li { - line-height: 20px; -} - -ul.unstyled, -ol.unstyled { - margin-left: 0; - list-style: none; -} - -ul.inline, -ol.inline { - margin-left: 0; - list-style: none; -} - -ul.inline > li, -ol.inline > li { - display: inline-block; - *display: inline; - padding-right: 5px; - padding-left: 5px; - *zoom: 1; -} - -dl { - margin-bottom: 20px; -} - -dt, -dd { - line-height: 20px; -} - -dt { - font-weight: bold; -} - -dd { - margin-left: 10px; -} - -.dl-horizontal { - *zoom: 1; -} - -.dl-horizontal:before, -.dl-horizontal:after { - display: table; - line-height: 0; - content: ""; -} - -.dl-horizontal:after { - clear: both; -} - -.dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; -} - -.dl-horizontal dd { - margin-left: 180px; -} - -hr { - margin: 20px 0; - border: 0; - border-top: 1px solid #eeeeee; - border-bottom: 1px solid #ffffff; -} - -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #999999; -} - -abbr.initialism { - font-size: 90%; - text-transform: uppercase; -} - -blockquote { - padding: 0 0 0 15px; - margin: 0 0 20px; - border-left: 5px solid #eeeeee; -} - -blockquote p { - margin-bottom: 0; - font-size: 17.5px; - font-weight: 300; - line-height: 1.25; -} - -blockquote small { - display: block; - line-height: 20px; - color: #999999; -} - -blockquote small:before { - content: '\2014 \00A0'; -} - -blockquote.pull-right { - float: right; - padding-right: 15px; - padding-left: 0; - border-right: 5px solid #eeeeee; - border-left: 0; -} - -blockquote.pull-right p, -blockquote.pull-right small { - text-align: right; -} - -blockquote.pull-right small:before { - content: ''; -} - -blockquote.pull-right small:after { - content: '\00A0 \2014'; -} - -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} - -address { - display: block; - margin-bottom: 20px; - font-style: normal; - line-height: 20px; -} - -code, -pre { - padding: 0 3px 2px; - font-family: Monaco, Menlo, Consolas, "Courier New", monospace; - font-size: 12px; - color: #333333; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -code { - padding: 2px 4px; - color: #d14; - white-space: nowrap; - background-color: #f7f7f9; - border: 1px solid #e1e1e8; -} - -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 20px; - word-break: break-all; - word-wrap: break-word; - white-space: pre; - white-space: pre-wrap; - background-color: #f5f5f5; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -pre.prettyprint { - margin-bottom: 20px; -} - -pre code { - padding: 0; - color: inherit; - white-space: pre; - white-space: pre-wrap; - background-color: transparent; - border: 0; -} - -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} - -form { - margin: 0 0 20px; -} - -fieldset { - padding: 0; - margin: 0; - border: 0; -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: 40px; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} - -legend small { - font-size: 15px; - color: #999999; -} - -label, -input, -button, -select, -textarea { - font-size: 14px; - font-weight: normal; - line-height: 20px; -} - -input, -button, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -} - -label { - display: block; - margin-bottom: 5px; -} - -select, -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - display: inline-block; - height: 30px; - padding: 4px 6px; - margin-bottom: 10px; - font-size: 14px; - line-height: 20px; - color: #555555; - vertical-align: middle; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -input, -textarea, -.uneditable-input { - width: 206px; -} - -textarea { - height: auto; -} - -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - background-color: #ffffff; - border: 1px solid #cccccc; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; - -moz-transition: border linear 0.2s, box-shadow linear 0.2s; - -o-transition: border linear 0.2s, box-shadow linear 0.2s; - transition: border linear 0.2s, box-shadow linear 0.2s; -} - -textarea:focus, -input[type="text"]:focus, -input[type="password"]:focus, -input[type="datetime"]:focus, -input[type="datetime-local"]:focus, -input[type="date"]:focus, -input[type="month"]:focus, -input[type="time"]:focus, -input[type="week"]:focus, -input[type="number"]:focus, -input[type="email"]:focus, -input[type="url"]:focus, -input[type="search"]:focus, -input[type="tel"]:focus, -input[type="color"]:focus, -.uneditable-input:focus { - border-color: rgba(82, 168, 236, 0.8); - outline: 0; - outline: thin dotted \9; - /* IE6-9 */ - - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); -} - -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - *margin-top: 0; - line-height: normal; -} - -input[type="file"], -input[type="image"], -input[type="submit"], -input[type="reset"], -input[type="button"], -input[type="radio"], -input[type="checkbox"] { - width: auto; -} - -select, -input[type="file"] { - height: 30px; - /* In IE7, the height of the select element cannot be changed by height, only font-size */ - - *margin-top: 4px; - /* For IE7, add top margin to align select with labels */ - - line-height: 30px; -} - -select { - width: 220px; - background-color: #ffffff; - border: 1px solid #cccccc; -} - -select[multiple], -select[size] { - height: auto; -} - -select:focus, -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.uneditable-input, -.uneditable-textarea { - color: #999999; - cursor: not-allowed; - background-color: #fcfcfc; - border-color: #cccccc; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); -} - -.uneditable-input { - overflow: hidden; - white-space: nowrap; -} - -.uneditable-textarea { - width: auto; - height: auto; -} - -input:-moz-placeholder, -textarea:-moz-placeholder { - color: #999999; -} - -input:-ms-input-placeholder, -textarea:-ms-input-placeholder { - color: #999999; -} - -input::-webkit-input-placeholder, -textarea::-webkit-input-placeholder { - color: #999999; -} - -.radio, -.checkbox { - min-height: 20px; - padding-left: 20px; -} - -.radio input[type="radio"], -.checkbox input[type="checkbox"] { - float: left; - margin-left: -20px; -} - -.controls > .radio:first-child, -.controls > .checkbox:first-child { - padding-top: 5px; -} - -.radio.inline, -.checkbox.inline { - display: inline-block; - padding-top: 5px; - margin-bottom: 0; - vertical-align: middle; -} - -.radio.inline + .radio.inline, -.checkbox.inline + .checkbox.inline { - margin-left: 10px; -} - -.input-mini { - width: 60px; -} - -.input-small { - width: 90px; -} - -.input-medium { - width: 150px; -} - -.input-large { - width: 210px; -} - -.input-xlarge { - width: 270px; -} - -.input-xxlarge { - width: 530px; -} - -input[class*="span"], -select[class*="span"], -textarea[class*="span"], -.uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"] { - float: none; - margin-left: 0; -} - -.input-append input[class*="span"], -.input-append .uneditable-input[class*="span"], -.input-prepend input[class*="span"], -.input-prepend .uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"], -.row-fluid .input-prepend [class*="span"], -.row-fluid .input-append [class*="span"] { - display: inline-block; -} - -input, -textarea, -.uneditable-input { - margin-left: 0; -} - -.controls-row [class*="span"] + [class*="span"] { - margin-left: 20px; -} - -input.span12, -textarea.span12, -.uneditable-input.span12 { - width: 926px; -} - -input.span11, -textarea.span11, -.uneditable-input.span11 { - width: 846px; -} - -input.span10, -textarea.span10, -.uneditable-input.span10 { - width: 766px; -} - -input.span9, -textarea.span9, -.uneditable-input.span9 { - width: 686px; -} - -input.span8, -textarea.span8, -.uneditable-input.span8 { - width: 606px; -} - -input.span7, -textarea.span7, -.uneditable-input.span7 { - width: 526px; -} - -input.span6, -textarea.span6, -.uneditable-input.span6 { - width: 446px; -} - -input.span5, -textarea.span5, -.uneditable-input.span5 { - width: 366px; -} - -input.span4, -textarea.span4, -.uneditable-input.span4 { - width: 286px; -} - -input.span3, -textarea.span3, -.uneditable-input.span3 { - width: 206px; -} - -input.span2, -textarea.span2, -.uneditable-input.span2 { - width: 126px; -} - -input.span1, -textarea.span1, -.uneditable-input.span1 { - width: 46px; -} - -.controls-row { - *zoom: 1; -} - -.controls-row:before, -.controls-row:after { - display: table; - line-height: 0; - content: ""; -} - -.controls-row:after { - clear: both; -} - -.controls-row [class*="span"], -.row-fluid .controls-row [class*="span"] { - float: left; -} - -.controls-row .checkbox[class*="span"], -.controls-row .radio[class*="span"] { - padding-top: 5px; -} - -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - cursor: not-allowed; - background-color: #eeeeee; -} - -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"][readonly], -input[type="checkbox"][readonly] { - background-color: transparent; -} - -.control-group.warning .control-label, -.control-group.warning .help-block, -.control-group.warning .help-inline { - color: #c09853; -} - -.control-group.warning .checkbox, -.control-group.warning .radio, -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - color: #c09853; -} - -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - border-color: #c09853; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.warning input:focus, -.control-group.warning select:focus, -.control-group.warning textarea:focus { - border-color: #a47e3c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; -} - -.control-group.warning .input-prepend .add-on, -.control-group.warning .input-append .add-on { - color: #c09853; - background-color: #fcf8e3; - border-color: #c09853; -} - -.control-group.error .control-label, -.control-group.error .help-block, -.control-group.error .help-inline { - color: #b94a48; -} - -.control-group.error .checkbox, -.control-group.error .radio, -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - color: #b94a48; -} - -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - border-color: #b94a48; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.error input:focus, -.control-group.error select:focus, -.control-group.error textarea:focus { - border-color: #953b39; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; -} - -.control-group.error .input-prepend .add-on, -.control-group.error .input-append .add-on { - color: #b94a48; - background-color: #f2dede; - border-color: #b94a48; -} - -.control-group.success .control-label, -.control-group.success .help-block, -.control-group.success .help-inline { - color: #468847; -} - -.control-group.success .checkbox, -.control-group.success .radio, -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - color: #468847; -} - -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - border-color: #468847; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.success input:focus, -.control-group.success select:focus, -.control-group.success textarea:focus { - border-color: #356635; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; -} - -.control-group.success .input-prepend .add-on, -.control-group.success .input-append .add-on { - color: #468847; - background-color: #dff0d8; - border-color: #468847; -} - -.control-group.info .control-label, -.control-group.info .help-block, -.control-group.info .help-inline { - color: #3a87ad; -} - -.control-group.info .checkbox, -.control-group.info .radio, -.control-group.info input, -.control-group.info select, -.control-group.info textarea { - color: #3a87ad; -} - -.control-group.info input, -.control-group.info select, -.control-group.info textarea { - border-color: #3a87ad; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.info input:focus, -.control-group.info select:focus, -.control-group.info textarea:focus { - border-color: #2d6987; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; -} - -.control-group.info .input-prepend .add-on, -.control-group.info .input-append .add-on { - color: #3a87ad; - background-color: #d9edf7; - border-color: #3a87ad; -} - -input:focus:invalid, -textarea:focus:invalid, -select:focus:invalid { - color: #b94a48; - border-color: #ee5f5b; -} - -input:focus:invalid:focus, -textarea:focus:invalid:focus, -select:focus:invalid:focus { - border-color: #e9322d; - -webkit-box-shadow: 0 0 6px #f8b9b7; - -moz-box-shadow: 0 0 6px #f8b9b7; - box-shadow: 0 0 6px #f8b9b7; -} - -.form-actions { - padding: 19px 20px 20px; - margin-top: 20px; - margin-bottom: 20px; - background-color: #f5f5f5; - border-top: 1px solid #e5e5e5; - *zoom: 1; -} - -.form-actions:before, -.form-actions:after { - display: table; - line-height: 0; - content: ""; -} - -.form-actions:after { - clear: both; -} - -.help-block, -.help-inline { - color: #595959; -} - -.help-block { - display: block; - margin-bottom: 10px; -} - -.help-inline { - display: inline-block; - *display: inline; - padding-left: 5px; - vertical-align: middle; - *zoom: 1; -} - -.input-append, -.input-prepend { - display: inline-block; - margin-bottom: 10px; - font-size: 0; - white-space: nowrap; - vertical-align: middle; -} - -.input-append input, -.input-prepend input, -.input-append select, -.input-prepend select, -.input-append .uneditable-input, -.input-prepend .uneditable-input, -.input-append .dropdown-menu, -.input-prepend .dropdown-menu, -.input-append .popover, -.input-prepend .popover { - font-size: 14px; -} - -.input-append input, -.input-prepend input, -.input-append select, -.input-prepend select, -.input-append .uneditable-input, -.input-prepend .uneditable-input { - position: relative; - margin-bottom: 0; - *margin-left: 0; - vertical-align: top; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-append input:focus, -.input-prepend input:focus, -.input-append select:focus, -.input-prepend select:focus, -.input-append .uneditable-input:focus, -.input-prepend .uneditable-input:focus { - z-index: 2; -} - -.input-append .add-on, -.input-prepend .add-on { - display: inline-block; - width: auto; - height: 20px; - min-width: 16px; - padding: 4px 5px; - font-size: 14px; - font-weight: normal; - line-height: 20px; - text-align: center; - text-shadow: 0 1px 0 #ffffff; - background-color: #eeeeee; - border: 1px solid #ccc; -} - -.input-append .add-on, -.input-prepend .add-on, -.input-append .btn, -.input-prepend .btn, -.input-append .btn-group > .dropdown-toggle, -.input-prepend .btn-group > .dropdown-toggle { - vertical-align: top; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.input-append .active, -.input-prepend .active { - background-color: #a9dba9; - border-color: #46a546; -} - -.input-prepend .add-on, -.input-prepend .btn { - margin-right: -1px; -} - -.input-prepend .add-on:first-child, -.input-prepend .btn:first-child { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-append input, -.input-append select, -.input-append .uneditable-input { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-append input + .btn-group .btn:last-child, -.input-append select + .btn-group .btn:last-child, -.input-append .uneditable-input + .btn-group .btn:last-child { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-append .add-on, -.input-append .btn, -.input-append .btn-group { - margin-left: -1px; -} - -.input-append .add-on:last-child, -.input-append .btn:last-child, -.input-append .btn-group:last-child > .dropdown-toggle { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append input, -.input-prepend.input-append select, -.input-prepend.input-append .uneditable-input { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.input-prepend.input-append input + .btn-group .btn, -.input-prepend.input-append select + .btn-group .btn, -.input-prepend.input-append .uneditable-input + .btn-group .btn { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append .add-on:first-child, -.input-prepend.input-append .btn:first-child { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-prepend.input-append .add-on:last-child, -.input-prepend.input-append .btn:last-child { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append .btn-group:first-child { - margin-left: 0; -} - -input.search-query { - padding-right: 14px; - padding-right: 4px \9; - padding-left: 14px; - padding-left: 4px \9; - /* IE7-8 doesn't have border-radius, so don't indent the padding */ - - margin-bottom: 0; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -/* Allow for input prepend/append in search forms */ - -.form-search .input-append .search-query, -.form-search .input-prepend .search-query { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.form-search .input-append .search-query { - -webkit-border-radius: 14px 0 0 14px; - -moz-border-radius: 14px 0 0 14px; - border-radius: 14px 0 0 14px; -} - -.form-search .input-append .btn { - -webkit-border-radius: 0 14px 14px 0; - -moz-border-radius: 0 14px 14px 0; - border-radius: 0 14px 14px 0; -} - -.form-search .input-prepend .search-query { - -webkit-border-radius: 0 14px 14px 0; - -moz-border-radius: 0 14px 14px 0; - border-radius: 0 14px 14px 0; -} - -.form-search .input-prepend .btn { - -webkit-border-radius: 14px 0 0 14px; - -moz-border-radius: 14px 0 0 14px; - border-radius: 14px 0 0 14px; -} - -.form-search input, -.form-inline input, -.form-horizontal input, -.form-search textarea, -.form-inline textarea, -.form-horizontal textarea, -.form-search select, -.form-inline select, -.form-horizontal select, -.form-search .help-inline, -.form-inline .help-inline, -.form-horizontal .help-inline, -.form-search .uneditable-input, -.form-inline .uneditable-input, -.form-horizontal .uneditable-input, -.form-search .input-prepend, -.form-inline .input-prepend, -.form-horizontal .input-prepend, -.form-search .input-append, -.form-inline .input-append, -.form-horizontal .input-append { - display: inline-block; - *display: inline; - margin-bottom: 0; - vertical-align: middle; - *zoom: 1; -} - -.form-search .hide, -.form-inline .hide, -.form-horizontal .hide { - display: none; -} - -.form-search label, -.form-inline label, -.form-search .btn-group, -.form-inline .btn-group { - display: inline-block; -} - -.form-search .input-append, -.form-inline .input-append, -.form-search .input-prepend, -.form-inline .input-prepend { - margin-bottom: 0; -} - -.form-search .radio, -.form-search .checkbox, -.form-inline .radio, -.form-inline .checkbox { - padding-left: 0; - margin-bottom: 0; - vertical-align: middle; -} - -.form-search .radio input[type="radio"], -.form-search .checkbox input[type="checkbox"], -.form-inline .radio input[type="radio"], -.form-inline .checkbox input[type="checkbox"] { - float: left; - margin-right: 3px; - margin-left: 0; -} - -.control-group { - margin-bottom: 10px; -} - -legend + .control-group { - margin-top: 20px; - -webkit-margin-top-collapse: separate; -} - -.form-horizontal .control-group { - margin-bottom: 20px; - *zoom: 1; -} - -.form-horizontal .control-group:before, -.form-horizontal .control-group:after { - display: table; - line-height: 0; - content: ""; -} - -.form-horizontal .control-group:after { - clear: both; -} - -.form-horizontal .control-label { - float: left; - width: 160px; - padding-top: 5px; - text-align: right; -} - -.form-horizontal .controls { - *display: inline-block; - *padding-left: 20px; - margin-left: 180px; - *margin-left: 0; -} - -.form-horizontal .controls:first-child { - *padding-left: 180px; -} - -.form-horizontal .help-block { - margin-bottom: 0; -} - -.form-horizontal input + .help-block, -.form-horizontal select + .help-block, -.form-horizontal textarea + .help-block, -.form-horizontal .uneditable-input + .help-block, -.form-horizontal .input-prepend + .help-block, -.form-horizontal .input-append + .help-block { - margin-top: 10px; -} - -.form-horizontal .form-actions { - padding-left: 180px; -} - -table { - max-width: 100%; - background-color: transparent; - border-collapse: collapse; - border-spacing: 0; -} - -.table { - width: 100%; - margin-bottom: 20px; -} - -.table th, -.table td { - padding: 8px; - line-height: 20px; - text-align: left; - vertical-align: top; - border-top: 1px solid #dddddd; -} - -.table th { - font-weight: bold; -} - -.table thead th { - vertical-align: bottom; -} - -.table caption + thead tr:first-child th, -.table caption + thead tr:first-child td, -.table colgroup + thead tr:first-child th, -.table colgroup + thead tr:first-child td, -.table thead:first-child tr:first-child th, -.table thead:first-child tr:first-child td { - border-top: 0; -} - -.table tbody + tbody { - border-top: 2px solid #dddddd; -} - -.table .table { - background-color: #ffffff; -} - -.table-condensed th, -.table-condensed td { - padding: 4px 5px; -} - -.table-bordered { - border: 1px solid #dddddd; - border-collapse: separate; - *border-collapse: collapse; - border-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.table-bordered th, -.table-bordered td { - border-left: 1px solid #dddddd; -} - -.table-bordered caption + thead tr:first-child th, -.table-bordered caption + tbody tr:first-child th, -.table-bordered caption + tbody tr:first-child td, -.table-bordered colgroup + thead tr:first-child th, -.table-bordered colgroup + tbody tr:first-child th, -.table-bordered colgroup + tbody tr:first-child td, -.table-bordered thead:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child td { - border-top: 0; -} - -.table-bordered thead:first-child tr:first-child > th:first-child, -.table-bordered tbody:first-child tr:first-child > td:first-child, -.table-bordered tbody:first-child tr:first-child > th:first-child { - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; -} - -.table-bordered thead:first-child tr:first-child > th:last-child, -.table-bordered tbody:first-child tr:first-child > td:last-child, -.table-bordered tbody:first-child tr:first-child > th:last-child { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} - -.table-bordered thead:last-child tr:last-child > th:first-child, -.table-bordered tbody:last-child tr:last-child > td:first-child, -.table-bordered tbody:last-child tr:last-child > th:first-child, -.table-bordered tfoot:last-child tr:last-child > td:first-child, -.table-bordered tfoot:last-child tr:last-child > th:first-child { - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; -} - -.table-bordered thead:last-child tr:last-child > th:last-child, -.table-bordered tbody:last-child tr:last-child > td:last-child, -.table-bordered tbody:last-child tr:last-child > th:last-child, -.table-bordered tfoot:last-child tr:last-child > td:last-child, -.table-bordered tfoot:last-child tr:last-child > th:last-child { - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; -} - -.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { - -webkit-border-bottom-left-radius: 0; - border-bottom-left-radius: 0; - -moz-border-radius-bottomleft: 0; -} - -.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { - -webkit-border-bottom-right-radius: 0; - border-bottom-right-radius: 0; - -moz-border-radius-bottomright: 0; -} - -.table-bordered caption + thead tr:first-child th:first-child, -.table-bordered caption + tbody tr:first-child td:first-child, -.table-bordered colgroup + thead tr:first-child th:first-child, -.table-bordered colgroup + tbody tr:first-child td:first-child { - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; -} - -.table-bordered caption + thead tr:first-child th:last-child, -.table-bordered caption + tbody tr:first-child td:last-child, -.table-bordered colgroup + thead tr:first-child th:last-child, -.table-bordered colgroup + tbody tr:first-child td:last-child { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} - -.table-striped tbody > tr:nth-child(odd) > td, -.table-striped tbody > tr:nth-child(odd) > th { - background-color: #f9f9f9; -} - -.table-hover tbody tr:hover > td, -.table-hover tbody tr:hover > th { - background-color: #f5f5f5; -} - -table td[class*="span"], -table th[class*="span"], -.row-fluid table td[class*="span"], -.row-fluid table th[class*="span"] { - display: table-cell; - float: none; - margin-left: 0; -} - -.table td.span1, -.table th.span1 { - float: none; - width: 44px; - margin-left: 0; -} - -.table td.span2, -.table th.span2 { - float: none; - width: 124px; - margin-left: 0; -} - -.table td.span3, -.table th.span3 { - float: none; - width: 204px; - margin-left: 0; -} - -.table td.span4, -.table th.span4 { - float: none; - width: 284px; - margin-left: 0; -} - -.table td.span5, -.table th.span5 { - float: none; - width: 364px; - margin-left: 0; -} - -.table td.span6, -.table th.span6 { - float: none; - width: 444px; - margin-left: 0; -} - -.table td.span7, -.table th.span7 { - float: none; - width: 524px; - margin-left: 0; -} - -.table td.span8, -.table th.span8 { - float: none; - width: 604px; - margin-left: 0; -} - -.table td.span9, -.table th.span9 { - float: none; - width: 684px; - margin-left: 0; -} - -.table td.span10, -.table th.span10 { - float: none; - width: 764px; - margin-left: 0; -} - -.table td.span11, -.table th.span11 { - float: none; - width: 844px; - margin-left: 0; -} - -.table td.span12, -.table th.span12 { - float: none; - width: 924px; - margin-left: 0; -} - -.table tbody tr.success > td { - background-color: #dff0d8; -} - -.table tbody tr.error > td { - background-color: #f2dede; -} - -.table tbody tr.warning > td { - background-color: #fcf8e3; -} - -.table tbody tr.info > td { - background-color: #d9edf7; -} - -.table-hover tbody tr.success:hover > td { - background-color: #d0e9c6; -} - -.table-hover tbody tr.error:hover > td { - background-color: #ebcccc; -} - -.table-hover tbody tr.warning:hover > td { - background-color: #faf2cc; -} - -.table-hover tbody tr.info:hover > td { - background-color: #c4e3f3; -} - -[class^="icon-"], -[class*=" icon-"] { - display: inline-block; - width: 14px; - height: 14px; - margin-top: 1px; - *margin-right: .3em; - line-height: 14px; - vertical-align: text-top; - background-image: url("../img/glyphicons-halflings.png"); - background-position: 14px 14px; - background-repeat: no-repeat; -} - -/* White icons with optional class, or on hover/focus/active states of certain elements */ - -.icon-white, -.nav-pills > .active > a > [class^="icon-"], -.nav-pills > .active > a > [class*=" icon-"], -.nav-list > .active > a > [class^="icon-"], -.nav-list > .active > a > [class*=" icon-"], -.navbar-inverse .nav > .active > a > [class^="icon-"], -.navbar-inverse .nav > .active > a > [class*=" icon-"], -.dropdown-menu > li > a:hover > [class^="icon-"], -.dropdown-menu > li > a:focus > [class^="icon-"], -.dropdown-menu > li > a:hover > [class*=" icon-"], -.dropdown-menu > li > a:focus > [class*=" icon-"], -.dropdown-menu > .active > a > [class^="icon-"], -.dropdown-menu > .active > a > [class*=" icon-"], -.dropdown-submenu:hover > a > [class^="icon-"], -.dropdown-submenu:focus > a > [class^="icon-"], -.dropdown-submenu:hover > a > [class*=" icon-"], -.dropdown-submenu:focus > a > [class*=" icon-"] { - background-image: url("../img/glyphicons-halflings-white.png"); -} - -.icon-glass { - background-position: 0 0; -} - -.icon-music { - background-position: -24px 0; -} - -.icon-search { - background-position: -48px 0; -} - -.icon-envelope { - background-position: -72px 0; -} - -.icon-heart { - background-position: -96px 0; -} - -.icon-star { - background-position: -120px 0; -} - -.icon-star-empty { - background-position: -144px 0; -} - -.icon-user { - background-position: -168px 0; -} - -.icon-film { - background-position: -192px 0; -} - -.icon-th-large { - background-position: -216px 0; -} - -.icon-th { - background-position: -240px 0; -} - -.icon-th-list { - background-position: -264px 0; -} - -.icon-ok { - background-position: -288px 0; -} - -.icon-remove { - background-position: -312px 0; -} - -.icon-zoom-in { - background-position: -336px 0; -} - -.icon-zoom-out { - background-position: -360px 0; -} - -.icon-off { - background-position: -384px 0; -} - -.icon-signal { - background-position: -408px 0; -} - -.icon-cog { - background-position: -432px 0; -} - -.icon-trash { - background-position: -456px 0; -} - -.icon-home { - background-position: 0 -24px; -} - -.icon-file { - background-position: -24px -24px; -} - -.icon-time { - background-position: -48px -24px; -} - -.icon-road { - background-position: -72px -24px; -} - -.icon-download-alt { - background-position: -96px -24px; -} - -.icon-download { - background-position: -120px -24px; -} - -.icon-upload { - background-position: -144px -24px; -} - -.icon-inbox { - background-position: -168px -24px; -} - -.icon-play-circle { - background-position: -192px -24px; -} - -.icon-repeat { - background-position: -216px -24px; -} - -.icon-refresh { - background-position: -240px -24px; -} - -.icon-list-alt { - background-position: -264px -24px; -} - -.icon-lock { - background-position: -287px -24px; -} - -.icon-flag { - background-position: -312px -24px; -} - -.icon-headphones { - background-position: -336px -24px; -} - -.icon-volume-off { - background-position: -360px -24px; -} - -.icon-volume-down { - background-position: -384px -24px; -} - -.icon-volume-up { - background-position: -408px -24px; -} - -.icon-qrcode { - background-position: -432px -24px; -} - -.icon-barcode { - background-position: -456px -24px; -} - -.icon-tag { - background-position: 0 -48px; -} - -.icon-tags { - background-position: -25px -48px; -} - -.icon-book { - background-position: -48px -48px; -} - -.icon-bookmark { - background-position: -72px -48px; -} - -.icon-print { - background-position: -96px -48px; -} - -.icon-camera { - background-position: -120px -48px; -} - -.icon-font { - background-position: -144px -48px; -} - -.icon-bold { - background-position: -167px -48px; -} - -.icon-italic { - background-position: -192px -48px; -} - -.icon-text-height { - background-position: -216px -48px; -} - -.icon-text-width { - background-position: -240px -48px; -} - -.icon-align-left { - background-position: -264px -48px; -} - -.icon-align-center { - background-position: -288px -48px; -} - -.icon-align-right { - background-position: -312px -48px; -} - -.icon-align-justify { - background-position: -336px -48px; -} - -.icon-list { - background-position: -360px -48px; -} - -.icon-indent-left { - background-position: -384px -48px; -} - -.icon-indent-right { - background-position: -408px -48px; -} - -.icon-facetime-video { - background-position: -432px -48px; -} - -.icon-picture { - background-position: -456px -48px; -} - -.icon-pencil { - background-position: 0 -72px; -} - -.icon-map-marker { - background-position: -24px -72px; -} - -.icon-adjust { - background-position: -48px -72px; -} - -.icon-tint { - background-position: -72px -72px; -} - -.icon-edit { - background-position: -96px -72px; -} - -.icon-share { - background-position: -120px -72px; -} - -.icon-check { - background-position: -144px -72px; -} - -.icon-move { - background-position: -168px -72px; -} - -.icon-step-backward { - background-position: -192px -72px; -} - -.icon-fast-backward { - background-position: -216px -72px; -} - -.icon-backward { - background-position: -240px -72px; -} - -.icon-play { - background-position: -264px -72px; -} - -.icon-pause { - background-position: -288px -72px; -} - -.icon-stop { - background-position: -312px -72px; -} - -.icon-forward { - background-position: -336px -72px; -} - -.icon-fast-forward { - background-position: -360px -72px; -} - -.icon-step-forward { - background-position: -384px -72px; -} - -.icon-eject { - background-position: -408px -72px; -} - -.icon-chevron-left { - background-position: -432px -72px; -} - -.icon-chevron-right { - background-position: -456px -72px; -} - -.icon-plus-sign { - background-position: 0 -96px; -} - -.icon-minus-sign { - background-position: -24px -96px; -} - -.icon-remove-sign { - background-position: -48px -96px; -} - -.icon-ok-sign { - background-position: -72px -96px; -} - -.icon-question-sign { - background-position: -96px -96px; -} - -.icon-info-sign { - background-position: -120px -96px; -} - -.icon-screenshot { - background-position: -144px -96px; -} - -.icon-remove-circle { - background-position: -168px -96px; -} - -.icon-ok-circle { - background-position: -192px -96px; -} - -.icon-ban-circle { - background-position: -216px -96px; -} - -.icon-arrow-left { - background-position: -240px -96px; -} - -.icon-arrow-right { - background-position: -264px -96px; -} - -.icon-arrow-up { - background-position: -289px -96px; -} - -.icon-arrow-down { - background-position: -312px -96px; -} - -.icon-share-alt { - background-position: -336px -96px; -} - -.icon-resize-full { - background-position: -360px -96px; -} - -.icon-resize-small { - background-position: -384px -96px; -} - -.icon-plus { - background-position: -408px -96px; -} - -.icon-minus { - background-position: -433px -96px; -} - -.icon-asterisk { - background-position: -456px -96px; -} - -.icon-exclamation-sign { - background-position: 0 -120px; -} - -.icon-gift { - background-position: -24px -120px; -} - -.icon-leaf { - background-position: -48px -120px; -} - -.icon-fire { - background-position: -72px -120px; -} - -.icon-eye-open { - background-position: -96px -120px; -} - -.icon-eye-close { - background-position: -120px -120px; -} - -.icon-warning-sign { - background-position: -144px -120px; -} - -.icon-plane { - background-position: -168px -120px; -} - -.icon-calendar { - background-position: -192px -120px; -} - -.icon-random { - width: 16px; - background-position: -216px -120px; -} - -.icon-comment { - background-position: -240px -120px; -} - -.icon-magnet { - background-position: -264px -120px; -} - -.icon-chevron-up { - background-position: -288px -120px; -} - -.icon-chevron-down { - background-position: -313px -119px; -} - -.icon-retweet { - background-position: -336px -120px; -} - -.icon-shopping-cart { - background-position: -360px -120px; -} - -.icon-folder-close { - width: 16px; - background-position: -384px -120px; -} - -.icon-folder-open { - width: 16px; - background-position: -408px -120px; -} - -.icon-resize-vertical { - background-position: -432px -119px; -} - -.icon-resize-horizontal { - background-position: -456px -118px; -} - -.icon-hdd { - background-position: 0 -144px; -} - -.icon-bullhorn { - background-position: -24px -144px; -} - -.icon-bell { - background-position: -48px -144px; -} - -.icon-certificate { - background-position: -72px -144px; -} - -.icon-thumbs-up { - background-position: -96px -144px; -} - -.icon-thumbs-down { - background-position: -120px -144px; -} - -.icon-hand-right { - background-position: -144px -144px; -} - -.icon-hand-left { - background-position: -168px -144px; -} - -.icon-hand-up { - background-position: -192px -144px; -} - -.icon-hand-down { - background-position: -216px -144px; -} - -.icon-circle-arrow-right { - background-position: -240px -144px; -} - -.icon-circle-arrow-left { - background-position: -264px -144px; -} - -.icon-circle-arrow-up { - background-position: -288px -144px; -} - -.icon-circle-arrow-down { - background-position: -312px -144px; -} - -.icon-globe { - background-position: -336px -144px; -} - -.icon-wrench { - background-position: -360px -144px; -} - -.icon-tasks { - background-position: -384px -144px; -} - -.icon-filter { - background-position: -408px -144px; -} - -.icon-briefcase { - background-position: -432px -144px; -} - -.icon-fullscreen { - background-position: -456px -144px; -} - -.dropup, -.dropdown { - position: relative; -} - -.dropdown-toggle { - *margin-bottom: -3px; -} - -.dropdown-toggle:active, -.open .dropdown-toggle { - outline: 0; -} - -.caret { - display: inline-block; - width: 0; - height: 0; - vertical-align: top; - border-top: 4px solid #000000; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - content: ""; -} - -.dropdown .caret { - margin-top: 8px; - margin-left: 2px; -} - -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - list-style: none; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - *border-right-width: 2px; - *border-bottom-width: 2px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} - -.dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.dropdown-menu .divider { - *width: 100%; - height: 1px; - margin: 9px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} - -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 20px; - color: #333333; - white-space: nowrap; -} - -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus, -.dropdown-submenu:hover > a, -.dropdown-submenu:focus > a { - color: #ffffff; - text-decoration: none; - background-color: #0081c2; - background-image: -moz-linear-gradient(top, #0088cc, #0077b3); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); - background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); - background-image: -o-linear-gradient(top, #0088cc, #0077b3); - background-image: linear-gradient(to bottom, #0088cc, #0077b3); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); -} - -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #ffffff; - text-decoration: none; - background-color: #0081c2; - background-image: -moz-linear-gradient(top, #0088cc, #0077b3); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); - background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); - background-image: -o-linear-gradient(top, #0088cc, #0077b3); - background-image: linear-gradient(to bottom, #0088cc, #0077b3); - background-repeat: repeat-x; - outline: 0; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); -} - -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #999999; -} - -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: default; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.open { - *z-index: 1000; -} - -.open > .dropdown-menu { - display: block; -} - -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} - -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} - -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - border-top: 0; - border-bottom: 4px solid #000000; - content: ""; -} - -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} - -.dropdown-submenu { - position: relative; -} - -.dropdown-submenu > .dropdown-menu { - top: 0; - left: 100%; - margin-top: -6px; - margin-left: -1px; - -webkit-border-radius: 0 6px 6px 6px; - -moz-border-radius: 0 6px 6px 6px; - border-radius: 0 6px 6px 6px; -} - -.dropdown-submenu:hover > .dropdown-menu { - display: block; -} - -.dropup .dropdown-submenu > .dropdown-menu { - top: auto; - bottom: 0; - margin-top: 0; - margin-bottom: -2px; - -webkit-border-radius: 5px 5px 5px 0; - -moz-border-radius: 5px 5px 5px 0; - border-radius: 5px 5px 5px 0; -} - -.dropdown-submenu > a:after { - display: block; - float: right; - width: 0; - height: 0; - margin-top: 5px; - margin-right: -10px; - border-color: transparent; - border-left-color: #cccccc; - border-style: solid; - border-width: 5px 0 5px 5px; - content: " "; -} - -.dropdown-submenu:hover > a:after { - border-left-color: #ffffff; -} - -.dropdown-submenu.pull-left { - float: none; -} - -.dropdown-submenu.pull-left > .dropdown-menu { - left: -100%; - margin-left: 10px; - -webkit-border-radius: 6px 0 6px 6px; - -moz-border-radius: 6px 0 6px 6px; - border-radius: 6px 0 6px 6px; -} - -.dropdown .dropdown-menu .nav-header { - padding-right: 20px; - padding-left: 20px; -} - -.typeahead { - z-index: 1051; - margin-top: 2px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} - -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} - -.well-large { - padding: 24px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.well-small { - padding: 9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - -moz-transition: opacity 0.15s linear; - -o-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} - -.fade.in { - opacity: 1; -} - -.collapse { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height 0.35s ease; - -moz-transition: height 0.35s ease; - -o-transition: height 0.35s ease; - transition: height 0.35s ease; -} - -.collapse.in { - height: auto; -} - -.close { - float: right; - font-size: 20px; - font-weight: bold; - line-height: 20px; - color: #000000; - text-shadow: 0 1px 0 #ffffff; - opacity: 0.2; - filter: alpha(opacity=20); -} - -.close:hover, -.close:focus { - color: #000000; - text-decoration: none; - cursor: pointer; - opacity: 0.4; - filter: alpha(opacity=40); -} - -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} - -.btn { - display: inline-block; - *display: inline; - padding: 4px 12px; - margin-bottom: 0; - *margin-left: .3em; - font-size: 14px; - line-height: 20px; - color: #333333; - text-align: center; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - vertical-align: middle; - cursor: pointer; - background-color: #f5f5f5; - *background-color: #e6e6e6; - background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); - background-repeat: repeat-x; - border: 1px solid #cccccc; - *border: 0; - border-color: #e6e6e6 #e6e6e6 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-bottom-color: #b3b3b3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn:hover, -.btn:focus, -.btn:active, -.btn.active, -.btn.disabled, -.btn[disabled] { - color: #333333; - background-color: #e6e6e6; - *background-color: #d9d9d9; -} - -.btn:active, -.btn.active { - background-color: #cccccc \9; -} - -.btn:first-child { - *margin-left: 0; -} - -.btn:hover, -.btn:focus { - color: #333333; - text-decoration: none; - background-position: 0 -15px; - -webkit-transition: background-position 0.1s linear; - -moz-transition: background-position 0.1s linear; - -o-transition: background-position 0.1s linear; - transition: background-position 0.1s linear; -} - -.btn:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.btn.active, -.btn:active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn.disabled, -.btn[disabled] { - cursor: default; - background-image: none; - opacity: 0.65; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} - -.btn-large { - padding: 11px 19px; - font-size: 17.5px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.btn-large [class^="icon-"], -.btn-large [class*=" icon-"] { - margin-top: 4px; -} - -.btn-small { - padding: 2px 10px; - font-size: 11.9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.btn-small [class^="icon-"], -.btn-small [class*=" icon-"] { - margin-top: 0; -} - -.btn-mini [class^="icon-"], -.btn-mini [class*=" icon-"] { - margin-top: -1px; -} - -.btn-mini { - padding: 0 6px; - font-size: 10.5px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.btn-block { - display: block; - width: 100%; - padding-right: 0; - padding-left: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.btn-block + .btn-block { - margin-top: 5px; -} - -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} - -.btn-primary.active, -.btn-warning.active, -.btn-danger.active, -.btn-success.active, -.btn-info.active, -.btn-inverse.active { - color: rgba(255, 255, 255, 0.75); -} - -.btn-primary { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #006dcc; - *background-color: #0044cc; - background-image: -moz-linear-gradient(top, #0088cc, #0044cc); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); - background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); - background-image: -o-linear-gradient(top, #0088cc, #0044cc); - background-image: linear-gradient(to bottom, #0088cc, #0044cc); - background-repeat: repeat-x; - border-color: #0044cc #0044cc #002a80; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.btn-primary.disabled, -.btn-primary[disabled] { - color: #ffffff; - background-color: #0044cc; - *background-color: #003bb3; -} - -.btn-primary:active, -.btn-primary.active { - background-color: #003399 \9; -} - -.btn-warning { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #faa732; - *background-color: #f89406; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(to bottom, #fbb450, #f89406); - background-repeat: repeat-x; - border-color: #f89406 #f89406 #ad6704; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-warning:hover, -.btn-warning:focus, -.btn-warning:active, -.btn-warning.active, -.btn-warning.disabled, -.btn-warning[disabled] { - color: #ffffff; - background-color: #f89406; - *background-color: #df8505; -} - -.btn-warning:active, -.btn-warning.active { - background-color: #c67605 \9; -} - -.btn-danger { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #da4f49; - *background-color: #bd362f; - background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); - background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); - background-repeat: repeat-x; - border-color: #bd362f #bd362f #802420; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-danger:hover, -.btn-danger:focus, -.btn-danger:active, -.btn-danger.active, -.btn-danger.disabled, -.btn-danger[disabled] { - color: #ffffff; - background-color: #bd362f; - *background-color: #a9302a; -} - -.btn-danger:active, -.btn-danger.active { - background-color: #942a25 \9; -} - -.btn-success { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #5bb75b; - *background-color: #51a351; - background-image: -moz-linear-gradient(top, #62c462, #51a351); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); - background-image: -webkit-linear-gradient(top, #62c462, #51a351); - background-image: -o-linear-gradient(top, #62c462, #51a351); - background-image: linear-gradient(to bottom, #62c462, #51a351); - background-repeat: repeat-x; - border-color: #51a351 #51a351 #387038; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-success:hover, -.btn-success:focus, -.btn-success:active, -.btn-success.active, -.btn-success.disabled, -.btn-success[disabled] { - color: #ffffff; - background-color: #51a351; - *background-color: #499249; -} - -.btn-success:active, -.btn-success.active { - background-color: #408140 \9; -} - -.btn-info { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #49afcd; - *background-color: #2f96b4; - background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); - background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); - background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); - background-repeat: repeat-x; - border-color: #2f96b4 #2f96b4 #1f6377; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-info:hover, -.btn-info:focus, -.btn-info:active, -.btn-info.active, -.btn-info.disabled, -.btn-info[disabled] { - color: #ffffff; - background-color: #2f96b4; - *background-color: #2a85a0; -} - -.btn-info:active, -.btn-info.active { - background-color: #24748c \9; -} - -.btn-inverse { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #363636; - *background-color: #222222; - background-image: -moz-linear-gradient(top, #444444, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); - background-image: -webkit-linear-gradient(top, #444444, #222222); - background-image: -o-linear-gradient(top, #444444, #222222); - background-image: linear-gradient(to bottom, #444444, #222222); - background-repeat: repeat-x; - border-color: #222222 #222222 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-inverse:hover, -.btn-inverse:focus, -.btn-inverse:active, -.btn-inverse.active, -.btn-inverse.disabled, -.btn-inverse[disabled] { - color: #ffffff; - background-color: #222222; - *background-color: #151515; -} - -.btn-inverse:active, -.btn-inverse.active { - background-color: #080808 \9; -} - -button.btn, -input[type="submit"].btn { - *padding-top: 3px; - *padding-bottom: 3px; -} - -button.btn::-moz-focus-inner, -input[type="submit"].btn::-moz-focus-inner { - padding: 0; - border: 0; -} - -button.btn.btn-large, -input[type="submit"].btn.btn-large { - *padding-top: 7px; - *padding-bottom: 7px; -} - -button.btn.btn-small, -input[type="submit"].btn.btn-small { - *padding-top: 3px; - *padding-bottom: 3px; -} - -button.btn.btn-mini, -input[type="submit"].btn.btn-mini { - *padding-top: 1px; - *padding-bottom: 1px; -} - -.btn-link, -.btn-link:active, -.btn-link[disabled] { - background-color: transparent; - background-image: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} - -.btn-link { - color: #0088cc; - cursor: pointer; - border-color: transparent; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-link:hover, -.btn-link:focus { - color: #005580; - text-decoration: underline; - background-color: transparent; -} - -.btn-link[disabled]:hover, -.btn-link[disabled]:focus { - color: #333333; - text-decoration: none; -} - -.btn-group { - position: relative; - display: inline-block; - *display: inline; - *margin-left: .3em; - font-size: 0; - white-space: nowrap; - vertical-align: middle; - *zoom: 1; -} - -.btn-group:first-child { - *margin-left: 0; -} - -.btn-group + .btn-group { - margin-left: 5px; -} - -.btn-toolbar { - margin-top: 10px; - margin-bottom: 10px; - font-size: 0; -} - -.btn-toolbar > .btn + .btn, -.btn-toolbar > .btn-group + .btn, -.btn-toolbar > .btn + .btn-group { - margin-left: 5px; -} - -.btn-group > .btn { - position: relative; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-group > .btn + .btn { - margin-left: -1px; -} - -.btn-group > .btn, -.btn-group > .dropdown-menu, -.btn-group > .popover { - font-size: 14px; -} - -.btn-group > .btn-mini { - font-size: 10.5px; -} - -.btn-group > .btn-small { - font-size: 11.9px; -} - -.btn-group > .btn-large { - font-size: 17.5px; -} - -.btn-group > .btn:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-topleft: 4px; -} - -.btn-group > .btn:last-child, -.btn-group > .dropdown-toggle { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; -} - -.btn-group > .btn.large:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; - -webkit-border-top-left-radius: 6px; - border-top-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-topleft: 6px; -} - -.btn-group > .btn.large:last-child, -.btn-group > .large.dropdown-toggle { - -webkit-border-top-right-radius: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-topright: 6px; - -moz-border-radius-bottomright: 6px; -} - -.btn-group > .btn:hover, -.btn-group > .btn:focus, -.btn-group > .btn:active, -.btn-group > .btn.active { - z-index: 2; -} - -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} - -.btn-group > .btn + .dropdown-toggle { - *padding-top: 5px; - padding-right: 8px; - *padding-bottom: 5px; - padding-left: 8px; - -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn-group > .btn-mini + .dropdown-toggle { - *padding-top: 2px; - padding-right: 5px; - *padding-bottom: 2px; - padding-left: 5px; -} - -.btn-group > .btn-small + .dropdown-toggle { - *padding-top: 5px; - *padding-bottom: 4px; -} - -.btn-group > .btn-large + .dropdown-toggle { - *padding-top: 7px; - padding-right: 12px; - *padding-bottom: 7px; - padding-left: 12px; -} - -.btn-group.open .dropdown-toggle { - background-image: none; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn-group.open .btn.dropdown-toggle { - background-color: #e6e6e6; -} - -.btn-group.open .btn-primary.dropdown-toggle { - background-color: #0044cc; -} - -.btn-group.open .btn-warning.dropdown-toggle { - background-color: #f89406; -} - -.btn-group.open .btn-danger.dropdown-toggle { - background-color: #bd362f; -} - -.btn-group.open .btn-success.dropdown-toggle { - background-color: #51a351; -} - -.btn-group.open .btn-info.dropdown-toggle { - background-color: #2f96b4; -} - -.btn-group.open .btn-inverse.dropdown-toggle { - background-color: #222222; -} - -.btn .caret { - margin-top: 8px; - margin-left: 0; -} - -.btn-large .caret { - margin-top: 6px; -} - -.btn-large .caret { - border-top-width: 5px; - border-right-width: 5px; - border-left-width: 5px; -} - -.btn-mini .caret, -.btn-small .caret { - margin-top: 8px; -} - -.dropup .btn-large .caret { - border-bottom-width: 5px; -} - -.btn-primary .caret, -.btn-warning .caret, -.btn-danger .caret, -.btn-info .caret, -.btn-success .caret, -.btn-inverse .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.btn-group-vertical { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - - *zoom: 1; -} - -.btn-group-vertical > .btn { - display: block; - float: none; - max-width: 100%; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-group-vertical > .btn + .btn { - margin-top: -1px; - margin-left: 0; -} - -.btn-group-vertical > .btn:first-child { - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} - -.btn-group-vertical > .btn:last-child { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} - -.btn-group-vertical > .btn-large:first-child { - -webkit-border-radius: 6px 6px 0 0; - -moz-border-radius: 6px 6px 0 0; - border-radius: 6px 6px 0 0; -} - -.btn-group-vertical > .btn-large:last-child { - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; -} - -.alert { - padding: 8px 35px 8px 14px; - margin-bottom: 20px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - background-color: #fcf8e3; - border: 1px solid #fbeed5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.alert, -.alert h4 { - color: #c09853; -} - -.alert h4 { - margin: 0; -} - -.alert .close { - position: relative; - top: -2px; - right: -21px; - line-height: 20px; -} - -.alert-success { - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; -} - -.alert-success h4 { - color: #468847; -} - -.alert-danger, -.alert-error { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; -} - -.alert-danger h4, -.alert-error h4 { - color: #b94a48; -} - -.alert-info { - color: #3a87ad; - background-color: #d9edf7; - border-color: #bce8f1; -} - -.alert-info h4 { - color: #3a87ad; -} - -.alert-block { - padding-top: 14px; - padding-bottom: 14px; -} - -.alert-block > p, -.alert-block > ul { - margin-bottom: 0; -} - -.alert-block p + p { - margin-top: 5px; -} - -.nav { - margin-bottom: 20px; - margin-left: 0; - list-style: none; -} - -.nav > li > a { - display: block; -} - -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} - -.nav > li > a > img { - max-width: none; -} - -.nav > .pull-right { - float: right; -} - -.nav-header { - display: block; - padding: 3px 15px; - font-size: 11px; - font-weight: bold; - line-height: 20px; - color: #999999; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - text-transform: uppercase; -} - -.nav li + .nav-header { - margin-top: 9px; -} - -.nav-list { - padding-right: 15px; - padding-left: 15px; - margin-bottom: 0; -} - -.nav-list > li > a, -.nav-list .nav-header { - margin-right: -15px; - margin-left: -15px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -} - -.nav-list > li > a { - padding: 3px 15px; -} - -.nav-list > .active > a, -.nav-list > .active > a:hover, -.nav-list > .active > a:focus { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); - background-color: #0088cc; -} - -.nav-list [class^="icon-"], -.nav-list [class*=" icon-"] { - margin-right: 2px; -} - -.nav-list .divider { - *width: 100%; - height: 1px; - margin: 9px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} - -.nav-tabs, -.nav-pills { - *zoom: 1; -} - -.nav-tabs:before, -.nav-pills:before, -.nav-tabs:after, -.nav-pills:after { - display: table; - line-height: 0; - content: ""; -} - -.nav-tabs:after, -.nav-pills:after { - clear: both; -} - -.nav-tabs > li, -.nav-pills > li { - float: left; -} - -.nav-tabs > li > a, -.nav-pills > li > a { - padding-right: 12px; - padding-left: 12px; - margin-right: 2px; - line-height: 14px; -} - -.nav-tabs { - border-bottom: 1px solid #ddd; -} - -.nav-tabs > li { - margin-bottom: -1px; -} - -.nav-tabs > li > a { - padding-top: 8px; - padding-bottom: 8px; - line-height: 20px; - border: 1px solid transparent; - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} - -.nav-tabs > li > a:hover, -.nav-tabs > li > a:focus { - border-color: #eeeeee #eeeeee #dddddd; -} - -.nav-tabs > .active > a, -.nav-tabs > .active > a:hover, -.nav-tabs > .active > a:focus { - color: #555555; - cursor: default; - background-color: #ffffff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} - -.nav-pills > li > a { - padding-top: 8px; - padding-bottom: 8px; - margin-top: 2px; - margin-bottom: 2px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} - -.nav-pills > .active > a, -.nav-pills > .active > a:hover, -.nav-pills > .active > a:focus { - color: #ffffff; - background-color: #0088cc; -} - -.nav-stacked > li { - float: none; -} - -.nav-stacked > li > a { - margin-right: 0; -} - -.nav-tabs.nav-stacked { - border-bottom: 0; -} - -.nav-tabs.nav-stacked > li > a { - border: 1px solid #ddd; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.nav-tabs.nav-stacked > li:first-child > a { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-topleft: 4px; -} - -.nav-tabs.nav-stacked > li:last-child > a { - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -moz-border-radius-bottomright: 4px; - -moz-border-radius-bottomleft: 4px; -} - -.nav-tabs.nav-stacked > li > a:hover, -.nav-tabs.nav-stacked > li > a:focus { - z-index: 2; - border-color: #ddd; -} - -.nav-pills.nav-stacked > li > a { - margin-bottom: 3px; -} - -.nav-pills.nav-stacked > li:last-child > a { - margin-bottom: 1px; -} - -.nav-tabs .dropdown-menu { - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; -} - -.nav-pills .dropdown-menu { - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.nav .dropdown-toggle .caret { - margin-top: 6px; - border-top-color: #0088cc; - border-bottom-color: #0088cc; -} - -.nav .dropdown-toggle:hover .caret, -.nav .dropdown-toggle:focus .caret { - border-top-color: #005580; - border-bottom-color: #005580; -} - -/* move down carets for tabs */ - -.nav-tabs .dropdown-toggle .caret { - margin-top: 8px; -} - -.nav .active .dropdown-toggle .caret { - border-top-color: #fff; - border-bottom-color: #fff; -} - -.nav-tabs .active .dropdown-toggle .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} - -.nav > .dropdown.active > a:hover, -.nav > .dropdown.active > a:focus { - cursor: pointer; -} - -.nav-tabs .open .dropdown-toggle, -.nav-pills .open .dropdown-toggle, -.nav > li.dropdown.open.active > a:hover, -.nav > li.dropdown.open.active > a:focus { - color: #ffffff; - background-color: #999999; - border-color: #999999; -} - -.nav li.dropdown.open .caret, -.nav li.dropdown.open.active .caret, -.nav li.dropdown.open a:hover .caret, -.nav li.dropdown.open a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; - opacity: 1; - filter: alpha(opacity=100); -} - -.tabs-stacked .open > a:hover, -.tabs-stacked .open > a:focus { - border-color: #999999; -} - -.tabbable { - *zoom: 1; -} - -.tabbable:before, -.tabbable:after { - display: table; - line-height: 0; - content: ""; -} - -.tabbable:after { - clear: both; -} - -.tab-content { - overflow: auto; -} - -.tabs-below > .nav-tabs, -.tabs-right > .nav-tabs, -.tabs-left > .nav-tabs { - border-bottom: 0; -} - -.tab-content > .tab-pane, -.pill-content > .pill-pane { - display: none; -} - -.tab-content > .active, -.pill-content > .active { - display: block; -} - -.tabs-below > .nav-tabs { - border-top: 1px solid #ddd; -} - -.tabs-below > .nav-tabs > li { - margin-top: -1px; - margin-bottom: 0; -} - -.tabs-below > .nav-tabs > li > a { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} - -.tabs-below > .nav-tabs > li > a:hover, -.tabs-below > .nav-tabs > li > a:focus { - border-top-color: #ddd; - border-bottom-color: transparent; -} - -.tabs-below > .nav-tabs > .active > a, -.tabs-below > .nav-tabs > .active > a:hover, -.tabs-below > .nav-tabs > .active > a:focus { - border-color: transparent #ddd #ddd #ddd; -} - -.tabs-left > .nav-tabs > li, -.tabs-right > .nav-tabs > li { - float: none; -} - -.tabs-left > .nav-tabs > li > a, -.tabs-right > .nav-tabs > li > a { - min-width: 74px; - margin-right: 0; - margin-bottom: 3px; -} - -.tabs-left > .nav-tabs { - float: left; - margin-right: 19px; - border-right: 1px solid #ddd; -} - -.tabs-left > .nav-tabs > li > a { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.tabs-left > .nav-tabs > li > a:hover, -.tabs-left > .nav-tabs > li > a:focus { - border-color: #eeeeee #dddddd #eeeeee #eeeeee; -} - -.tabs-left > .nav-tabs .active > a, -.tabs-left > .nav-tabs .active > a:hover, -.tabs-left > .nav-tabs .active > a:focus { - border-color: #ddd transparent #ddd #ddd; - *border-right-color: #ffffff; -} - -.tabs-right > .nav-tabs { - float: right; - margin-left: 19px; - border-left: 1px solid #ddd; -} - -.tabs-right > .nav-tabs > li > a { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.tabs-right > .nav-tabs > li > a:hover, -.tabs-right > .nav-tabs > li > a:focus { - border-color: #eeeeee #eeeeee #eeeeee #dddddd; -} - -.tabs-right > .nav-tabs .active > a, -.tabs-right > .nav-tabs .active > a:hover, -.tabs-right > .nav-tabs .active > a:focus { - border-color: #ddd #ddd #ddd transparent; - *border-left-color: #ffffff; -} - -.nav > .disabled > a { - color: #999999; -} - -.nav > .disabled > a:hover, -.nav > .disabled > a:focus { - text-decoration: none; - cursor: default; - background-color: transparent; -} - -.navbar { - *position: relative; - *z-index: 2; - margin-bottom: 20px; - overflow: visible; -} - -.navbar-inner { - min-height: 40px; - padding-right: 20px; - padding-left: 20px; - background-color: #fafafa; - background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); - background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); - background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); - background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); - background-repeat: repeat-x; - border: 1px solid #d4d4d4; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); - *zoom: 1; - -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); -} - -.navbar-inner:before, -.navbar-inner:after { - display: table; - line-height: 0; - content: ""; -} - -.navbar-inner:after { - clear: both; -} - -.navbar .container { - width: auto; -} - -.nav-collapse.collapse { - height: auto; - overflow: visible; -} - -.navbar .brand { - display: block; - float: left; - padding: 10px 20px 10px; - margin-left: -20px; - font-size: 20px; - font-weight: 200; - color: #777777; - text-shadow: 0 1px 0 #ffffff; -} - -.navbar .brand:hover, -.navbar .brand:focus { - text-decoration: none; -} - -.navbar-text { - margin-bottom: 0; - line-height: 40px; - color: #777777; -} - -.navbar-link { - color: #777777; -} - -.navbar-link:hover, -.navbar-link:focus { - color: #333333; -} - -.navbar .divider-vertical { - height: 40px; - margin: 0 9px; - border-right: 1px solid #ffffff; - border-left: 1px solid #f2f2f2; -} - -.navbar .btn, -.navbar .btn-group { - margin-top: 5px; -} - -.navbar .btn-group .btn, -.navbar .input-prepend .btn, -.navbar .input-append .btn, -.navbar .input-prepend .btn-group, -.navbar .input-append .btn-group { - margin-top: 0; -} - -.navbar-form { - margin-bottom: 0; - *zoom: 1; -} - -.navbar-form:before, -.navbar-form:after { - display: table; - line-height: 0; - content: ""; -} - -.navbar-form:after { - clear: both; -} - -.navbar-form input, -.navbar-form select, -.navbar-form .radio, -.navbar-form .checkbox { - margin-top: 5px; -} - -.navbar-form input, -.navbar-form select, -.navbar-form .btn { - display: inline-block; - margin-bottom: 0; -} - -.navbar-form input[type="image"], -.navbar-form input[type="checkbox"], -.navbar-form input[type="radio"] { - margin-top: 3px; -} - -.navbar-form .input-append, -.navbar-form .input-prepend { - margin-top: 5px; - white-space: nowrap; -} - -.navbar-form .input-append input, -.navbar-form .input-prepend input { - margin-top: 0; -} - -.navbar-search { - position: relative; - float: left; - margin-top: 5px; - margin-bottom: 0; -} - -.navbar-search .search-query { - padding: 4px 14px; - margin-bottom: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: 1; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -.navbar-static-top { - position: static; - margin-bottom: 0; -} - -.navbar-static-top .navbar-inner { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; - margin-bottom: 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-static-top .navbar-inner { - border-width: 0 0 1px; -} - -.navbar-fixed-bottom .navbar-inner { - border-width: 1px 0 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-fixed-bottom .navbar-inner { - padding-right: 0; - padding-left: 0; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.navbar-static-top .container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} - -.navbar-fixed-top { - top: 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-static-top .navbar-inner { - -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); -} - -.navbar-fixed-bottom { - bottom: 0; -} - -.navbar-fixed-bottom .navbar-inner { - -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); - box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); -} - -.navbar .nav { - position: relative; - left: 0; - display: block; - float: left; - margin: 0 10px 0 0; -} - -.navbar .nav.pull-right { - float: right; - margin-right: 0; -} - -.navbar .nav > li { - float: left; -} - -.navbar .nav > li > a { - float: none; - padding: 10px 15px 10px; - color: #777777; - text-decoration: none; - text-shadow: 0 1px 0 #ffffff; -} - -.navbar .nav .dropdown-toggle .caret { - margin-top: 8px; -} - -.navbar .nav > li > a:focus, -.navbar .nav > li > a:hover { - color: #333333; - text-decoration: none; - background-color: transparent; -} - -.navbar .nav > .active > a, -.navbar .nav > .active > a:hover, -.navbar .nav > .active > a:focus { - color: #555555; - text-decoration: none; - background-color: #e5e5e5; - -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); -} - -.navbar .btn-navbar { - display: none; - float: right; - padding: 7px 10px; - margin-right: 5px; - margin-left: 5px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #ededed; - *background-color: #e5e5e5; - background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); - background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); - background-repeat: repeat-x; - border-color: #e5e5e5 #e5e5e5 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); -} - -.navbar .btn-navbar:hover, -.navbar .btn-navbar:focus, -.navbar .btn-navbar:active, -.navbar .btn-navbar.active, -.navbar .btn-navbar.disabled, -.navbar .btn-navbar[disabled] { - color: #ffffff; - background-color: #e5e5e5; - *background-color: #d9d9d9; -} - -.navbar .btn-navbar:active, -.navbar .btn-navbar.active { - background-color: #cccccc \9; -} - -.navbar .btn-navbar .icon-bar { - display: block; - width: 18px; - height: 2px; - background-color: #f5f5f5; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); -} - -.btn-navbar .icon-bar + .icon-bar { - margin-top: 3px; -} - -.navbar .nav > li > .dropdown-menu:before { - position: absolute; - top: -7px; - left: 9px; - display: inline-block; - border-right: 7px solid transparent; - border-bottom: 7px solid #ccc; - border-left: 7px solid transparent; - border-bottom-color: rgba(0, 0, 0, 0.2); - content: ''; -} - -.navbar .nav > li > .dropdown-menu:after { - position: absolute; - top: -6px; - left: 10px; - display: inline-block; - border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; - border-left: 6px solid transparent; - content: ''; -} - -.navbar-fixed-bottom .nav > li > .dropdown-menu:before { - top: auto; - bottom: -7px; - border-top: 7px solid #ccc; - border-bottom: 0; - border-top-color: rgba(0, 0, 0, 0.2); -} - -.navbar-fixed-bottom .nav > li > .dropdown-menu:after { - top: auto; - bottom: -6px; - border-top: 6px solid #ffffff; - border-bottom: 0; -} - -.navbar .nav li.dropdown > a:hover .caret, -.navbar .nav li.dropdown > a:focus .caret { - border-top-color: #333333; - border-bottom-color: #333333; -} - -.navbar .nav li.dropdown.open > .dropdown-toggle, -.navbar .nav li.dropdown.active > .dropdown-toggle, -.navbar .nav li.dropdown.open.active > .dropdown-toggle { - color: #555555; - background-color: #e5e5e5; -} - -.navbar .nav li.dropdown > .dropdown-toggle .caret { - border-top-color: #777777; - border-bottom-color: #777777; -} - -.navbar .nav li.dropdown.open > .dropdown-toggle .caret, -.navbar .nav li.dropdown.active > .dropdown-toggle .caret, -.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} - -.navbar .pull-right > li > .dropdown-menu, -.navbar .nav > li > .dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu:before, -.navbar .nav > li > .dropdown-menu.pull-right:before { - right: 12px; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu:after, -.navbar .nav > li > .dropdown-menu.pull-right:after { - right: 13px; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu .dropdown-menu, -.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { - right: 100%; - left: auto; - margin-right: -1px; - margin-left: 0; - -webkit-border-radius: 6px 0 6px 6px; - -moz-border-radius: 6px 0 6px 6px; - border-radius: 6px 0 6px 6px; -} - -.navbar-inverse .navbar-inner { - background-color: #1b1b1b; - background-image: -moz-linear-gradient(top, #222222, #111111); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); - background-image: -webkit-linear-gradient(top, #222222, #111111); - background-image: -o-linear-gradient(top, #222222, #111111); - background-image: linear-gradient(to bottom, #222222, #111111); - background-repeat: repeat-x; - border-color: #252525; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); -} - -.navbar-inverse .brand, -.navbar-inverse .nav > li > a { - color: #999999; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} - -.navbar-inverse .brand:hover, -.navbar-inverse .nav > li > a:hover, -.navbar-inverse .brand:focus, -.navbar-inverse .nav > li > a:focus { - color: #ffffff; -} - -.navbar-inverse .brand { - color: #999999; -} - -.navbar-inverse .navbar-text { - color: #999999; -} - -.navbar-inverse .nav > li > a:focus, -.navbar-inverse .nav > li > a:hover { - color: #ffffff; - background-color: transparent; -} - -.navbar-inverse .nav .active > a, -.navbar-inverse .nav .active > a:hover, -.navbar-inverse .nav .active > a:focus { - color: #ffffff; - background-color: #111111; -} - -.navbar-inverse .navbar-link { - color: #999999; -} - -.navbar-inverse .navbar-link:hover, -.navbar-inverse .navbar-link:focus { - color: #ffffff; -} - -.navbar-inverse .divider-vertical { - border-right-color: #222222; - border-left-color: #111111; -} - -.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, -.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, -.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { - color: #ffffff; - background-color: #111111; -} - -.navbar-inverse .nav li.dropdown > a:hover .caret, -.navbar-inverse .nav li.dropdown > a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { - border-top-color: #999999; - border-bottom-color: #999999; -} - -.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, -.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, -.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.navbar-inverse .navbar-search .search-query { - color: #ffffff; - background-color: #515151; - border-color: #111111; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -webkit-transition: none; - -moz-transition: none; - -o-transition: none; - transition: none; -} - -.navbar-inverse .navbar-search .search-query:-moz-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query:focus, -.navbar-inverse .navbar-search .search-query.focused { - padding: 5px 15px; - color: #333333; - text-shadow: 0 1px 0 #ffffff; - background-color: #ffffff; - border: 0; - outline: 0; - -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -} - -.navbar-inverse .btn-navbar { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e0e0e; - *background-color: #040404; - background-image: -moz-linear-gradient(top, #151515, #040404); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); - background-image: -webkit-linear-gradient(top, #151515, #040404); - background-image: -o-linear-gradient(top, #151515, #040404); - background-image: linear-gradient(to bottom, #151515, #040404); - background-repeat: repeat-x; - border-color: #040404 #040404 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.navbar-inverse .btn-navbar:hover, -.navbar-inverse .btn-navbar:focus, -.navbar-inverse .btn-navbar:active, -.navbar-inverse .btn-navbar.active, -.navbar-inverse .btn-navbar.disabled, -.navbar-inverse .btn-navbar[disabled] { - color: #ffffff; - background-color: #040404; - *background-color: #000000; -} - -.navbar-inverse .btn-navbar:active, -.navbar-inverse .btn-navbar.active { - background-color: #000000 \9; -} - -.breadcrumb { - padding: 8px 15px; - margin: 0 0 20px; - list-style: none; - background-color: #f5f5f5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.breadcrumb > li { - display: inline-block; - *display: inline; - text-shadow: 0 1px 0 #ffffff; - *zoom: 1; -} - -.breadcrumb > li > .divider { - padding: 0 5px; - color: #ccc; -} - -.breadcrumb > .active { - color: #999999; -} - -.pagination { - margin: 20px 0; -} - -.pagination ul { - display: inline-block; - *display: inline; - margin-bottom: 0; - margin-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - *zoom: 1; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.pagination ul > li { - display: inline; -} - -.pagination ul > li > a, -.pagination ul > li > span { - float: left; - padding: 4px 12px; - line-height: 20px; - text-decoration: none; - background-color: #ffffff; - border: 1px solid #dddddd; - border-left-width: 0; -} - -.pagination ul > li > a:hover, -.pagination ul > li > a:focus, -.pagination ul > .active > a, -.pagination ul > .active > span { - background-color: #f5f5f5; -} - -.pagination ul > .active > a, -.pagination ul > .active > span { - color: #999999; - cursor: default; -} - -.pagination ul > .disabled > span, -.pagination ul > .disabled > a, -.pagination ul > .disabled > a:hover, -.pagination ul > .disabled > a:focus { - color: #999999; - cursor: default; - background-color: transparent; -} - -.pagination ul > li:first-child > a, -.pagination ul > li:first-child > span { - border-left-width: 1px; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-topleft: 4px; -} - -.pagination ul > li:last-child > a, -.pagination ul > li:last-child > span { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; -} - -.pagination-centered { - text-align: center; -} - -.pagination-right { - text-align: right; -} - -.pagination-large ul > li > a, -.pagination-large ul > li > span { - padding: 11px 19px; - font-size: 17.5px; -} - -.pagination-large ul > li:first-child > a, -.pagination-large ul > li:first-child > span { - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; - -webkit-border-top-left-radius: 6px; - border-top-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-topleft: 6px; -} - -.pagination-large ul > li:last-child > a, -.pagination-large ul > li:last-child > span { - -webkit-border-top-right-radius: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-topright: 6px; - -moz-border-radius-bottomright: 6px; -} - -.pagination-mini ul > li:first-child > a, -.pagination-small ul > li:first-child > a, -.pagination-mini ul > li:first-child > span, -.pagination-small ul > li:first-child > span { - -webkit-border-bottom-left-radius: 3px; - border-bottom-left-radius: 3px; - -webkit-border-top-left-radius: 3px; - border-top-left-radius: 3px; - -moz-border-radius-bottomleft: 3px; - -moz-border-radius-topleft: 3px; -} - -.pagination-mini ul > li:last-child > a, -.pagination-small ul > li:last-child > a, -.pagination-mini ul > li:last-child > span, -.pagination-small ul > li:last-child > span { - -webkit-border-top-right-radius: 3px; - border-top-right-radius: 3px; - -webkit-border-bottom-right-radius: 3px; - border-bottom-right-radius: 3px; - -moz-border-radius-topright: 3px; - -moz-border-radius-bottomright: 3px; -} - -.pagination-small ul > li > a, -.pagination-small ul > li > span { - padding: 2px 10px; - font-size: 11.9px; -} - -.pagination-mini ul > li > a, -.pagination-mini ul > li > span { - padding: 0 6px; - font-size: 10.5px; -} - -.pager { - margin: 20px 0; - text-align: center; - list-style: none; - *zoom: 1; -} - -.pager:before, -.pager:after { - display: table; - line-height: 0; - content: ""; -} - -.pager:after { - clear: both; -} - -.pager li { - display: inline; -} - -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #f5f5f5; -} - -.pager .next > a, -.pager .next > span { - float: right; -} - -.pager .previous > a, -.pager .previous > span { - float: left; -} - -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #999999; - cursor: default; - background-color: #fff; -} - -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000000; -} - -.modal-backdrop.fade { - opacity: 0; -} - -.modal-backdrop, -.modal-backdrop.fade.in { - opacity: 0.8; - filter: alpha(opacity=80); -} - -.modal { - position: fixed; - top: 10%; - left: 50%; - z-index: 1050; - width: 560px; - margin-left: -280px; - background-color: #ffffff; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, 0.3); - *border: 1px solid #999; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - outline: none; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} - -.modal.fade { - top: -25%; - -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; - -moz-transition: opacity 0.3s linear, top 0.3s ease-out; - -o-transition: opacity 0.3s linear, top 0.3s ease-out; - transition: opacity 0.3s linear, top 0.3s ease-out; -} - -.modal.fade.in { - top: 10%; -} - -.modal-header { - padding: 9px 15px; - border-bottom: 1px solid #eee; -} - -.modal-header .close { - margin-top: 2px; -} - -.modal-header h3 { - margin: 0; - line-height: 30px; -} - -.modal-body { - position: relative; - max-height: 400px; - padding: 15px; - overflow-y: auto; -} - -.modal-form { - margin-bottom: 0; -} - -.modal-footer { - padding: 14px 15px 15px; - margin-bottom: 0; - text-align: right; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; -} - -.modal-footer:before, -.modal-footer:after { - display: table; - line-height: 0; - content: ""; -} - -.modal-footer:after { - clear: both; -} - -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} - -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} - -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} - -.tooltip { - position: absolute; - z-index: 1030; - display: block; - font-size: 11px; - line-height: 1.4; - opacity: 0; - filter: alpha(opacity=0); - visibility: visible; -} - -.tooltip.in { - opacity: 0.8; - filter: alpha(opacity=80); -} - -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} - -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} - -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} - -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} - -.tooltip-inner { - max-width: 200px; - padding: 8px; - color: #ffffff; - text-align: center; - text-decoration: none; - background-color: #000000; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top-color: #000000; - border-width: 5px 5px 0; -} - -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-right-color: #000000; - border-width: 5px 5px 5px 0; -} - -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-left-color: #000000; - border-width: 5px 0 5px 5px; -} - -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-bottom-color: #000000; - border-width: 0 5px 5px; -} - -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - max-width: 276px; - padding: 1px; - text-align: left; - white-space: normal; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} - -.popover.top { - margin-top: -10px; -} - -.popover.right { - margin-left: 10px; -} - -.popover.bottom { - margin-top: 10px; -} - -.popover.left { - margin-left: -10px; -} - -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - font-weight: normal; - line-height: 18px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - -webkit-border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - border-radius: 5px 5px 0 0; -} - -.popover-title:empty { - display: none; -} - -.popover-content { - padding: 9px 14px; -} - -.popover .arrow, -.popover .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.popover .arrow { - border-width: 11px; -} - -.popover .arrow:after { - border-width: 10px; - content: ""; -} - -.popover.top .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, 0.25); - border-bottom-width: 0; -} - -.popover.top .arrow:after { - bottom: 1px; - margin-left: -10px; - border-top-color: #ffffff; - border-bottom-width: 0; -} - -.popover.right .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, 0.25); - border-left-width: 0; -} - -.popover.right .arrow:after { - bottom: -10px; - left: 1px; - border-right-color: #ffffff; - border-left-width: 0; -} - -.popover.bottom .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, 0.25); - border-top-width: 0; -} - -.popover.bottom .arrow:after { - top: 1px; - margin-left: -10px; - border-bottom-color: #ffffff; - border-top-width: 0; -} - -.popover.left .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, 0.25); - border-right-width: 0; -} - -.popover.left .arrow:after { - right: 1px; - bottom: -10px; - border-left-color: #ffffff; - border-right-width: 0; -} - -.thumbnails { - margin-left: -20px; - list-style: none; - *zoom: 1; -} - -.thumbnails:before, -.thumbnails:after { - display: table; - line-height: 0; - content: ""; -} - -.thumbnails:after { - clear: both; -} - -.row-fluid .thumbnails { - margin-left: 0; -} - -.thumbnails > li { - float: left; - margin-bottom: 20px; - margin-left: 20px; -} - -.thumbnail { - display: block; - padding: 4px; - line-height: 20px; - border: 1px solid #ddd; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} - -a.thumbnail:hover, -a.thumbnail:focus { - border-color: #0088cc; - -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); -} - -.thumbnail > img { - display: block; - max-width: 100%; - margin-right: auto; - margin-left: auto; -} - -.thumbnail .caption { - padding: 9px; - color: #555555; -} - -.media, -.media-body { - overflow: hidden; - *overflow: visible; - zoom: 1; -} - -.media, -.media .media { - margin-top: 15px; -} - -.media:first-child { - margin-top: 0; -} - -.media-object { - display: block; -} - -.media-heading { - margin: 0 0 5px; -} - -.media > .pull-left { - margin-right: 10px; -} - -.media > .pull-right { - margin-left: 10px; -} - -.media-list { - margin-left: 0; - list-style: none; -} - -.label, -.badge { - display: inline-block; - padding: 2px 4px; - font-size: 11.844px; - font-weight: bold; - line-height: 14px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - white-space: nowrap; - vertical-align: baseline; - background-color: #999999; -} - -.label { - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.badge { - padding-right: 9px; - padding-left: 9px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; - border-radius: 9px; -} - -.label:empty, -.badge:empty { - display: none; -} - -a.label:hover, -a.label:focus, -a.badge:hover, -a.badge:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} - -.label-important, -.badge-important { - background-color: #b94a48; -} - -.label-important[href], -.badge-important[href] { - background-color: #953b39; -} - -.label-warning, -.badge-warning { - background-color: #f89406; -} - -.label-warning[href], -.badge-warning[href] { - background-color: #c67605; -} - -.label-success, -.badge-success { - background-color: #468847; -} - -.label-success[href], -.badge-success[href] { - background-color: #356635; -} - -.label-info, -.badge-info { - background-color: #3a87ad; -} - -.label-info[href], -.badge-info[href] { - background-color: #2d6987; -} - -.label-inverse, -.badge-inverse { - background-color: #333333; -} - -.label-inverse[href], -.badge-inverse[href] { - background-color: #1a1a1a; -} - -.btn .label, -.btn .badge { - position: relative; - top: -1px; -} - -.btn-mini .label, -.btn-mini .badge { - top: 0; -} - -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-moz-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-ms-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} - -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f7f7f7; - background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); - background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); - background-repeat: repeat-x; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -} - -.progress .bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - color: #ffffff; - text-align: center; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e90d2; - background-image: -moz-linear-gradient(top, #149bdf, #0480be); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); - background-image: -webkit-linear-gradient(top, #149bdf, #0480be); - background-image: -o-linear-gradient(top, #149bdf, #0480be); - background-image: linear-gradient(to bottom, #149bdf, #0480be); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-transition: width 0.6s ease; - -moz-transition: width 0.6s ease; - -o-transition: width 0.6s ease; - transition: width 0.6s ease; -} - -.progress .bar + .bar { - -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); -} - -.progress-striped .bar { - background-color: #149bdf; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - -moz-background-size: 40px 40px; - -o-background-size: 40px 40px; - background-size: 40px 40px; -} - -.progress.active .bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -ms-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} - -.progress-danger .bar, -.progress .bar-danger { - background-color: #dd514c; - background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); - background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); -} - -.progress-danger.progress-striped .bar, -.progress-striped .bar-danger { - background-color: #ee5f5b; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-success .bar, -.progress .bar-success { - background-color: #5eb95e; - background-image: -moz-linear-gradient(top, #62c462, #57a957); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); - background-image: -webkit-linear-gradient(top, #62c462, #57a957); - background-image: -o-linear-gradient(top, #62c462, #57a957); - background-image: linear-gradient(to bottom, #62c462, #57a957); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); -} - -.progress-success.progress-striped .bar, -.progress-striped .bar-success { - background-color: #62c462; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-info .bar, -.progress .bar-info { - background-color: #4bb1cf; - background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); - background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); - background-image: -o-linear-gradient(top, #5bc0de, #339bb9); - background-image: linear-gradient(to bottom, #5bc0de, #339bb9); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); -} - -.progress-info.progress-striped .bar, -.progress-striped .bar-info { - background-color: #5bc0de; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-warning .bar, -.progress .bar-warning { - background-color: #faa732; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(to bottom, #fbb450, #f89406); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); -} - -.progress-warning.progress-striped .bar, -.progress-striped .bar-warning { - background-color: #fbb450; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.accordion { - margin-bottom: 20px; -} - -.accordion-group { - margin-bottom: 2px; - border: 1px solid #e5e5e5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.accordion-heading { - border-bottom: 0; -} - -.accordion-heading .accordion-toggle { - display: block; - padding: 8px 15px; -} - -.accordion-toggle { - cursor: pointer; -} - -.accordion-inner { - padding: 9px 15px; - border-top: 1px solid #e5e5e5; -} - -.carousel { - position: relative; - margin-bottom: 20px; - line-height: 1; -} - -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} - -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: 0.6s ease-in-out left; - -moz-transition: 0.6s ease-in-out left; - -o-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} - -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - line-height: 1; -} - -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} - -.carousel-inner > .active { - left: 0; -} - -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} - -.carousel-inner > .next { - left: 100%; -} - -.carousel-inner > .prev { - left: -100%; -} - -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} - -.carousel-inner > .active.left { - left: -100%; -} - -.carousel-inner > .active.right { - left: 100%; -} - -.carousel-control { - position: absolute; - top: 40%; - left: 15px; - width: 40px; - height: 40px; - margin-top: -20px; - font-size: 60px; - font-weight: 100; - line-height: 30px; - color: #ffffff; - text-align: center; - background: #222222; - border: 3px solid #ffffff; - -webkit-border-radius: 23px; - -moz-border-radius: 23px; - border-radius: 23px; - opacity: 0.5; - filter: alpha(opacity=50); -} - -.carousel-control.right { - right: 15px; - left: auto; -} - -.carousel-control:hover, -.carousel-control:focus { - color: #ffffff; - text-decoration: none; - opacity: 0.9; - filter: alpha(opacity=90); -} - -.carousel-indicators { - position: absolute; - top: 15px; - right: 15px; - z-index: 5; - margin: 0; - list-style: none; -} - -.carousel-indicators li { - display: block; - float: left; - width: 10px; - height: 10px; - margin-left: 5px; - text-indent: -999px; - background-color: #ccc; - background-color: rgba(255, 255, 255, 0.25); - border-radius: 5px; -} - -.carousel-indicators .active { - background-color: #fff; -} - -.carousel-caption { - position: absolute; - right: 0; - bottom: 0; - left: 0; - padding: 15px; - background: #333333; - background: rgba(0, 0, 0, 0.75); -} - -.carousel-caption h4, -.carousel-caption p { - line-height: 20px; - color: #ffffff; -} - -.carousel-caption h4 { - margin: 0 0 5px; -} - -.carousel-caption p { - margin-bottom: 0; -} - -.hero-unit { - padding: 60px; - margin-bottom: 30px; - font-size: 18px; - font-weight: 200; - line-height: 30px; - color: inherit; - background-color: #eeeeee; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.hero-unit h1 { - margin-bottom: 0; - font-size: 60px; - line-height: 1; - letter-spacing: -1px; - color: inherit; -} - -.hero-unit li { - line-height: 30px; -} - -.pull-right { - float: right; -} - -.pull-left { - float: left; -} - -.hide { - display: none; -} - -.show { - display: block; -} - -.invisible { - visibility: hidden; -} - -.affix { - position: fixed; -} diff --git a/spring-security-login-and-registration/src/main/webapp/resources/pwstrength.js b/spring-security-login-and-registration/src/main/webapp/resources/pwstrength.js deleted file mode 100644 index 0a08b4d065..0000000000 --- a/spring-security-login-and-registration/src/main/webapp/resources/pwstrength.js +++ /dev/null @@ -1,4 +0,0 @@ -/* pwstrength-bootstrap 2015-02-07 - GPLv3 & MIT License */ - -!function(a){var b={};try{if(!a&&module&&module.exports){var a=require("jquery"),c=require("jsdom").jsdom;a=a(c().parentWindow)}}catch(d){}!function(a,b){"use strict";var c={};b.forbiddenSequences=["0123456789","abcdefghijklmnopqrstuvwxyz","qwertyuiop","asdfghjkl","zxcvbnm","!@#$%^&*()_+"],c.wordNotEmail=function(a,b,c){return b.match(/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i)?c:0},c.wordLength=function(a,b,c){var d=b.length,e=Math.pow(d,a.rules.raisePower);return d2&&(a.each(b.forbiddenSequences,function(b,c){var e=[c,c.split("").reverse().join("")];a.each(e,function(a,b){for(f=0;f-1&&(g=!0)})}),g)?e:0},c.wordLowercase=function(a,b,c){return b.match(/[a-z]/)&&c},c.wordUppercase=function(a,b,c){return b.match(/[A-Z]/)&&c},c.wordOneNumber=function(a,b,c){return b.match(/\d+/)&&c},c.wordThreeNumbers=function(a,b,c){return b.match(/(.*[0-9].*[0-9].*[0-9])/)&&c},c.wordOneSpecialChar=function(a,b,c){return b.match(/[!,@,#,$,%,\^,&,*,?,_,~]/)&&c},c.wordTwoSpecialChar=function(a,b,c){return b.match(/(.*[!,@,#,$,%,\^,&,*,?,_,~].*[!,@,#,$,%,\^,&,*,?,_,~])/)&&c},c.wordUpperLowerCombo=function(a,b,c){return b.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)&&c},c.wordLetterNumberCombo=function(a,b,c){return b.match(/([a-zA-Z])/)&&b.match(/([0-9])/)&&c},c.wordLetterNumberCharCombo=function(a,b,c){return b.match(/([a-zA-Z0-9].*[!,@,#,$,%,\^,&,*,?,_,~])|([!,@,#,$,%,\^,&,*,?,_,~].*[a-zA-Z0-9])/)&&c},b.validation=c,b.executeRules=function(c,d){var e=0;return a.each(c.rules.activated,function(f,g){if(g){var h,i,j=c.rules.scores[f],k=b.validation[f];a.isFunction(k)||(k=c.rules.extra[f]),a.isFunction(k)&&(h=k(c,d,j),h&&(e+=h),(0>h||!a.isNumeric(h)&&!h)&&(i=c.ui.spanError(c,f),i.length>0&&c.instances.errors.push(i)))}}),e}}(a,b);try{module&&module.exports&&(module.exports=b)}catch(d){}var e={};e.common={},e.common.minChar=6,e.common.usernameField="#username",e.common.userInputs=[],e.common.onLoad=void 0,e.common.onKeyUp=void 0,e.common.zxcvbn=!1,e.common.zxcvbnTerms=[],e.common.debug=!1,e.rules={},e.rules.extra={},e.rules.scores={wordNotEmail:-100,wordLength:-50,wordSimilarToUsername:-100,wordSequences:-50,wordTwoCharacterClasses:2,wordRepetitions:-25,wordLowercase:1,wordUppercase:3,wordOneNumber:3,wordThreeNumbers:5,wordOneSpecialChar:3,wordTwoSpecialChar:5,wordUpperLowerCombo:2,wordLetterNumberCombo:2,wordLetterNumberCharCombo:2},e.rules.activated={wordNotEmail:!0,wordLength:!0,wordSimilarToUsername:!0,wordSequences:!0,wordTwoCharacterClasses:!1,wordRepetitions:!1,wordLowercase:!0,wordUppercase:!0,wordOneNumber:!0,wordThreeNumbers:!0,wordOneSpecialChar:!0,wordTwoSpecialChar:!0,wordUpperLowerCombo:!0,wordLetterNumberCombo:!0,wordLetterNumberCharCombo:!0},e.rules.raisePower=1.4,e.ui={},e.ui.bootstrap2=!1,e.ui.showProgressBar=!0,e.ui.showPopover=!1,e.ui.showStatus=!1,e.ui.spanError=function(a,b){"use strict";var c=a.ui.errorMessages[b];return c?''+c+"":""},e.ui.popoverError=function(b){"use strict";var c="
    Errors:
      ";return a.each(b,function(a,b){c+="
    • "+b+"
    • "}),c+="
    "},e.ui.errorMessages={wordLength:"Your password is too short",wordNotEmail:"Do not use your email as your password",wordSimilarToUsername:"Your password cannot contain your username",wordTwoCharacterClasses:"Use different character classes",wordRepetitions:"Too many repetitions",wordSequences:"Your password contains sequences"},e.ui.verdicts=["Weak","Normal","Medium","Strong","Very Strong"],e.ui.showVerdicts=!0,e.ui.showVerdictsInsideProgressBar=!1,e.ui.useVerdictCssClass=!1,e.ui.showErrors=!1,e.ui.container=void 0,e.ui.viewports={progress:void 0,verdict:void 0,errors:void 0},e.ui.scores=[14,26,38,50];var f={};!function(a,b){"use strict";var c=["danger","warning","success"],d=["error","warning","success"];b.getContainer=function(b,c){var d;return d=a(b.ui.container),d&&1===d.length||(d=c.parent()),d},b.findElement=function(a,b,c){return b?a.find(b).find(c):a.find(c)},b.getUIElements=function(a,c){var d,e;return a.instances.viewports?a.instances.viewports:(d=b.getContainer(a,c),e={},e.$progressbar=b.findElement(d,a.ui.viewports.progress,"div.progress"),a.ui.showVerdictsInsideProgressBar&&(e.$verdict=e.$progressbar.find("span.password-verdict")),a.ui.showPopover||(a.ui.showVerdictsInsideProgressBar||(e.$verdict=b.findElement(d,a.ui.viewports.verdict,"span.password-verdict")),e.$errors=b.findElement(d,a.ui.viewports.errors,"ul.error-list")),a.instances.viewports=e,e)},b.initProgressBar=function(c,d){var e=b.getContainer(c,d),f="
    ",c.ui.showVerdictsInsideProgressBar&&(f+=""),f+="
    ",c.ui.viewports.progress?e.find(c.ui.viewports.progress).append(f):a(f).insertAfter(d)},b.initHelper=function(c,d,e,f){var g=b.getContainer(c,d);f?g.find(f).append(e):a(e).insertAfter(d)},b.initVerdict=function(a,c){b.initHelper(a,c,"",a.ui.viewports.verdict)},b.initErrorList=function(a,c){b.initHelper(a,c,"
      ",a.ui.viewports.errors)},b.initPopover=function(a,b){b.popover("destroy"),b.popover({html:!0,placement:"bottom",trigger:"manual",content:" "})},b.initUI=function(a,c){a.ui.showPopover?b.initPopover(a,c):(a.ui.showErrors&&b.initErrorList(a,c),a.ui.showVerdicts&&!a.ui.showVerdictsInsideProgressBar&&b.initVerdict(a,c)),a.ui.showProgressBar&&b.initProgressBar(a,c)},b.possibleProgressBarClasses=["danger","warning","success"],b.updateProgressBar=function(d,e,f,g){var h=b.getUIElements(d,e).$progressbar,i=h.find(".progress-bar"),j="progress-";d.ui.bootstrap2&&(i=h.find(".bar"),j=""),a.each(b.possibleProgressBarClasses,function(a,b){i.removeClass(j+"bar-"+b)}),i.addClass(j+"bar-"+c[f]),i.css("width",g+"%")},b.updateVerdict=function(a,d,e,f){var g=b.getUIElements(a,d).$verdict;g.removeClass(c.join(" ")),e>-1&&g.addClass(c[e]),g.html(f)},b.updateErrors=function(c,d){var e=b.getUIElements(c,d).$errors,f="";a.each(c.instances.errors,function(a,b){f+="
    • "+b+"
    • "}),e.html(f)},b.updatePopover=function(a,b,c){var d=b.data("bs.popover"),e="",f=!0;return a.ui.showVerdicts&&!a.ui.showVerdictsInsideProgressBar&&c.length>0&&(e="
      "+c+"
      ",f=!1),a.ui.showErrors&&(a.instances.errors.length>0&&(f=!1),e+=a.ui.popoverError(a.instances.errors)),f?void b.popover("hide"):(a.ui.bootstrap2&&(d=b.data("popover")),void(d.$arrow&&d.$arrow.parents("body").length>0?b.find("+ .popover .popover-content").html(e):(d.options.content=e,b.popover("show"))))},b.updateFieldStatus=function(b,c,e){var f=b.ui.bootstrap2?".control-group":".form-group",g=c.parents(f).first();a.each(d,function(a,c){b.ui.bootstrap2||(c="has-"+c),g.removeClass(c)}),e=d[e],b.ui.bootstrap2||(e="has-"+e),g.addClass(e)},b.percentage=function(a,b){var c=Math.floor(100*a/b);return c=0>c?1:c,c=c>100?100:c},b.getVerdictAndCssClass=function(a,b){var c,d,e;return 0>=b?(c=0,e=-1,d=a.ui.verdicts[0]):b params = new HashMap(); - params.put("oldpassword", "test"); - params.put("password", "newtest"); - - final Response response = request.with().params(params).post(URL); - - assertEquals(200, response.statusCode()); - assertTrue(response.body().asString().contains("Password updated successfully")); - } - - @Test - public void givenWrongOldPassword_whenChangingPassword_thenBadRequest() { - final RequestSpecification request = RestAssured.given().auth().form("test@test.com", "test", formConfig); - - final Map params = new HashMap(); - params.put("oldpassword", "abc"); - params.put("password", "newtest"); - - final Response response = request.with().params(params).post(URL); - - assertEquals(400, response.statusCode()); - assertTrue(response.body().asString().contains("Invalid Old Password")); - } - - @Test - public void givenNotAuthenticatedUser_whenChangingPassword_thenRedirect() { - final Map params = new HashMap(); - params.put("oldpassword", "abc"); - params.put("password", "xyz"); - - final Response response = RestAssured.with().params(params).post(URL); - - assertEquals(302, response.statusCode()); - assertFalse(response.body().asString().contains("Password updated successfully")); - } - -} diff --git a/spring-security-login-and-registration/src/test/java/org/baeldung/test/SpringSecurityRolesIntegrationTest.java b/spring-security-login-and-registration/src/test/java/org/baeldung/test/SpringSecurityRolesIntegrationTest.java deleted file mode 100644 index 978497fabd..0000000000 --- a/spring-security-login-and-registration/src/test/java/org/baeldung/test/SpringSecurityRolesIntegrationTest.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.baeldung.test; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import java.util.ArrayList; -import java.util.Arrays; - -import org.baeldung.persistence.dao.PrivilegeRepository; -import org.baeldung.persistence.dao.RoleRepository; -import org.baeldung.persistence.dao.UserRepository; -import org.baeldung.persistence.model.Privilege; -import org.baeldung.persistence.model.Role; -import org.baeldung.persistence.model.User; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.AnnotationConfigContextLoader; -import org.springframework.test.context.transaction.TransactionConfiguration; -import org.springframework.transaction.annotation.Transactional; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) -@Transactional -@TransactionConfiguration -public class SpringSecurityRolesIntegrationTest { - - @Autowired - private UserRepository userRepository; - - @Autowired - private RoleRepository roleRepository; - - @Autowired - private PrivilegeRepository privilegeRepository; - - @Autowired - private PasswordEncoder passwordEncoder; - - private User user; - private Role role; - private Privilege privilege; - - // tests - - @Test - public void testDeleteUser() { - role = new Role("TEST_ROLE"); - roleRepository.save(role); - - user = new User(); - user.setFirstName("John"); - user.setLastName("Doe"); - user.setPassword(passwordEncoder.encode("123")); - user.setEmail("john@doe.com"); - user.setRoles(Arrays.asList(role)); - user.setEnabled(true); - userRepository.save(user); - - assertNotNull(userRepository.findByEmail(user.getEmail())); - assertNotNull(roleRepository.findByName(role.getName())); - user.setRoles(null); - userRepository.delete(user); - - assertNull(userRepository.findByEmail(user.getEmail())); - assertNotNull(roleRepository.findByName(role.getName())); - } - - @Test - public void testDeleteRole() { - privilege = new Privilege("TEST_PRIVILEGE"); - privilegeRepository.save(privilege); - - role = new Role("TEST_ROLE"); - role.setPrivileges(Arrays.asList(privilege)); - roleRepository.save(role); - - user = new User(); - user.setFirstName("John"); - user.setLastName("Doe"); - user.setPassword(passwordEncoder.encode("123")); - user.setEmail("john@doe.com"); - user.setRoles(Arrays.asList(role)); - user.setEnabled(true); - userRepository.save(user); - - assertNotNull(privilegeRepository.findByName(privilege.getName())); - assertNotNull(userRepository.findByEmail(user.getEmail())); - assertNotNull(roleRepository.findByName(role.getName())); - - user.setRoles(new ArrayList()); - role.setPrivileges(new ArrayList()); - roleRepository.delete(role); - - assertNull(roleRepository.findByName(role.getName())); - assertNotNull(privilegeRepository.findByName(privilege.getName())); - assertNotNull(userRepository.findByEmail(user.getEmail())); - } - - @Test - public void testDeletePrivilege() { - privilege = new Privilege("TEST_PRIVILEGE"); - privilegeRepository.save(privilege); - - role = new Role("TEST_ROLE"); - role.setPrivileges(Arrays.asList(privilege)); - roleRepository.save(role); - - assertNotNull(roleRepository.findByName(role.getName())); - assertNotNull(privilegeRepository.findByName(privilege.getName())); - - role.setPrivileges(new ArrayList()); - privilegeRepository.delete(privilege); - - assertNull(privilegeRepository.findByName(privilege.getName())); - assertNotNull(roleRepository.findByName(role.getName())); - } -} diff --git a/spring-security-mvc-custom/.classpath b/spring-security-mvc-custom/.classpath deleted file mode 100644 index bbfdf4ade5..0000000000 --- a/spring-security-mvc-custom/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-mvc-custom/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-security-mvc-custom/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-security-mvc-custom/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-mvc-custom/.project b/spring-security-mvc-custom/.project deleted file mode 100644 index 81c640f9e3..0000000000 --- a/spring-security-mvc-custom/.project +++ /dev/null @@ -1,42 +0,0 @@ - - - spring-security-mvc-custom - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/spring-security-mvc-custom/.settings/.jsdtscope b/spring-security-mvc-custom/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/spring-security-mvc-custom/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-mvc-custom/.settings/org.eclipse.jdt.core.prefs b/spring-security-mvc-custom/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/spring-security-mvc-custom/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-security-mvc-custom/.settings/org.eclipse.jdt.ui.prefs b/spring-security-mvc-custom/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-security-mvc-custom/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-security-mvc-custom/.settings/org.eclipse.m2e.core.prefs b/spring-security-mvc-custom/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-security-mvc-custom/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-security-mvc-custom/.settings/org.eclipse.m2e.wtp.prefs b/spring-security-mvc-custom/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-security-mvc-custom/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-security-mvc-custom/.settings/org.eclipse.wst.common.component b/spring-security-mvc-custom/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 0a268a3d82..0000000000 --- a/spring-security-mvc-custom/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-security-mvc-custom/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-security-mvc-custom/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f5888c1411..0000000000 --- a/spring-security-mvc-custom/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-mvc-custom/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-security-mvc-custom/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-security-mvc-custom/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-security-mvc-custom/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-security-mvc-custom/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-security-mvc-custom/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-security-mvc-custom/.settings/org.eclipse.wst.validation.prefs b/spring-security-mvc-custom/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-security-mvc-custom/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-security-mvc-custom/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-security-mvc-custom/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-security-mvc-custom/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-security-mvc-custom/.springBeans b/spring-security-mvc-custom/.springBeans deleted file mode 100644 index 7623a7e888..0000000000 --- a/spring-security-mvc-custom/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/spring-security-mvc-custom/README.md b/spring-security-mvc-custom/README.md index 17f32e4a2f..14bac6c454 100644 --- a/spring-security-mvc-custom/README.md +++ b/spring-security-mvc-custom/README.md @@ -2,6 +2,8 @@ ## Spring Security Login Example Project +###The Course +The "REST With Spring" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [Spring Security Remember Me](http://www.baeldung.com/spring-security-remember-me) diff --git a/spring-security-mvc-custom/pom.xml b/spring-security-mvc-custom/pom.xml index b5f71847f5..ca9b3423cc 100644 --- a/spring-security-mvc-custom/pom.xml +++ b/spring-security-mvc-custom/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-mvc-custom 0.1-SNAPSHOT @@ -230,12 +230,12 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 1.7.13 @@ -258,14 +258,14 @@ 4.5 4.4.1 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-security-mvc-digest-auth/.classpath b/spring-security-mvc-digest-auth/.classpath deleted file mode 100644 index bbfdf4ade5..0000000000 --- a/spring-security-mvc-digest-auth/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-mvc-digest-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-security-mvc-digest-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-security-mvc-digest-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-mvc-digest-auth/.project b/spring-security-mvc-digest-auth/.project deleted file mode 100644 index f387b771fc..0000000000 --- a/spring-security-mvc-digest-auth/.project +++ /dev/null @@ -1,42 +0,0 @@ - - - spring-security-mvc-digest-auth - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/spring-security-mvc-digest-auth/.settings/.jsdtscope b/spring-security-mvc-digest-auth/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/spring-security-mvc-digest-auth/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-mvc-digest-auth/.settings/org.eclipse.jdt.core.prefs b/spring-security-mvc-digest-auth/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index f78b9bf1c1..0000000000 --- a/spring-security-mvc-digest-auth/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,91 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-security-mvc-digest-auth/.settings/org.eclipse.jdt.ui.prefs b/spring-security-mvc-digest-auth/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-security-mvc-digest-auth/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-security-mvc-digest-auth/.settings/org.eclipse.m2e.core.prefs b/spring-security-mvc-digest-auth/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-security-mvc-digest-auth/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-security-mvc-digest-auth/.settings/org.eclipse.m2e.wtp.prefs b/spring-security-mvc-digest-auth/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-security-mvc-digest-auth/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.common.component b/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 0d189e36cd..0000000000 --- a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f5888c1411..0000000000 --- a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.validation.prefs b/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-security-mvc-digest-auth/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-security-mvc-digest-auth/.springBeans b/spring-security-mvc-digest-auth/.springBeans deleted file mode 100644 index 7623a7e888..0000000000 --- a/spring-security-mvc-digest-auth/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/spring-security-mvc-digest-auth/README.md b/spring-security-mvc-digest-auth/README.md index 3b93a84505..8b79b6b113 100644 --- a/spring-security-mvc-digest-auth/README.md +++ b/spring-security-mvc-digest-auth/README.md @@ -2,6 +2,8 @@ ## Spring Security with Digest Authentication Example Project +###The Course +The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Article: - [Spring Security Digest Authentication](http://www.baeldung.com/spring-security-digest-authentication) diff --git a/spring-security-mvc-digest-auth/pom.xml b/spring-security-mvc-digest-auth/pom.xml index dc2c4d80a5..c292eb6b54 100644 --- a/spring-security-mvc-digest-auth/pom.xml +++ b/spring-security-mvc-digest-auth/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-mvc-digest-auth 0.1-SNAPSHOT @@ -225,12 +225,12 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 1.7.13 @@ -253,14 +253,14 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-security-mvc-ldap/.classpath b/spring-security-mvc-ldap/.classpath deleted file mode 100644 index 6acf3eeeca..0000000000 --- a/spring-security-mvc-ldap/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-mvc-ldap/.project b/spring-security-mvc-ldap/.project deleted file mode 100644 index 17814c8c03..0000000000 --- a/spring-security-mvc-ldap/.project +++ /dev/null @@ -1,54 +0,0 @@ - - - spring-security-mvc-ldap - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.hibernate.eclipse.console.hibernateBuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - org.hibernate.eclipse.console.hibernateNature - - diff --git a/spring-security-mvc-ldap/README.md b/spring-security-mvc-ldap/README.md index 260b4b38d8..fe6a667c40 100644 --- a/spring-security-mvc-ldap/README.md +++ b/spring-security-mvc-ldap/README.md @@ -1,11 +1,13 @@ ## Spring Security with LDAP Example Project +###The Course +The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Article: - [Spring Security - security none, filters none, access permitAll](http://www.baeldung.com/security-none-filters-none-access-permitAll) - [Spring Security Basic Authentication](http://www.baeldung.com/spring-security-basic-authentication) - +- [Intro to Spring Security LDAP](http://www.baeldung.com/spring-security-ldap) ### Notes - the project uses Spring Boot - simply run 'SampleLDAPApplication.java' to start up Spring Boot with a Tomcat container and embedded LDAP server. diff --git a/spring-security-mvc-ldap/pom.xml b/spring-security-mvc-ldap/pom.xml index 317c8dfb73..b001a86955 100644 --- a/spring-security-mvc-ldap/pom.xml +++ b/spring-security-mvc-ldap/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-mvc-ldap 0.1-SNAPSHOT @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.3.2.RELEASE + 1.3.3.RELEASE diff --git a/spring-security-mvc-login/.classpath b/spring-security-mvc-login/.classpath deleted file mode 100644 index bbfdf4ade5..0000000000 --- a/spring-security-mvc-login/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-mvc-login/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-security-mvc-login/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-security-mvc-login/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-mvc-login/.project b/spring-security-mvc-login/.project deleted file mode 100644 index d52a48244a..0000000000 --- a/spring-security-mvc-login/.project +++ /dev/null @@ -1,42 +0,0 @@ - - - spring-security-mvc-login - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/spring-security-mvc-login/.settings/.jsdtscope b/spring-security-mvc-login/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/spring-security-mvc-login/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-mvc-login/.settings/org.eclipse.jdt.core.prefs b/spring-security-mvc-login/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/spring-security-mvc-login/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-security-mvc-login/.settings/org.eclipse.jdt.ui.prefs b/spring-security-mvc-login/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-security-mvc-login/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-security-mvc-login/.settings/org.eclipse.m2e.core.prefs b/spring-security-mvc-login/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-security-mvc-login/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-security-mvc-login/.settings/org.eclipse.m2e.wtp.prefs b/spring-security-mvc-login/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-security-mvc-login/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-security-mvc-login/.settings/org.eclipse.wst.common.component b/spring-security-mvc-login/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 8b704170f8..0000000000 --- a/spring-security-mvc-login/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-security-mvc-login/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-security-mvc-login/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f5888c1411..0000000000 --- a/spring-security-mvc-login/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-mvc-login/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-security-mvc-login/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-security-mvc-login/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-security-mvc-login/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-security-mvc-login/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-security-mvc-login/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-security-mvc-login/.settings/org.eclipse.wst.validation.prefs b/spring-security-mvc-login/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-security-mvc-login/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-security-mvc-login/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-security-mvc-login/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-security-mvc-login/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-security-mvc-login/.springBeans b/spring-security-mvc-login/.springBeans deleted file mode 100644 index 7623a7e888..0000000000 --- a/spring-security-mvc-login/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/spring-security-mvc-login/README.md b/spring-security-mvc-login/README.md index 256078f4b6..7cddc42e1d 100644 --- a/spring-security-mvc-login/README.md +++ b/spring-security-mvc-login/README.md @@ -2,11 +2,13 @@ ## Spring Security Login Example Project +###The Course +The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [Spring Security Form Login](http://www.baeldung.com/spring-security-login) - [Spring Security Logout](http://www.baeldung.com/spring-security-logout) -- [Spring Security Expressions – hasRole Example](http://www.baeldung.com/spring-security-expressions-basic) +- [Spring Security Expressions – hasRole Example](http://www.baeldung.com/spring-security-expressions-basic) ### Build the Project diff --git a/spring-security-mvc-login/pom.xml b/spring-security-mvc-login/pom.xml index ee6b37743b..943eeaa197 100644 --- a/spring-security-mvc-login/pom.xml +++ b/spring-security-mvc-login/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-mvc-login 0.1-SNAPSHOT @@ -222,12 +222,12 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 1.7.13 @@ -250,14 +250,14 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/spring/ChannelSecSecurityConfig.java b/spring-security-mvc-login/src/main/java/org/baeldung/spring/ChannelSecSecurityConfig.java new file mode 100644 index 0000000000..4f736360b9 --- /dev/null +++ b/spring-security-mvc-login/src/main/java/org/baeldung/spring/ChannelSecSecurityConfig.java @@ -0,0 +1,69 @@ +package org.baeldung.spring; + +import org.baeldung.security.CustomLogoutSuccessHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; + +@Configuration +// @ImportResource({ "classpath:channelWebSecurityConfig.xml" }) +@EnableWebSecurity +@Profile("https") +public class ChannelSecSecurityConfig extends WebSecurityConfigurerAdapter { + + public ChannelSecSecurityConfig() { + super(); + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.inMemoryAuthentication() + .withUser("user1").password("user1Pass").roles("USER") + .and() + .withUser("user2").password("user2Pass").roles("USER"); + // @formatter:on + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http + .csrf().disable() + .authorizeRequests() + .antMatchers("/anonymous*").anonymous() + .antMatchers("/login*").permitAll() + .anyRequest().authenticated() + .and() + .requiresChannel() + .antMatchers("/login*", "/perform_login").requiresSecure() + .anyRequest().requiresInsecure() + .and() + .sessionManagement() + .sessionFixation() + .none() + .and() + .formLogin() + .loginPage("/login.html") + .loginProcessingUrl("/perform_login") + .defaultSuccessUrl("/homepage.html",true) + .failureUrl("/login.html?error=true") + .and() + .logout() + .logoutUrl("/perform_logout") + .deleteCookies("JSESSIONID") + .logoutSuccessHandler(logoutSuccessHandler()); + // @formatter:on + } + + @Bean + public LogoutSuccessHandler logoutSuccessHandler() { + return new CustomLogoutSuccessHandler(); + } + +} diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java b/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java index 4da114c78b..654c934fac 100644 --- a/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java +++ b/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java @@ -1,14 +1,61 @@ package org.baeldung.spring; +import org.baeldung.security.CustomLogoutSuccessHandler; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; +import org.springframework.context.annotation.Profile; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; @Configuration -@ImportResource({ "classpath:webSecurityConfig.xml" }) -public class SecSecurityConfig { +// @ImportResource({ "classpath:webSecurityConfig.xml" }) +@EnableWebSecurity +@Profile("!https") +public class SecSecurityConfig extends WebSecurityConfigurerAdapter { public SecSecurityConfig() { super(); } + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.inMemoryAuthentication() + .withUser("user1").password("user1Pass").roles("USER") + .and() + .withUser("user2").password("user2Pass").roles("USER"); + // @formatter:on + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http + .csrf().disable() + .authorizeRequests() + .antMatchers("/anonymous*").anonymous() + .antMatchers("/login*").permitAll() + .anyRequest().authenticated() + .and() + .formLogin() + .loginPage("/login.html") + .loginProcessingUrl("/perform_login") + .defaultSuccessUrl("/homepage.html",true) + .failureUrl("/login.html?error=true") + .and() + .logout() + .logoutUrl("/perform_logout") + .deleteCookies("JSESSIONID") + .logoutSuccessHandler(logoutSuccessHandler()); + // @formatter:on + } + + @Bean + public LogoutSuccessHandler logoutSuccessHandler() { + return new CustomLogoutSuccessHandler(); + } + } diff --git a/spring-security-mvc-login/src/main/resources/channelWebSecurityConfig.xml b/spring-security-mvc-login/src/main/resources/channelWebSecurityConfig.xml new file mode 100644 index 0000000000..de073b8aac --- /dev/null +++ b/spring-security-mvc-login/src/main/resources/channelWebSecurityConfig.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml b/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml index ec4cf60eb5..7a736d0024 100644 --- a/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml +++ b/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml @@ -13,12 +13,11 @@ - + - diff --git a/spring-security-mvc-login/src/main/webapp/WEB-INF/web.xml b/spring-security-mvc-login/src/main/webapp/WEB-INF/web.xml index f13ae48c7e..0a0a340995 100644 --- a/spring-security-mvc-login/src/main/webapp/WEB-INF/web.xml +++ b/spring-security-mvc-login/src/main/webapp/WEB-INF/web.xml @@ -1,9 +1,8 @@ - + Spring MVC Application diff --git a/spring-security-mvc-persisted-remember-me/README.md b/spring-security-mvc-persisted-remember-me/README.md index 11f5417028..f910c3f62b 100644 --- a/spring-security-mvc-persisted-remember-me/README.md +++ b/spring-security-mvc-persisted-remember-me/README.md @@ -2,9 +2,11 @@ ## Spring Security Persisted Remember Me Example Project +###The Course +The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: -- [Spring Security Persisted Remember Me] +- [Spring Security Persisted Remember Me](http://www.baeldung.com/spring-security-persistent-remember-me) - [Spring Security Remember Me](http://www.baeldung.com/spring-security-remember-me) - [Redirect to different pages after Login with Spring Security](http://www.baeldung.com/spring_redirect_after_login) diff --git a/spring-security-mvc-persisted-remember-me/pom.xml b/spring-security-mvc-persisted-remember-me/pom.xml index 1691f10f43..3f1d78f8ea 100644 --- a/spring-security-mvc-persisted-remember-me/pom.xml +++ b/spring-security-mvc-persisted-remember-me/pom.xml @@ -1,7 +1,7 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-mvc-persisted-remember-me 0.1-SNAPSHOT @@ -260,12 +260,12 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 1.4.190 9.1-901.jdbc4 @@ -291,14 +291,14 @@ 4.5 4.4.1 - 2.4.1 + 2.9.0 - 3.3 - 2.5 - 2.18.1 + 3.5.1 + 2.6 + 2.19.1 2.7 - 1.4.11 + 1.4.18 diff --git a/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/service/MyUserDetailsService.java b/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/service/MyUserDetailsService.java index ac2aa6beb6..c662c32738 100644 --- a/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/service/MyUserDetailsService.java +++ b/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/service/MyUserDetailsService.java @@ -1,11 +1,5 @@ package org.baeldung.service; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.baeldung.security.SecurityRole; @@ -17,34 +11,30 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; -/** - * User Details Service - hard coded to two users for the example. - */ +import java.util.*; +import java.util.stream.Collectors; + @Service public class MyUserDetailsService implements UserDetailsService { private final Log logger = LogFactory.getLog(this.getClass()); - private Map availableUsers = new HashMap(); + private final Map availableUsers = new HashMap(); public MyUserDetailsService() { - populateDemoUsers(); - } @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - + public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { logger.info("Load user by username " + username); - UserDetails user = availableUsers.get(username); + final UserDetails user = availableUsers.get(username); if (user == null) { - throw new UsernameNotFoundException("Username not found"); - } else { - return availableUsers.get(username); + throw new UsernameNotFoundException(username); } + return user; } /** @@ -52,32 +42,19 @@ public class MyUserDetailsService implements UserDetailsService { * in database or retrieved from another system). */ private void populateDemoUsers() { - logger.info("Populate demo users"); availableUsers.put("user", createUser("user", "password", Arrays.asList(SecurityRole.ROLE_USER))); availableUsers.put("admin", createUser("admin", "password", Arrays.asList(SecurityRole.ROLE_ADMIN))); } - /** - * Create a demo User. - * - * @param username - * Username - * @param password - * Password - * @param roles - * Role names user is assigned to - * @return User - */ - private User createUser(String username, String password, List roles) { - + private User createUser(final String username, final String password, final List roles) { logger.info("Create user " + username); - List authorities = new ArrayList(); - for (SecurityRole role : roles) { - authorities.add(new SimpleGrantedAuthority(role.toString())); - } + final List authorities = roles.stream() + .map(role -> new SimpleGrantedAuthority(role.toString())) + .collect(Collectors.toList()); + return new User(username, password, true, true, true, true, authorities); } } diff --git a/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/spring/DatabaseConfig.java b/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/spring/DatabaseConfig.java deleted file mode 100644 index 7f0428df77..0000000000 --- a/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/spring/DatabaseConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.baeldung.spring; - -import javax.sql.DataSource; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -import org.springframework.core.env.Environment; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -import com.google.common.base.Preconditions; - -/** - * Spring Database Configuration. - */ -@Configuration -@EnableTransactionManagement -@PropertySource({ "classpath:persistence-h2.properties" }) -public class DatabaseConfig { - - @Autowired - private Environment env; - - @Bean - public DataSource dataSource() { - final DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); - dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); - dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); - dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); - return dataSource; - } -} diff --git a/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/spring/PersistenceConfig.java b/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/spring/PersistenceConfig.java new file mode 100644 index 0000000000..02308e64fb --- /dev/null +++ b/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/spring/PersistenceConfig.java @@ -0,0 +1,38 @@ +package org.baeldung.spring; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +/** + * Spring Database Configuration. + */ +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-h2.properties" }) +public class PersistenceConfig { + + @Autowired + private Environment env; + + // + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + return dataSource; + } + +} diff --git a/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/spring/SecurityConfig.java b/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/spring/SecurityConfig.java index b3549511fc..2d9bb8e731 100644 --- a/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/spring/SecurityConfig.java +++ b/spring-security-mvc-persisted-remember-me/src/main/java/org/baeldung/spring/SecurityConfig.java @@ -1,11 +1,9 @@ package org.baeldung.spring; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; /** * Spring Security Configuration. @@ -15,9 +13,6 @@ import org.springframework.security.web.authentication.AuthenticationSuccessHand @ImportResource({ "classpath:webSecurityConfig.xml" }) public class SecurityConfig extends WebSecurityConfigurerAdapter { - @Autowired - private AuthenticationSuccessHandler mySimpleUrlAuthenticationSuccessHandler; - public SecurityConfig() { super(); } diff --git a/spring-security-mvc-persisted-remember-me/src/main/resources/webSecurityConfig.xml b/spring-security-mvc-persisted-remember-me/src/main/resources/webSecurityConfig.xml index a11f13c9ab..d1f081cb9b 100644 --- a/spring-security-mvc-persisted-remember-me/src/main/resources/webSecurityConfig.xml +++ b/spring-security-mvc-persisted-remember-me/src/main/resources/webSecurityConfig.xml @@ -1,55 +1,51 @@ - + http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.2.xsd" +> - - - + + + - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-security-mvc-session/.classpath b/spring-security-mvc-session/.classpath deleted file mode 100644 index bbfdf4ade5..0000000000 --- a/spring-security-mvc-session/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-mvc-session/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-security-mvc-session/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-security-mvc-session/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-mvc-session/.project b/spring-security-mvc-session/.project deleted file mode 100644 index 4670a72a3b..0000000000 --- a/spring-security-mvc-session/.project +++ /dev/null @@ -1,42 +0,0 @@ - - - spring-security-mvc-session - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/spring-security-mvc-session/.settings/.jsdtscope b/spring-security-mvc-session/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/spring-security-mvc-session/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-mvc-session/.settings/org.eclipse.jdt.core.prefs b/spring-security-mvc-session/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index b126d6476b..0000000000 --- a/spring-security-mvc-session/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-security-mvc-session/.settings/org.eclipse.jdt.ui.prefs b/spring-security-mvc-session/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-security-mvc-session/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-security-mvc-session/.settings/org.eclipse.m2e.core.prefs b/spring-security-mvc-session/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-security-mvc-session/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-security-mvc-session/.settings/org.eclipse.m2e.wtp.prefs b/spring-security-mvc-session/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-security-mvc-session/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-security-mvc-session/.settings/org.eclipse.wst.common.component b/spring-security-mvc-session/.settings/org.eclipse.wst.common.component deleted file mode 100644 index db01b7dfe4..0000000000 --- a/spring-security-mvc-session/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-security-mvc-session/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-security-mvc-session/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f5888c1411..0000000000 --- a/spring-security-mvc-session/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-mvc-session/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-security-mvc-session/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-security-mvc-session/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-security-mvc-session/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-security-mvc-session/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-security-mvc-session/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-security-mvc-session/.settings/org.eclipse.wst.validation.prefs b/spring-security-mvc-session/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-security-mvc-session/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-security-mvc-session/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-security-mvc-session/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-security-mvc-session/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-security-mvc-session/.springBeans b/spring-security-mvc-session/.springBeans deleted file mode 100644 index 7623a7e888..0000000000 --- a/spring-security-mvc-session/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/mvc-servlet.xml - - - - diff --git a/spring-security-mvc-session/README.md b/spring-security-mvc-session/README.md index 0df728688a..fc44209640 100644 --- a/spring-security-mvc-session/README.md +++ b/spring-security-mvc-session/README.md @@ -2,9 +2,11 @@ ## Spring Security Login Example Project +###The Course +The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: -- [HttpSessionListener Example – Monitoring](http://www.baeldung.com/httpsessionlistener_with_metrics) +- [HttpSessionListener Example – Monitoring](http://www.baeldung.com/httpsessionlistener_with_metrics) - [Spring Security Session Management](http://www.baeldung.com/spring-security-session) diff --git a/spring-security-mvc-session/pom.xml b/spring-security-mvc-session/pom.xml index fd90be6cc8..e330825bf2 100644 --- a/spring-security-mvc-session/pom.xml +++ b/spring-security-mvc-session/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-mvc-session 0.1-SNAPSHOT @@ -230,12 +230,12 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 1.7.13 @@ -259,14 +259,14 @@ 4.5 4.4.1 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 + 2.19.1 2.7 - 1.4.15 + 1.4.18 diff --git a/spring-security-mvc-session/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java b/spring-security-mvc-session/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java index 19f1ca76a6..19f49ea59d 100644 --- a/spring-security-mvc-session/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java +++ b/spring-security-mvc-session/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java @@ -21,7 +21,7 @@ public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSu private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); - protected MySimpleUrlAuthenticationSuccessHandler() { + public MySimpleUrlAuthenticationSuccessHandler() { super(); } diff --git a/spring-security-mvc-session/src/main/java/org/baeldung/spring/SecSecurityConfig.java b/spring-security-mvc-session/src/main/java/org/baeldung/spring/SecSecurityConfig.java index 4da114c78b..deeea78e4e 100644 --- a/spring-security-mvc-session/src/main/java/org/baeldung/spring/SecSecurityConfig.java +++ b/spring-security-mvc-session/src/main/java/org/baeldung/spring/SecSecurityConfig.java @@ -1,14 +1,72 @@ package org.baeldung.spring; +import org.baeldung.security.MySimpleUrlAuthenticationSuccessHandler; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.security.web.session.HttpSessionEventPublisher; @Configuration -@ImportResource({ "classpath:webSecurityConfig.xml" }) -public class SecSecurityConfig { +// @ImportResource({ "classpath:webSecurityConfig.xml" }) +@EnableWebSecurity +public class SecSecurityConfig extends WebSecurityConfigurerAdapter { public SecSecurityConfig() { super(); } + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.inMemoryAuthentication() + .withUser("user1").password("user1Pass").roles("USER") + .and() + .withUser("admin1").password("admin1Pass").roles("ADMIN"); + // @formatter:on + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http + .csrf().disable() + .authorizeRequests() + .antMatchers("/anonymous*").anonymous() + .antMatchers("/login*").permitAll() + .anyRequest().authenticated() + .and() + .formLogin() + .loginPage("/login.html") + .loginProcessingUrl("/login") + .successHandler(successHandler()) + .failureUrl("/login.html?error=true") + .and() + .logout().deleteCookies("JSESSIONID") + .and() + .rememberMe().key("uniqueAndSecret").tokenValiditySeconds(86400) + .and() + .sessionManagement() + .sessionFixation().migrateSession() + .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) + .invalidSessionUrl("/invalidSession.html") + .maximumSessions(2) + .expiredUrl("/sessionExpired.html"); + + // @formatter:on + } + + private AuthenticationSuccessHandler successHandler() { + return new MySimpleUrlAuthenticationSuccessHandler(); + } + + @Bean + public HttpSessionEventPublisher httpSessionEventPublisher() { + return new HttpSessionEventPublisher(); + } + } diff --git a/spring-security-mvc-session/src/main/webapp/WEB-INF/web.xml b/spring-security-mvc-session/src/main/webapp/WEB-INF/web.xml index 45b49b2a91..57826fadac 100644 --- a/spring-security-mvc-session/src/main/webapp/WEB-INF/web.xml +++ b/spring-security-mvc-session/src/main/webapp/WEB-INF/web.xml @@ -1,9 +1,8 @@ - + Spring MVC Session Application @@ -13,9 +12,9 @@ org.baeldung.web.SessionListenerWithMetrics - + diff --git a/spring-security-oauth/.project b/spring-security-oauth/.project deleted file mode 100644 index fe6e295165..0000000000 --- a/spring-security-oauth/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - spring-security-oauth - - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.m2e.core.maven2Nature - - diff --git a/spring-security-oauth/README.md b/spring-security-oauth/README.md deleted file mode 100644 index 6baa0a1824..0000000000 --- a/spring-security-oauth/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## Spring Security OAuth - -### Relevant Articles: -- [Spring REST API + OAuth2 + AngularJS](http://www.baeldung.com/rest-api-spring-oauth2-angularjs) - -### Build the Project -``` -mvn clean install -``` - -### Notes -- Make sure to run the project on port 8081 -- Run 4 sub-modules simultaneously - - spring-security-oauth-server - - spring-security-oauth-resource - - spring-security-oauth-ui-implicit - - spring-security-oauth-ui-password diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml deleted file mode 100644 index 7bb7aa86c8..0000000000 --- a/spring-security-oauth/pom.xml +++ /dev/null @@ -1,104 +0,0 @@ - - 4.0.0 - org.baeldung - spring-security-oauth - 1.0.0-SNAPSHOT - - spring-security-oauth - pom - - - org.springframework.boot - spring-boot-starter-parent - 1.3.1.RELEASE - - - - spring-security-oauth-server - spring-security-oauth-resource - spring-security-oauth-ui-implicit - spring-security-oauth-ui-password - - - - spring-security-oauth - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - - - - org.apache.maven.plugins - maven-war-plugin - ${maven-war-plugin.version} - - false - - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - true - - **/*IntegrationTest.java - **/*LiveTest.java - - - - - - - - - - - - - - - 4.2.2.RELEASE - 4.0.3.RELEASE - 2.0.7.RELEASE - - - - 2.5.1 - - - 1.7.12 - 1.1.3 - - - 18.0 - 3.3.2 - - - 1.3 - 4.11 - 1.10.19 - - 4.4 - 4.4 - - 2.4.0 - - - 3.3 - 2.6 - 2.19 - 1.4.16 - - - - \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-resource/.classpath b/spring-security-oauth/spring-security-oauth-resource/.classpath deleted file mode 100644 index 0cad5db2d0..0000000000 --- a/spring-security-oauth/spring-security-oauth-resource/.classpath +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-oauth/spring-security-oauth-resource/.project b/spring-security-oauth/spring-security-oauth-resource/.project deleted file mode 100644 index c3a285960b..0000000000 --- a/spring-security-oauth/spring-security-oauth-resource/.project +++ /dev/null @@ -1,48 +0,0 @@ - - - spring-security-oauth-resource - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-security-oauth/spring-security-oauth-resource/pom.xml b/spring-security-oauth/spring-security-oauth-resource/pom.xml deleted file mode 100644 index 84a5027cb5..0000000000 --- a/spring-security-oauth/spring-security-oauth-resource/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - 4.0.0 - spring-security-oauth-resource - spring-security-oauth-resource - war - - - org.baeldung - spring-security-oauth - 1.0.0-SNAPSHOT - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework - spring-jdbc - - - - mysql - mysql-connector-java - runtime - - - - org.springframework.security.oauth - spring-security-oauth2 - ${oauth.version} - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - - - - spring-security-oauth-resource - - - src/main/resources - true - - - - - \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/config/OAuth2ResourceServerConfig.java b/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/config/OAuth2ResourceServerConfig.java deleted file mode 100644 index c5e33739ae..0000000000 --- a/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/config/OAuth2ResourceServerConfig.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.baeldung.config; - -import javax.sql.DataSource; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -import org.springframework.core.env.Environment; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; -import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; - -@Configuration -@PropertySource({ "classpath:persistence.properties" }) -@EnableResourceServer -@EnableGlobalMethodSecurity(prePostEnabled = true) -public class OAuth2ResourceServerConfig extends GlobalMethodSecurityConfiguration { - - @Autowired - private Environment env; - - @Override - protected MethodSecurityExpressionHandler createExpressionHandler() { - return new OAuth2MethodSecurityExpressionHandler(); - } - - @Bean - public DataSource dataSource() { - final DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); - dataSource.setUrl(env.getProperty("jdbc.url")); - dataSource.setUsername(env.getProperty("jdbc.user")); - dataSource.setPassword(env.getProperty("jdbc.pass")); - return dataSource; - } - - @Bean - public TokenStore tokenStore() { - return new JdbcTokenStore(dataSource()); - } - -} diff --git a/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java b/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java deleted file mode 100644 index 1e35eff551..0000000000 --- a/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.baeldung.config; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.web.SpringBootServletInitializer; - -@SpringBootApplication -public class ResourceServerApplication extends SpringBootServletInitializer { - - public static void main(String[] args) { - SpringApplication.run(ResourceServerApplication.class, args); - } - -} \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java b/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java deleted file mode 100644 index c040c8ac42..0000000000 --- a/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.config; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; - -@Configuration -@EnableWebMvc -@ComponentScan({ "org.baeldung.web.controller" }) -public class ResourceServerWebConfig extends WebMvcConfigurerAdapter { - -} diff --git a/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/web/controller/FooController.java b/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/web/controller/FooController.java deleted file mode 100644 index 8dfa19bd84..0000000000 --- a/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/web/controller/FooController.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.baeldung.web.controller; - -import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; -import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; - -import org.baeldung.web.dto.Foo; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; - -@Controller -public class FooController { - - public FooController() { - super(); - } - - // API - read - @PreAuthorize("#oauth2.hasScope('read')") - @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}") - @ResponseBody - public Foo findById(@PathVariable final long id) { - return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4)); - } - -} diff --git a/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/web/dto/Foo.java b/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/web/dto/Foo.java deleted file mode 100644 index 9d26618e7f..0000000000 --- a/spring-security-oauth/spring-security-oauth-resource/src/main/java/org/baeldung/web/dto/Foo.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.baeldung.web.dto; - -public class Foo { - private long id; - private String name; - - public Foo() { - super(); - } - - public Foo(final long id, final String name) { - super(); - - this.id = id; - this.name = name; - } - - // - - public long getId() { - return id; - } - - public void setId(final long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(final String name) { - this.name = name; - } - -} \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-resource/src/main/resources/application.properties b/spring-security-oauth/spring-security-oauth-resource/src/main/resources/application.properties deleted file mode 100644 index 62a10d1751..0000000000 --- a/spring-security-oauth/spring-security-oauth-resource/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -server.contextPath=/spring-security-oauth-resource -server.port=8081 \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-resource/src/main/resources/persistence.properties b/spring-security-oauth/spring-security-oauth-resource/src/main/resources/persistence.properties deleted file mode 100644 index b975b10e9f..0000000000 --- a/spring-security-oauth/spring-security-oauth-resource/src/main/resources/persistence.properties +++ /dev/null @@ -1,6 +0,0 @@ -################### DataSource Configuration ########################## -jdbc.driverClassName=com.mysql.jdbc.Driver -jdbc.url=jdbc:mysql://localhost:3306/oauth2?createDatabaseIfNotExist=true -jdbc.user=tutorialuser -jdbc.pass=tutorialmy5ql - diff --git a/spring-security-oauth/spring-security-oauth-server/.classpath b/spring-security-oauth/spring-security-oauth-server/.classpath deleted file mode 100644 index 0cad5db2d0..0000000000 --- a/spring-security-oauth/spring-security-oauth-server/.classpath +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-oauth/spring-security-oauth-server/.project b/spring-security-oauth/spring-security-oauth-server/.project deleted file mode 100644 index a66e7f1009..0000000000 --- a/spring-security-oauth/spring-security-oauth-server/.project +++ /dev/null @@ -1,48 +0,0 @@ - - - spring-security-oauth-server - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-security-oauth/spring-security-oauth-server/pom.xml b/spring-security-oauth/spring-security-oauth-server/pom.xml deleted file mode 100644 index ebbaa993f1..0000000000 --- a/spring-security-oauth/spring-security-oauth-server/pom.xml +++ /dev/null @@ -1,64 +0,0 @@ - - 4.0.0 - spring-security-oauth-server - - spring-security-oauth-server - war - - - org.baeldung - spring-security-oauth - 1.0.0-SNAPSHOT - - - - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework - spring-jdbc - - - - mysql - mysql-connector-java - runtime - - - - - - - org.springframework.security.oauth - spring-security-oauth2 - ${oauth.version} - - - - - - - spring-security-oauth-server - - - src/main/resources - true - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - - \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-server/src/main/java/org/baeldung/config/OAuth2AuthorizationServerConfig.java b/spring-security-oauth/spring-security-oauth-server/src/main/java/org/baeldung/config/OAuth2AuthorizationServerConfig.java deleted file mode 100644 index c2f6ca41ae..0000000000 --- a/spring-security-oauth/spring-security-oauth-server/src/main/java/org/baeldung/config/OAuth2AuthorizationServerConfig.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.baeldung.config; - -import javax.sql.DataSource; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -import org.springframework.core.env.Environment; -import org.springframework.core.io.Resource; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.jdbc.datasource.init.DataSourceInitializer; -import org.springframework.jdbc.datasource.init.DatabasePopulator; -import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; -import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; - -@Configuration -@PropertySource({ "classpath:persistence.properties" }) -@EnableAuthorizationServer -public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { - - @Autowired - private Environment env; - - @Autowired - @Qualifier("authenticationManagerBean") - private AuthenticationManager authenticationManager; - - @Value("classpath:schema.sql") - private Resource schemaScript; - - @Override - public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { - oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()"); - } - - @Override - public void configure(ClientDetailsServiceConfigurer clients) throws Exception { - // @formatter:off - clients.jdbc(dataSource()) - .withClient("clientId") - .authorizedGrantTypes("implicit") - .scopes("read") - .autoApprove(true) - .and() - .withClient("clientIdPassword") - .secret("secret") - .authorizedGrantTypes("password","authorization_code", "refresh_token") - .scopes("read"); - - // @formatter:on - } - - @Override - public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { - endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager); - } - - @Bean - public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) { - final DataSourceInitializer initializer = new DataSourceInitializer(); - initializer.setDataSource(dataSource); - initializer.setDatabasePopulator(databasePopulator()); - return initializer; - } - - private DatabasePopulator databasePopulator() { - final ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); - populator.addScript(schemaScript); - return populator; - } - - @Bean - public DataSource dataSource() { - final DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); - dataSource.setUrl(env.getProperty("jdbc.url")); - dataSource.setUsername(env.getProperty("jdbc.user")); - dataSource.setPassword(env.getProperty("jdbc.pass")); - return dataSource; - } - - @Bean - public TokenStore tokenStore() { - return new JdbcTokenStore(dataSource()); - } -} diff --git a/spring-security-oauth/spring-security-oauth-server/src/main/java/org/baeldung/config/ServerApplication.java b/spring-security-oauth/spring-security-oauth-server/src/main/java/org/baeldung/config/ServerApplication.java deleted file mode 100644 index 4b1ff2c7ad..0000000000 --- a/spring-security-oauth/spring-security-oauth-server/src/main/java/org/baeldung/config/ServerApplication.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.baeldung.config; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.web.SpringBootServletInitializer; - -@SpringBootApplication -public class ServerApplication extends SpringBootServletInitializer { - - public static void main(String[] args) { - SpringApplication.run(ServerApplication.class, args); - } - -} \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-server/src/main/java/org/baeldung/config/ServerSecurityConfig.java b/spring-security-oauth/spring-security-oauth-server/src/main/java/org/baeldung/config/ServerSecurityConfig.java deleted file mode 100644 index 3e1a8a8ccb..0000000000 --- a/spring-security-oauth/spring-security-oauth-server/src/main/java/org/baeldung/config/ServerSecurityConfig.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.baeldung.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; - -@Configuration -public class ServerSecurityConfig extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(final AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication().withUser("john").password("123").roles("USER"); - - } - - @Override - @Bean - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); - } - - @Override - protected void configure(final HttpSecurity http) throws Exception { - // @formatter:off - http.authorizeRequests() - .antMatchers("/login").permitAll() - .anyRequest().authenticated() - .and().formLogin().permitAll() - ; - // @formatter:on - } - -} diff --git a/spring-security-oauth/spring-security-oauth-server/src/main/resources/application.properties b/spring-security-oauth/spring-security-oauth-server/src/main/resources/application.properties deleted file mode 100644 index e33e7dabf6..0000000000 --- a/spring-security-oauth/spring-security-oauth-server/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -server.contextPath=/spring-security-oauth-server -server.port=8081 \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-server/src/main/resources/persistence.properties b/spring-security-oauth/spring-security-oauth-server/src/main/resources/persistence.properties deleted file mode 100644 index b975b10e9f..0000000000 --- a/spring-security-oauth/spring-security-oauth-server/src/main/resources/persistence.properties +++ /dev/null @@ -1,6 +0,0 @@ -################### DataSource Configuration ########################## -jdbc.driverClassName=com.mysql.jdbc.Driver -jdbc.url=jdbc:mysql://localhost:3306/oauth2?createDatabaseIfNotExist=true -jdbc.user=tutorialuser -jdbc.pass=tutorialmy5ql - diff --git a/spring-security-oauth/spring-security-oauth-server/src/main/resources/schema.sql b/spring-security-oauth/spring-security-oauth-server/src/main/resources/schema.sql deleted file mode 100644 index 9c0b504a42..0000000000 --- a/spring-security-oauth/spring-security-oauth-server/src/main/resources/schema.sql +++ /dev/null @@ -1,71 +0,0 @@ -drop table if exists oauth_client_details; -create table oauth_client_details ( - client_id VARCHAR(255) PRIMARY KEY, - resource_ids VARCHAR(255), - client_secret VARCHAR(255), - scope VARCHAR(255), - authorized_grant_types VARCHAR(255), - web_server_redirect_uri VARCHAR(255), - authorities VARCHAR(255), - access_token_validity INTEGER, - refresh_token_validity INTEGER, - additional_information VARCHAR(4096), - autoapprove VARCHAR(255) -); - -drop table if exists oauth_client_token; -create table oauth_client_token ( - token_id VARCHAR(255), - token LONG VARBINARY, - authentication_id VARCHAR(255) PRIMARY KEY, - user_name VARCHAR(255), - client_id VARCHAR(255) -); - -drop table if exists oauth_access_token; -create table oauth_access_token ( - token_id VARCHAR(255), - token LONG VARBINARY, - authentication_id VARCHAR(255) PRIMARY KEY, - user_name VARCHAR(255), - client_id VARCHAR(255), - authentication LONG VARBINARY, - refresh_token VARCHAR(255) -); - -drop table if exists oauth_refresh_token; -create table oauth_refresh_token ( - token_id VARCHAR(255), - token LONG VARBINARY, - authentication LONG VARBINARY -); - -drop table if exists oauth_code; -create table oauth_code ( - code VARCHAR(255), authentication LONG VARBINARY -); - -drop table if exists oauth_approvals; -create table oauth_approvals ( - userId VARCHAR(255), - clientId VARCHAR(255), - scope VARCHAR(255), - status VARCHAR(10), - expiresAt TIMESTAMP, - lastModifiedAt TIMESTAMP -); - -drop table if exists ClientDetails; -create table ClientDetails ( - appId VARCHAR(255) PRIMARY KEY, - resourceIds VARCHAR(255), - appSecret VARCHAR(255), - scope VARCHAR(255), - grantTypes VARCHAR(255), - redirectUrl VARCHAR(255), - authorities VARCHAR(255), - access_token_validity INTEGER, - refresh_token_validity INTEGER, - additionalInformation VARCHAR(4096), - autoApproveScopes VARCHAR(255) -); diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/.classpath b/spring-security-oauth/spring-security-oauth-ui-implicit/.classpath deleted file mode 100644 index 0cad5db2d0..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/.classpath +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/.project b/spring-security-oauth/spring-security-oauth-ui-implicit/.project deleted file mode 100644 index c9fc2aa8f0..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/.project +++ /dev/null @@ -1,53 +0,0 @@ - - - spring-security-oauth-ui-implicit - - - - - - org.eclipse.ui.externaltools.ExternalToolBuilder - full,incremental, - - - LaunchConfigHandle - <project>/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator (1).launch - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/pom.xml b/spring-security-oauth/spring-security-oauth-ui-implicit/pom.xml deleted file mode 100644 index aaa2900d48..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - 4.0.0 - spring-security-oauth-ui-implicit - - spring-security-oauth-ui-implicit - war - - - org.baeldung - spring-security-oauth - 1.0.0-SNAPSHOT - - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - - - spring-security-oauth-ui-implicit - - - src/main/resources - true - - - - \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/java/org/baeldung/config/UiApplication.java b/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/java/org/baeldung/config/UiApplication.java deleted file mode 100644 index 8f491516aa..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/java/org/baeldung/config/UiApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.config; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.web.SpringBootServletInitializer; - -@SpringBootApplication -public class UiApplication extends SpringBootServletInitializer { - - public static void main(String[] args) { - SpringApplication.run(UiApplication.class, args); - } -} \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/java/org/baeldung/config/UiWebConfig.java b/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/java/org/baeldung/config/UiWebConfig.java deleted file mode 100644 index 71197ce5d2..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/java/org/baeldung/config/UiWebConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.baeldung.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; -import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; - -@Configuration -@EnableWebMvc -public class UiWebConfig extends WebMvcConfigurerAdapter { - - @Bean - public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { - return new PropertySourcesPlaceholderConfigurer(); - } - - @Override - public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { - configurer.enable(); - } - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); - registry.addViewController("/").setViewName("forward:/index"); - registry.addViewController("/oauthTemp"); - registry.addViewController("/index"); - } - - @Override - public void addResourceHandlers(final ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); - } - -} \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/application.properties b/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/application.properties deleted file mode 100644 index 33de0adb88..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -server.contextPath=/spring-security-oauth-ui-implicit -server.port=8081 \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/oauth-ng.js b/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/oauth-ng.js deleted file mode 100644 index 333070b935..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/oauth-ng.js +++ /dev/null @@ -1,539 +0,0 @@ -/* oauth-ng - v0.4.2 - 2015-08-27 */ - -'use strict'; - -// App libraries -angular.module('oauth', [ - 'oauth.directive', // login directive - 'oauth.accessToken', // access token service - 'oauth.endpoint', // oauth endpoint service - 'oauth.profile', // profile model - 'oauth.storage', // storage - 'oauth.interceptor', // bearer token interceptor - 'oauth.configuration' // token appender -]) - .config(['$locationProvider','$httpProvider', - function($locationProvider, $httpProvider) { - $httpProvider.interceptors.push('ExpiredInterceptor'); - }]); - -'use strict'; - -var accessTokenService = angular.module('oauth.accessToken', []); - -accessTokenService.factory('AccessToken', ['Storage', '$rootScope', '$location', '$interval', function(Storage, $rootScope, $location, $interval){ - - var service = { - token: null - }, - oAuth2HashTokens = [ //per http://tools.ietf.org/html/rfc6749#section-4.2.2 - 'access_token', 'token_type', 'expires_in', 'scope', 'state', - 'error','error_description' - ]; - - /** - * Returns the access token. - */ - service.get = function(){ - return this.token; - }; - - /** - * Sets and returns the access token. It tries (in order) the following strategies: - * - takes the token from the fragment URI - * - takes the token from the sessionStorage - */ - service.set = function(){ - this.setTokenFromString($location.hash()); - - //If hash is present in URL always use it, cuz its coming from oAuth2 provider redirect - if(null === service.token){ - setTokenFromSession(); - } - - return this.token; - }; - - /** - * Delete the access token and remove the session. - * @returns {null} - */ - service.destroy = function(){ - Storage.delete('token'); - this.token = null; - return this.token; - }; - - /** - * Tells if the access token is expired. - */ - service.expired = function(){ - return (this.token && this.token.expires_at && new Date(this.token.expires_at) < new Date()); - }; - - /** - * Get the access token from a string and save it - * @param hash - */ - service.setTokenFromString = function(hash){ - var params = getTokenFromString(hash); - - if(params){ - removeFragment(); - setToken(params); - setExpiresAt(); - // We have to save it again to make sure expires_at is set - // and the expiry event is set up properly - setToken(this.token); - $rootScope.$broadcast('oauth:login', service.token); - } - }; - - /* * * * * * * * * * - * PRIVATE METHODS * - * * * * * * * * * */ - - /** - * Set the access token from the sessionStorage. - */ - var setTokenFromSession = function(){ - var params = Storage.get('token'); - if (params) { - setToken(params); - } - }; - - /** - * Set the access token. - * - * @param params - * @returns {*|{}} - */ - var setToken = function(params){ - service.token = service.token || {}; // init the token - angular.extend(service.token, params); // set the access token params - setTokenInSession(); // save the token into the session - setExpiresAtEvent(); // event to fire when the token expires - - return service.token; - }; - - /** - * Parse the fragment URI and return an object - * @param hash - * @returns {{}} - */ - var getTokenFromString = function(hash){ - var params = {}, - regex = /([^&=]+)=([^&]*)/g, - m; - - while ((m = regex.exec(hash)) !== null) { - params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]); - } - - if(params.access_token || params.error){ - return params; - } - }; - - /** - * Save the access token into the session - */ - var setTokenInSession = function(){ - Storage.set('token', service.token); - }; - - /** - * Set the access token expiration date (useful for refresh logics) - */ - var setExpiresAt = function(){ - if (!service.token) { - return; - } - if(typeof(service.token.expires_in) !== 'undefined' && service.token.expires_in !== null) { - var expires_at = new Date(); - expires_at.setSeconds(expires_at.getSeconds() + parseInt(service.token.expires_in)-60); // 60 seconds less to secure browser and response latency - service.token.expires_at = expires_at; - } - else { - service.token.expires_at = null; - } - }; - - - /** - * Set the timeout at which the expired event is fired - */ - var setExpiresAtEvent = function(){ - // Don't bother if there's no expires token - if (typeof(service.token.expires_at) === 'undefined' || service.token.expires_at === null) { - return; - } - var time = (new Date(service.token.expires_at))-(new Date()); - if(time && time > 0){ - $interval(function(){ - $rootScope.$broadcast('oauth:expired', service.token); - }, time, 1); - } - }; - - /** - * Remove the oAuth2 pieces from the hash fragment - */ - var removeFragment = function(){ - var curHash = $location.hash(); - angular.forEach(oAuth2HashTokens,function(hashKey){ - var re = new RegExp('&'+hashKey+'(=[^&]*)?|^'+hashKey+'(=[^&]*)?&?'); - curHash = curHash.replace(re,''); - }); - - $location.hash(curHash); - }; - - return service; - -}]); - -'use strict'; - -var endpointClient = angular.module('oauth.endpoint', []); - -endpointClient.factory('Endpoint', function() { - - var service = {}; - - /* - * Defines the authorization URL - */ - - service.set = function(configuration) { - this.config = configuration; - return this.get(); - }; - - /* - * Returns the authorization URL - */ - - service.get = function( overrides ) { - var params = angular.extend( {}, service.config, overrides); - var oAuthScope = (params.scope) ? encodeURIComponent(params.scope) : '', - state = (params.state) ? encodeURIComponent(params.state) : '', - authPathHasQuery = (params.authorizePath.indexOf('?') === -1) ? false : true, - appendChar = (authPathHasQuery) ? '&' : '?', //if authorizePath has ? already append OAuth2 params - responseType = (params.responseType) ? encodeURIComponent(params.responseType) : ''; - - var url = params.site + - params.authorizePath + - appendChar + 'response_type=' + responseType + '&' + - 'client_id=' + encodeURIComponent(params.clientId) + '&' + - 'redirect_uri=' + encodeURIComponent(params.redirectUri) + '&' + - 'scope=' + oAuthScope + '&' + - 'state=' + state; - - if( params.nonce ) { - url = url + '&nonce=' + params.nonce; - } - return url; - }; - - /* - * Redirects the app to the authorization URL - */ - - service.redirect = function( overrides ) { - var targetLocation = this.get( overrides ); - window.location.replace(targetLocation); - }; - - return service; -}); - -'use strict'; - -var profileClient = angular.module('oauth.profile', []); - -profileClient.factory('Profile', ['$http', 'AccessToken', '$rootScope', function($http, AccessToken, $rootScope) { - var service = {}; - var profile; - - service.find = function(uri) { - var promise = $http.get(uri, { headers: headers() }); - promise.success(function(response) { - profile = response; - $rootScope.$broadcast('oauth:profile', profile); - }); - return promise; - }; - - service.get = function() { - return profile; - }; - - service.set = function(resource) { - profile = resource; - return profile; - }; - - var headers = function() { - return { Authorization: 'Bearer ' + AccessToken.get().access_token }; - }; - - return service; -}]); - -'use strict'; - -var storageService = angular.module('oauth.storage', ['ngStorage']); - -storageService.factory('Storage', ['$rootScope', '$sessionStorage', '$localStorage', function($rootScope, $sessionStorage, $localStorage){ - - var service = { - storage: $sessionStorage // By default - }; - - /** - * Deletes the item from storage, - * Returns the item's previous value - */ - service.delete = function (name) { - var stored = this.get(name); - delete this.storage[name]; - return stored; - }; - - /** - * Returns the item from storage - */ - service.get = function (name) { - return this.storage[name]; - }; - - /** - * Sets the item in storage to the value specified - * Returns the item's value - */ - service.set = function (name, value) { - this.storage[name] = value; - return this.get(name); - }; - - /** - * Change the storage service being used - */ - service.use = function (storage) { - if (storage === 'sessionStorage') { - this.storage = $sessionStorage; - } else if (storage === 'localStorage') { - this.storage = $localStorage; - } - }; - - return service; -}]); -'use strict'; - -var oauthConfigurationService = angular.module('oauth.configuration', []); - -oauthConfigurationService.provider('OAuthConfiguration', function() { - var _config = {}; - - this.init = function(config, httpProvider) { - _config.protectedResources = config.protectedResources || []; - httpProvider.interceptors.push('AuthInterceptor'); - }; - - this.$get = function() { - return { - getConfig: function() { - return _config; - } - }; - }; -}) -.factory('AuthInterceptor', function($q, $rootScope, OAuthConfiguration, AccessToken) { - return { - 'request': function(config) { - OAuthConfiguration.getConfig().protectedResources.forEach(function(resource) { - // If the url is one of the protected resources, we want to see if there's a token and then - // add the token if it exists. - if (config.url.indexOf(resource) > -1) { - var token = AccessToken.get(); - if (token) { - config.headers.Authorization = 'Bearer ' + token.access_token; - } - } - }); - - return config; - } - }; -}); -'use strict'; - -var interceptorService = angular.module('oauth.interceptor', []); - -interceptorService.factory('ExpiredInterceptor', ['Storage', '$rootScope', function (Storage, $rootScope) { - - var service = {}; - - service.request = function(config) { - var token = Storage.get('token'); - - if (token && expired(token)) { - $rootScope.$broadcast('oauth:expired', token); - } - - return config; - }; - - var expired = function(token) { - return (token && token.expires_at && new Date(token.expires_at) < new Date()); - }; - - return service; -}]); - -'use strict'; - -var directives = angular.module('oauth.directive', []); - -directives.directive('oauth', [ - 'AccessToken', - 'Endpoint', - 'Profile', - 'Storage', - '$location', - '$rootScope', - '$compile', - '$http', - '$templateCache', - function(AccessToken, Endpoint, Profile, Storage, $location, $rootScope, $compile, $http, $templateCache) { - - var definition = { - restrict: 'AE', - replace: true, - scope: { - site: '@', // (required) set the oauth server host (e.g. http://oauth.example.com) - clientId: '@', // (required) client id - redirectUri: '@', // (required) client redirect uri - responseType: '@', // (optional) response type, defaults to token (use 'token' for implicit flow and 'code' for authorization code flow - scope: '@', // (optional) scope - profileUri: '@', // (optional) user profile uri (e.g http://example.com/me) - template: '@', // (optional) template to render (e.g bower_components/oauth-ng/dist/views/templates/default.html) - text: '@', // (optional) login text - authorizePath: '@', // (optional) authorization url - state: '@', // (optional) An arbitrary unique string created by your app to guard against Cross-site Request Forgery - storage: '@' // (optional) Store token in 'sessionStorage' or 'localStorage', defaults to 'sessionStorage' - } - }; - - definition.link = function postLink(scope, element) { - scope.show = 'none'; - - scope.$watch('clientId', function() { - init(); - }); - - var init = function() { - initAttributes(); // sets defaults - Storage.use(scope.storage);// set storage - compile(); // compiles the desired layout - Endpoint.set(scope); // sets the oauth authorization url - AccessToken.set(scope); // sets the access token object (if existing, from fragment or session) - initProfile(scope); // gets the profile resource (if existing the access token) - initView(); // sets the view (logged in or out) - }; - - var initAttributes = function() { - scope.authorizePath = scope.authorizePath || '/oauth/authorize'; - scope.tokenPath = scope.tokenPath || '/oauth/token'; - scope.template = scope.template || 'bower_components/oauth-ng/dist/views/templates/default.html'; - scope.responseType = scope.responseType || 'token'; - scope.text = scope.text || 'Sign In'; - scope.state = scope.state || undefined; - scope.scope = scope.scope || undefined; - scope.storage = scope.storage || 'sessionStorage'; - }; - - var compile = function() { - $http.get(scope.template, { cache: $templateCache }).success(function(html) { - element.html(html); - $compile(element.contents())(scope); - }); - }; - - var initProfile = function(scope) { - var token = AccessToken.get(); - - if (token && token.access_token && scope.profileUri) { - Profile.find(scope.profileUri).success(function(response) { - scope.profile = response; - }); - } - }; - - var initView = function() { - var token = AccessToken.get(); - - if (!token) { - return loggedOut(); // without access token it's logged out - } - if (token.access_token) { - return authorized(); // if there is the access token we are done - } - if (token.error) { - return denied(); // if the request has been denied we fire the denied event - } - }; - - scope.login = function() { - Endpoint.redirect(); - }; - - scope.logout = function() { - AccessToken.destroy(scope); - $rootScope.$broadcast('oauth:logout'); - loggedOut(); - }; - - scope.$on('oauth:expired', function() { - AccessToken.destroy(scope); - scope.show = 'logged-out'; - }); - - // user is authorized - var authorized = function() { - $rootScope.$broadcast('oauth:authorized', AccessToken.get()); - scope.show = 'logged-in'; - }; - - // set the oauth directive to the logged-out status - var loggedOut = function() { - $rootScope.$broadcast('oauth:loggedOut'); - scope.show = 'logged-out'; - }; - - // set the oauth directive to the denied status - var denied = function() { - scope.show = 'denied'; - $rootScope.$broadcast('oauth:denied'); - }; - - // Updates the template at runtime - scope.$on('oauth:template:update', function(event, template) { - scope.template = template; - compile(scope); - }); - - // Hack to update the directive content on logout - // TODO think to a cleaner solution - scope.$on('$routeChangeSuccess', function () { - init(); - }); - }; - - return definition; - } -]); diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/templates/header.html b/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/templates/header.html deleted file mode 100644 index a62bce9747..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/templates/header.html +++ /dev/null @@ -1,56 +0,0 @@ -
      - - - - - - - - - - - - - - -
      \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/templates/index.html b/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/templates/index.html deleted file mode 100755 index c98ed493bd..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/templates/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - -Spring Security OAuth - - - - -
      - -
      -

      Foo Details

      -
      - - {{foo.id}} -
      - -
      - -{{foo.name}} -
      - - -
      - - \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/templates/oauthTemp.html b/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/templates/oauthTemp.html deleted file mode 100644 index 1efc1eed3c..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/resources/templates/oauthTemp.html +++ /dev/null @@ -1,6 +0,0 @@ - \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/webapp/resources/oauth-ng.js b/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/webapp/resources/oauth-ng.js deleted file mode 100644 index 333070b935..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-implicit/src/main/webapp/resources/oauth-ng.js +++ /dev/null @@ -1,539 +0,0 @@ -/* oauth-ng - v0.4.2 - 2015-08-27 */ - -'use strict'; - -// App libraries -angular.module('oauth', [ - 'oauth.directive', // login directive - 'oauth.accessToken', // access token service - 'oauth.endpoint', // oauth endpoint service - 'oauth.profile', // profile model - 'oauth.storage', // storage - 'oauth.interceptor', // bearer token interceptor - 'oauth.configuration' // token appender -]) - .config(['$locationProvider','$httpProvider', - function($locationProvider, $httpProvider) { - $httpProvider.interceptors.push('ExpiredInterceptor'); - }]); - -'use strict'; - -var accessTokenService = angular.module('oauth.accessToken', []); - -accessTokenService.factory('AccessToken', ['Storage', '$rootScope', '$location', '$interval', function(Storage, $rootScope, $location, $interval){ - - var service = { - token: null - }, - oAuth2HashTokens = [ //per http://tools.ietf.org/html/rfc6749#section-4.2.2 - 'access_token', 'token_type', 'expires_in', 'scope', 'state', - 'error','error_description' - ]; - - /** - * Returns the access token. - */ - service.get = function(){ - return this.token; - }; - - /** - * Sets and returns the access token. It tries (in order) the following strategies: - * - takes the token from the fragment URI - * - takes the token from the sessionStorage - */ - service.set = function(){ - this.setTokenFromString($location.hash()); - - //If hash is present in URL always use it, cuz its coming from oAuth2 provider redirect - if(null === service.token){ - setTokenFromSession(); - } - - return this.token; - }; - - /** - * Delete the access token and remove the session. - * @returns {null} - */ - service.destroy = function(){ - Storage.delete('token'); - this.token = null; - return this.token; - }; - - /** - * Tells if the access token is expired. - */ - service.expired = function(){ - return (this.token && this.token.expires_at && new Date(this.token.expires_at) < new Date()); - }; - - /** - * Get the access token from a string and save it - * @param hash - */ - service.setTokenFromString = function(hash){ - var params = getTokenFromString(hash); - - if(params){ - removeFragment(); - setToken(params); - setExpiresAt(); - // We have to save it again to make sure expires_at is set - // and the expiry event is set up properly - setToken(this.token); - $rootScope.$broadcast('oauth:login', service.token); - } - }; - - /* * * * * * * * * * - * PRIVATE METHODS * - * * * * * * * * * */ - - /** - * Set the access token from the sessionStorage. - */ - var setTokenFromSession = function(){ - var params = Storage.get('token'); - if (params) { - setToken(params); - } - }; - - /** - * Set the access token. - * - * @param params - * @returns {*|{}} - */ - var setToken = function(params){ - service.token = service.token || {}; // init the token - angular.extend(service.token, params); // set the access token params - setTokenInSession(); // save the token into the session - setExpiresAtEvent(); // event to fire when the token expires - - return service.token; - }; - - /** - * Parse the fragment URI and return an object - * @param hash - * @returns {{}} - */ - var getTokenFromString = function(hash){ - var params = {}, - regex = /([^&=]+)=([^&]*)/g, - m; - - while ((m = regex.exec(hash)) !== null) { - params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]); - } - - if(params.access_token || params.error){ - return params; - } - }; - - /** - * Save the access token into the session - */ - var setTokenInSession = function(){ - Storage.set('token', service.token); - }; - - /** - * Set the access token expiration date (useful for refresh logics) - */ - var setExpiresAt = function(){ - if (!service.token) { - return; - } - if(typeof(service.token.expires_in) !== 'undefined' && service.token.expires_in !== null) { - var expires_at = new Date(); - expires_at.setSeconds(expires_at.getSeconds() + parseInt(service.token.expires_in)-60); // 60 seconds less to secure browser and response latency - service.token.expires_at = expires_at; - } - else { - service.token.expires_at = null; - } - }; - - - /** - * Set the timeout at which the expired event is fired - */ - var setExpiresAtEvent = function(){ - // Don't bother if there's no expires token - if (typeof(service.token.expires_at) === 'undefined' || service.token.expires_at === null) { - return; - } - var time = (new Date(service.token.expires_at))-(new Date()); - if(time && time > 0){ - $interval(function(){ - $rootScope.$broadcast('oauth:expired', service.token); - }, time, 1); - } - }; - - /** - * Remove the oAuth2 pieces from the hash fragment - */ - var removeFragment = function(){ - var curHash = $location.hash(); - angular.forEach(oAuth2HashTokens,function(hashKey){ - var re = new RegExp('&'+hashKey+'(=[^&]*)?|^'+hashKey+'(=[^&]*)?&?'); - curHash = curHash.replace(re,''); - }); - - $location.hash(curHash); - }; - - return service; - -}]); - -'use strict'; - -var endpointClient = angular.module('oauth.endpoint', []); - -endpointClient.factory('Endpoint', function() { - - var service = {}; - - /* - * Defines the authorization URL - */ - - service.set = function(configuration) { - this.config = configuration; - return this.get(); - }; - - /* - * Returns the authorization URL - */ - - service.get = function( overrides ) { - var params = angular.extend( {}, service.config, overrides); - var oAuthScope = (params.scope) ? encodeURIComponent(params.scope) : '', - state = (params.state) ? encodeURIComponent(params.state) : '', - authPathHasQuery = (params.authorizePath.indexOf('?') === -1) ? false : true, - appendChar = (authPathHasQuery) ? '&' : '?', //if authorizePath has ? already append OAuth2 params - responseType = (params.responseType) ? encodeURIComponent(params.responseType) : ''; - - var url = params.site + - params.authorizePath + - appendChar + 'response_type=' + responseType + '&' + - 'client_id=' + encodeURIComponent(params.clientId) + '&' + - 'redirect_uri=' + encodeURIComponent(params.redirectUri) + '&' + - 'scope=' + oAuthScope + '&' + - 'state=' + state; - - if( params.nonce ) { - url = url + '&nonce=' + params.nonce; - } - return url; - }; - - /* - * Redirects the app to the authorization URL - */ - - service.redirect = function( overrides ) { - var targetLocation = this.get( overrides ); - window.location.replace(targetLocation); - }; - - return service; -}); - -'use strict'; - -var profileClient = angular.module('oauth.profile', []); - -profileClient.factory('Profile', ['$http', 'AccessToken', '$rootScope', function($http, AccessToken, $rootScope) { - var service = {}; - var profile; - - service.find = function(uri) { - var promise = $http.get(uri, { headers: headers() }); - promise.success(function(response) { - profile = response; - $rootScope.$broadcast('oauth:profile', profile); - }); - return promise; - }; - - service.get = function() { - return profile; - }; - - service.set = function(resource) { - profile = resource; - return profile; - }; - - var headers = function() { - return { Authorization: 'Bearer ' + AccessToken.get().access_token }; - }; - - return service; -}]); - -'use strict'; - -var storageService = angular.module('oauth.storage', ['ngStorage']); - -storageService.factory('Storage', ['$rootScope', '$sessionStorage', '$localStorage', function($rootScope, $sessionStorage, $localStorage){ - - var service = { - storage: $sessionStorage // By default - }; - - /** - * Deletes the item from storage, - * Returns the item's previous value - */ - service.delete = function (name) { - var stored = this.get(name); - delete this.storage[name]; - return stored; - }; - - /** - * Returns the item from storage - */ - service.get = function (name) { - return this.storage[name]; - }; - - /** - * Sets the item in storage to the value specified - * Returns the item's value - */ - service.set = function (name, value) { - this.storage[name] = value; - return this.get(name); - }; - - /** - * Change the storage service being used - */ - service.use = function (storage) { - if (storage === 'sessionStorage') { - this.storage = $sessionStorage; - } else if (storage === 'localStorage') { - this.storage = $localStorage; - } - }; - - return service; -}]); -'use strict'; - -var oauthConfigurationService = angular.module('oauth.configuration', []); - -oauthConfigurationService.provider('OAuthConfiguration', function() { - var _config = {}; - - this.init = function(config, httpProvider) { - _config.protectedResources = config.protectedResources || []; - httpProvider.interceptors.push('AuthInterceptor'); - }; - - this.$get = function() { - return { - getConfig: function() { - return _config; - } - }; - }; -}) -.factory('AuthInterceptor', function($q, $rootScope, OAuthConfiguration, AccessToken) { - return { - 'request': function(config) { - OAuthConfiguration.getConfig().protectedResources.forEach(function(resource) { - // If the url is one of the protected resources, we want to see if there's a token and then - // add the token if it exists. - if (config.url.indexOf(resource) > -1) { - var token = AccessToken.get(); - if (token) { - config.headers.Authorization = 'Bearer ' + token.access_token; - } - } - }); - - return config; - } - }; -}); -'use strict'; - -var interceptorService = angular.module('oauth.interceptor', []); - -interceptorService.factory('ExpiredInterceptor', ['Storage', '$rootScope', function (Storage, $rootScope) { - - var service = {}; - - service.request = function(config) { - var token = Storage.get('token'); - - if (token && expired(token)) { - $rootScope.$broadcast('oauth:expired', token); - } - - return config; - }; - - var expired = function(token) { - return (token && token.expires_at && new Date(token.expires_at) < new Date()); - }; - - return service; -}]); - -'use strict'; - -var directives = angular.module('oauth.directive', []); - -directives.directive('oauth', [ - 'AccessToken', - 'Endpoint', - 'Profile', - 'Storage', - '$location', - '$rootScope', - '$compile', - '$http', - '$templateCache', - function(AccessToken, Endpoint, Profile, Storage, $location, $rootScope, $compile, $http, $templateCache) { - - var definition = { - restrict: 'AE', - replace: true, - scope: { - site: '@', // (required) set the oauth server host (e.g. http://oauth.example.com) - clientId: '@', // (required) client id - redirectUri: '@', // (required) client redirect uri - responseType: '@', // (optional) response type, defaults to token (use 'token' for implicit flow and 'code' for authorization code flow - scope: '@', // (optional) scope - profileUri: '@', // (optional) user profile uri (e.g http://example.com/me) - template: '@', // (optional) template to render (e.g bower_components/oauth-ng/dist/views/templates/default.html) - text: '@', // (optional) login text - authorizePath: '@', // (optional) authorization url - state: '@', // (optional) An arbitrary unique string created by your app to guard against Cross-site Request Forgery - storage: '@' // (optional) Store token in 'sessionStorage' or 'localStorage', defaults to 'sessionStorage' - } - }; - - definition.link = function postLink(scope, element) { - scope.show = 'none'; - - scope.$watch('clientId', function() { - init(); - }); - - var init = function() { - initAttributes(); // sets defaults - Storage.use(scope.storage);// set storage - compile(); // compiles the desired layout - Endpoint.set(scope); // sets the oauth authorization url - AccessToken.set(scope); // sets the access token object (if existing, from fragment or session) - initProfile(scope); // gets the profile resource (if existing the access token) - initView(); // sets the view (logged in or out) - }; - - var initAttributes = function() { - scope.authorizePath = scope.authorizePath || '/oauth/authorize'; - scope.tokenPath = scope.tokenPath || '/oauth/token'; - scope.template = scope.template || 'bower_components/oauth-ng/dist/views/templates/default.html'; - scope.responseType = scope.responseType || 'token'; - scope.text = scope.text || 'Sign In'; - scope.state = scope.state || undefined; - scope.scope = scope.scope || undefined; - scope.storage = scope.storage || 'sessionStorage'; - }; - - var compile = function() { - $http.get(scope.template, { cache: $templateCache }).success(function(html) { - element.html(html); - $compile(element.contents())(scope); - }); - }; - - var initProfile = function(scope) { - var token = AccessToken.get(); - - if (token && token.access_token && scope.profileUri) { - Profile.find(scope.profileUri).success(function(response) { - scope.profile = response; - }); - } - }; - - var initView = function() { - var token = AccessToken.get(); - - if (!token) { - return loggedOut(); // without access token it's logged out - } - if (token.access_token) { - return authorized(); // if there is the access token we are done - } - if (token.error) { - return denied(); // if the request has been denied we fire the denied event - } - }; - - scope.login = function() { - Endpoint.redirect(); - }; - - scope.logout = function() { - AccessToken.destroy(scope); - $rootScope.$broadcast('oauth:logout'); - loggedOut(); - }; - - scope.$on('oauth:expired', function() { - AccessToken.destroy(scope); - scope.show = 'logged-out'; - }); - - // user is authorized - var authorized = function() { - $rootScope.$broadcast('oauth:authorized', AccessToken.get()); - scope.show = 'logged-in'; - }; - - // set the oauth directive to the logged-out status - var loggedOut = function() { - $rootScope.$broadcast('oauth:loggedOut'); - scope.show = 'logged-out'; - }; - - // set the oauth directive to the denied status - var denied = function() { - scope.show = 'denied'; - $rootScope.$broadcast('oauth:denied'); - }; - - // Updates the template at runtime - scope.$on('oauth:template:update', function(event, template) { - scope.template = template; - compile(scope); - }); - - // Hack to update the directive content on logout - // TODO think to a cleaner solution - scope.$on('$routeChangeSuccess', function () { - init(); - }); - }; - - return definition; - } -]); diff --git a/spring-security-oauth/spring-security-oauth-ui-password/.classpath b/spring-security-oauth/spring-security-oauth-ui-password/.classpath deleted file mode 100644 index 0cad5db2d0..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-password/.classpath +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-oauth/spring-security-oauth-ui-password/.project b/spring-security-oauth/spring-security-oauth-ui-password/.project deleted file mode 100644 index 58d50a3f3a..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-password/.project +++ /dev/null @@ -1,48 +0,0 @@ - - - spring-security-oauth-ui-password - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-security-oauth/spring-security-oauth-ui-password/pom.xml b/spring-security-oauth/spring-security-oauth-ui-password/pom.xml deleted file mode 100644 index a2bf3d07bb..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-password/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - 4.0.0 - spring-security-oauth-ui-password - - spring-security-oauth-ui-password - war - - - org.baeldung - spring-security-oauth - 1.0.0-SNAPSHOT - - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - - - spring-security-oauth-ui-password - - - src/main/resources - true - - - - \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-password/src/main/java/org/baeldung/config/UiApplication.java b/spring-security-oauth/spring-security-oauth-ui-password/src/main/java/org/baeldung/config/UiApplication.java deleted file mode 100644 index 8f491516aa..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-password/src/main/java/org/baeldung/config/UiApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.config; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.web.SpringBootServletInitializer; - -@SpringBootApplication -public class UiApplication extends SpringBootServletInitializer { - - public static void main(String[] args) { - SpringApplication.run(UiApplication.class, args); - } -} \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-password/src/main/java/org/baeldung/config/UiWebConfig.java b/spring-security-oauth/spring-security-oauth-ui-password/src/main/java/org/baeldung/config/UiWebConfig.java deleted file mode 100644 index 0732182354..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-password/src/main/java/org/baeldung/config/UiWebConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.baeldung.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; -import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; - -@Configuration -@EnableWebMvc -public class UiWebConfig extends WebMvcConfigurerAdapter { - - @Bean - public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { - return new PropertySourcesPlaceholderConfigurer(); - } - - @Override - public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { - configurer.enable(); - } - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); - registry.addViewController("/").setViewName("forward:/index"); - registry.addViewController("/index"); - registry.addViewController("/login"); - } - - @Override - public void addResourceHandlers(final ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); - } - -} \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/application.properties b/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/application.properties deleted file mode 100644 index e76a587680..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -server.contextPath=/spring-security-oauth-ui-password -server.port=8081 \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/templates/header.html b/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/templates/header.html deleted file mode 100644 index 0bfe086bf1..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/templates/header.html +++ /dev/null @@ -1,73 +0,0 @@ -
      - - - - - - - - - - - -
      \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/templates/index.html b/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/templates/index.html deleted file mode 100755 index e2458c2940..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/templates/index.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - -Spring Security OAuth - - - - -
      - -
      -

      Foo Details

      -
      - - {{foo.id}} -
      - -
      - -{{foo.name}} -
      - - - -
      - - \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/templates/login.html b/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/templates/login.html deleted file mode 100755 index 4d105cec6c..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-password/src/main/resources/templates/login.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - -Spring Security OAuth - - - - -
      - -
      - -

      Login

      -
      -
      - - -
      - -
      - - -
      - -
      -Login -
      - -
      - -
      - - \ No newline at end of file diff --git a/spring-security-oauth/spring-security-oauth-ui-password/src/main/webapp/resources/angular-utf8-base64.min.js b/spring-security-oauth/spring-security-oauth-ui-password/src/main/webapp/resources/angular-utf8-base64.min.js deleted file mode 100644 index 24af57d020..0000000000 --- a/spring-security-oauth/spring-security-oauth-ui-password/src/main/webapp/resources/angular-utf8-base64.min.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";angular.module("ab-base64",[]).constant("base64",function(){var a={alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",lookup:null,ie:/MSIE /.test(navigator.userAgent),ieo:/MSIE [67]/.test(navigator.userAgent),encode:function(b){var c,d,e,f,g=a.toUtf8(b),h=-1,i=g.length,j=[,,,];if(a.ie){for(c=[];++h>2,j[1]=(3&d)<<4|e>>4,isNaN(e)?j[2]=j[3]=64:(f=g[++h],j[2]=(15&e)<<2|f>>6,j[3]=isNaN(f)?64:63&f),c.push(a.alphabet.charAt(j[0]),a.alphabet.charAt(j[1]),a.alphabet.charAt(j[2]),a.alphabet.charAt(j[3]));return c.join("")}for(c="";++h>2,j[1]=(3&d)<<4|e>>4,isNaN(e)?j[2]=j[3]=64:(f=g[++h],j[2]=(15&e)<<2|f>>6,j[3]=isNaN(f)?64:63&f),c+=a.alphabet[j[0]]+a.alphabet[j[1]]+a.alphabet[j[2]]+a.alphabet[j[3]];return c},decode:function(b){if(b=b.replace(/\s/g,""),b.length%4)throw new Error("InvalidLengthError: decode failed: The string to be decoded is not the correct length for a base64 encoded string.");if(/[^A-Za-z0-9+\/=\s]/g.test(b))throw new Error("InvalidCharacterError: decode failed: The string contains characters invalid in a base64 encoded string.");var c,d=a.fromUtf8(b),e=0,f=d.length;if(a.ieo){for(c=[];f>e;)c.push(d[e]<128?String.fromCharCode(d[e++]):d[e]>191&&d[e]<224?String.fromCharCode((31&d[e++])<<6|63&d[e++]):String.fromCharCode((15&d[e++])<<12|(63&d[e++])<<6|63&d[e++]));return c.join("")}for(c="";f>e;)c+=String.fromCharCode(d[e]<128?d[e++]:d[e]>191&&d[e]<224?(31&d[e++])<<6|63&d[e++]:(15&d[e++])<<12|(63&d[e++])<<6|63&d[e++]);return c},toUtf8:function(a){var b,c=-1,d=a.length,e=[];if(/^[\x00-\x7f]*$/.test(a))for(;++cb?e.push(b):2048>b?e.push(b>>6|192,63&b|128):e.push(b>>12|224,b>>6&63|128,63&b|128);return e},fromUtf8:function(b){var c,d=-1,e=[],f=[,,,];if(!a.lookup){for(c=a.alphabet.length,a.lookup={};++d>4),f[2]=a.lookup[b.charAt(++d)],64!==f[2])&&(e.push((15&f[1])<<4|f[2]>>2),f[3]=a.lookup[b.charAt(++d)],64!==f[3]);)e.push((3&f[2])<<6|f[3]);return e}},b={decode:function(b){b=b.replace(/-/g,"+").replace(/_/g,"/");var c=b.length%4;if(c){if(1===c)throw new Error("InvalidLengthError: Input base64url string is the wrong length to determine padding");b+=new Array(5-c).join("=")}return a.decode(b)},encode:function(b){var c=a.encode(b);return c.replace(/\+/g,"-").replace(/\//g,"_").split("=",1)[0]}};return{decode:a.decode,encode:a.encode,urldecode:b.decode,urlencode:b.encode}}()); \ No newline at end of file diff --git a/spring-security-rest-basic-auth/.classpath b/spring-security-rest-basic-auth/.classpath deleted file mode 100644 index 5778c9435e..0000000000 --- a/spring-security-rest-basic-auth/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-rest-basic-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-security-rest-basic-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-security-rest-basic-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-rest-basic-auth/.project b/spring-security-rest-basic-auth/.project deleted file mode 100644 index 17907f1636..0000000000 --- a/spring-security-rest-basic-auth/.project +++ /dev/null @@ -1,42 +0,0 @@ - - - spring-security-rest-basic-auth - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/spring-security-rest-basic-auth/.settings/.jsdtscope b/spring-security-rest-basic-auth/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/spring-security-rest-basic-auth/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-rest-basic-auth/.settings/org.eclipse.jdt.core.prefs b/spring-security-rest-basic-auth/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index fb671a82a6..0000000000 --- a/spring-security-rest-basic-auth/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-security-rest-basic-auth/.settings/org.eclipse.jdt.ui.prefs b/spring-security-rest-basic-auth/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-security-rest-basic-auth/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-security-rest-basic-auth/.settings/org.eclipse.m2e.core.prefs b/spring-security-rest-basic-auth/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-security-rest-basic-auth/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-security-rest-basic-auth/.settings/org.eclipse.m2e.wtp.prefs b/spring-security-rest-basic-auth/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-security-rest-basic-auth/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.common.component b/spring-security-rest-basic-auth/.settings/org.eclipse.wst.common.component deleted file mode 100644 index d852102ca2..0000000000 --- a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-security-rest-basic-auth/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f5888c1411..0000000000 --- a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-security-rest-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-security-rest-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.validation.prefs b/spring-security-rest-basic-auth/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-security-rest-basic-auth/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-security-rest-basic-auth/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-security-rest-basic-auth/.springBeans b/spring-security-rest-basic-auth/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/spring-security-rest-basic-auth/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/spring-security-rest-basic-auth/README.md b/spring-security-rest-basic-auth/README.md index 723bcebbdd..3bd46bdd2a 100644 --- a/spring-security-rest-basic-auth/README.md +++ b/spring-security-rest-basic-auth/README.md @@ -2,6 +2,8 @@ ## REST API with Basic Authentication - Example Project +###The Course +The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [RestTemplate with Basic Authentication in Spring](http://www.baeldung.com/2012/04/16/how-to-use-resttemplate-with-basic-authentication-in-spring-3-1) diff --git a/spring-security-rest-basic-auth/pom.xml b/spring-security-rest-basic-auth/pom.xml index 767edb7778..854bbb70be 100644 --- a/spring-security-rest-basic-auth/pom.xml +++ b/spring-security-rest-basic-auth/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-rest-basic-auth 0.2-SNAPSHOT @@ -287,12 +287,12 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 4.4.4 @@ -317,13 +317,13 @@ 4.12 1.10.19 - 2.8.0 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.19 - 1.4.17 + 2.19.1 + 1.4.18 diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/RestClientLiveManualTest.java b/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/RestClientLiveManualTest.java index b47f893b17..44c5c0cbb1 100644 --- a/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/RestClientLiveManualTest.java +++ b/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/RestClientLiveManualTest.java @@ -17,6 +17,7 @@ import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; +import org.junit.Ignore; import org.junit.Test; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; @@ -33,6 +34,8 @@ public class RestClientLiveManualTest { // tests + // old httpClient will throw UnsupportedOperationException + @Ignore @Test public final void givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenException() throws GeneralSecurityException { final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/test/LiveTestSuite.java b/spring-security-rest-basic-auth/src/test/java/org/baeldung/test/LiveTestSuite.java new file mode 100644 index 0000000000..8c9b48d056 --- /dev/null +++ b/spring-security-rest-basic-auth/src/test/java/org/baeldung/test/LiveTestSuite.java @@ -0,0 +1,16 @@ +package org.baeldung.test; + +import org.baeldung.client.ClientLiveTest; +import org.baeldung.client.RestClientLiveManualTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ +// @formatter:off + RestClientLiveManualTest.class + ,ClientLiveTest.class +}) // +public class LiveTestSuite { + +} diff --git a/spring-security-rest-custom/.classpath b/spring-security-rest-custom/.classpath deleted file mode 100644 index 5778c9435e..0000000000 --- a/spring-security-rest-custom/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-rest-custom/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-security-rest-custom/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-security-rest-custom/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-rest-custom/.gitignore b/spring-security-rest-custom/.gitignore deleted file mode 100644 index 83c05e60c8..0000000000 --- a/spring-security-rest-custom/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -*.class - -#folders# -/target -/neoDb* -/data -/src/main/webapp/WEB-INF/classes -*/META-INF/* - -# Packaged files # -*.jar -*.war -*.ear \ No newline at end of file diff --git a/spring-security-rest-custom/.project b/spring-security-rest-custom/.project deleted file mode 100644 index 801347984e..0000000000 --- a/spring-security-rest-custom/.project +++ /dev/null @@ -1,42 +0,0 @@ - - - spring-security-rest-custom - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/spring-security-rest-custom/.settings/.jsdtscope b/spring-security-rest-custom/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/spring-security-rest-custom/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-rest-custom/.settings/org.eclipse.jdt.core.prefs b/spring-security-rest-custom/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index fb671a82a6..0000000000 --- a/spring-security-rest-custom/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-security-rest-custom/.settings/org.eclipse.jdt.ui.prefs b/spring-security-rest-custom/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-security-rest-custom/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-security-rest-custom/.settings/org.eclipse.m2e.core.prefs b/spring-security-rest-custom/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-security-rest-custom/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-security-rest-custom/.settings/org.eclipse.m2e.wtp.prefs b/spring-security-rest-custom/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-security-rest-custom/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-security-rest-custom/.settings/org.eclipse.wst.common.component b/spring-security-rest-custom/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 3b22cb60bb..0000000000 --- a/spring-security-rest-custom/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-security-rest-custom/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-security-rest-custom/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index c5c0da6037..0000000000 --- a/spring-security-rest-custom/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-rest-custom/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-security-rest-custom/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-security-rest-custom/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-security-rest-custom/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-security-rest-custom/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-security-rest-custom/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-security-rest-custom/.settings/org.eclipse.wst.validation.prefs b/spring-security-rest-custom/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-security-rest-custom/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-security-rest-custom/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-security-rest-custom/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-security-rest-custom/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-security-rest-custom/.springBeans b/spring-security-rest-custom/.springBeans deleted file mode 100644 index f25fc5ab49..0000000000 --- a/spring-security-rest-custom/.springBeans +++ /dev/null @@ -1,13 +0,0 @@ - - - 1 - - - - - - - - - - diff --git a/spring-security-rest-custom/README.md b/spring-security-rest-custom/README.md index f19af32d41..85f2b7532c 100644 --- a/spring-security-rest-custom/README.md +++ b/spring-security-rest-custom/README.md @@ -2,6 +2,9 @@ ## Spring Security for REST Example Project +###The Course +The "REST With Spring" Classes: http://github.learnspringsecurity.com + ### Relevant Articles: - [Spring Security Authentication Provider](http://www.baeldung.com/spring-security-authentication-provider) - [Retrieve User Information in Spring Security](http://www.baeldung.com/get-user-in-spring-security) diff --git a/spring-security-rest-custom/pom.xml b/spring-security-rest-custom/pom.xml index df936353d9..071fa14b71 100644 --- a/spring-security-rest-custom/pom.xml +++ b/spring-security-rest-custom/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-rest-custom 0.1-SNAPSHOT @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.3.2.RELEASE + 1.3.3.RELEASE @@ -254,12 +254,12 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 1.7.13 @@ -280,13 +280,13 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 - 1.4.15 + 2.19.1 + 1.4.18 diff --git a/spring-security-rest-custom/src/main/java/org/baeldung/config/parent/SecurityConfig.java b/spring-security-rest-custom/src/main/java/org/baeldung/config/parent/SecurityConfig.java index ee9b0868e7..67d9abbae5 100644 --- a/spring-security-rest-custom/src/main/java/org/baeldung/config/parent/SecurityConfig.java +++ b/spring-security-rest-custom/src/main/java/org/baeldung/config/parent/SecurityConfig.java @@ -1,16 +1,41 @@ package org.baeldung.config.parent; +import org.baeldung.security.CustomAuthenticationProvider; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration -@ImportResource({ "classpath:webSecurityConfig.xml" }) +// @ImportResource({ "classpath:webSecurityConfig.xml" }) +@EnableWebSecurity @ComponentScan("org.baeldung.security") -public class SecurityConfig { +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private CustomAuthenticationProvider authProvider; public SecurityConfig() { super(); } + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.authenticationProvider(authProvider); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http + .authorizeRequests().anyRequest().authenticated() + .and() + .httpBasic(); + // @formatter:on + } + + } diff --git a/spring-security-rest-digest-auth/.classpath b/spring-security-rest-digest-auth/.classpath deleted file mode 100644 index 5778c9435e..0000000000 --- a/spring-security-rest-digest-auth/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-rest-digest-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-security-rest-digest-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-security-rest-digest-auth/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-rest-digest-auth/.project b/spring-security-rest-digest-auth/.project deleted file mode 100644 index 7c28666685..0000000000 --- a/spring-security-rest-digest-auth/.project +++ /dev/null @@ -1,42 +0,0 @@ - - - spring-security-rest-digest-auth - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - diff --git a/spring-security-rest-digest-auth/.settings/.jsdtscope b/spring-security-rest-digest-auth/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/spring-security-rest-digest-auth/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-rest-digest-auth/.settings/org.eclipse.jdt.core.prefs b/spring-security-rest-digest-auth/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index fb671a82a6..0000000000 --- a/spring-security-rest-digest-auth/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-security-rest-digest-auth/.settings/org.eclipse.jdt.ui.prefs b/spring-security-rest-digest-auth/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-security-rest-digest-auth/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-security-rest-digest-auth/.settings/org.eclipse.m2e.core.prefs b/spring-security-rest-digest-auth/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-security-rest-digest-auth/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-security-rest-digest-auth/.settings/org.eclipse.m2e.wtp.prefs b/spring-security-rest-digest-auth/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-security-rest-digest-auth/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.common.component b/spring-security-rest-digest-auth/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 128f61d711..0000000000 --- a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-security-rest-digest-auth/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 8a1c189419..0000000000 --- a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-security-rest-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-security-rest-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.validation.prefs b/spring-security-rest-digest-auth/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-security-rest-digest-auth/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-security-rest-digest-auth/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-security-rest-digest-auth/.springBeans b/spring-security-rest-digest-auth/.springBeans deleted file mode 100644 index a79097f40d..0000000000 --- a/spring-security-rest-digest-auth/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/spring-security-rest-digest-auth/README.md b/spring-security-rest-digest-auth/README.md index 06e847edad..3328bcb2e3 100644 --- a/spring-security-rest-digest-auth/README.md +++ b/spring-security-rest-digest-auth/README.md @@ -2,6 +2,8 @@ ## REST API with Digest Authentication - Example Project +###The Course +The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [RestTemplate with Digest Authentication](http://www.baeldung.com/resttemplate-digest-authentication) diff --git a/spring-security-rest-digest-auth/pom.xml b/spring-security-rest-digest-auth/pom.xml index 88e760458b..bfb4a7223a 100644 --- a/spring-security-rest-digest-auth/pom.xml +++ b/spring-security-rest-digest-auth/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-rest-digest-auth 0.1-SNAPSHOT @@ -83,6 +83,12 @@ ${org.springframework.version} + + org.springframework + spring-web + ${org.springframework.version} + + @@ -274,12 +280,12 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 4.4.4 @@ -290,7 +296,7 @@ 1.1.3 - 2.5.5 + 2.7.2 5.2.2.Final @@ -306,13 +312,13 @@ 4.12 1.10.19 - 2.8.0 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.19 - 1.4.17 + 2.19.1 + 1.4.18 diff --git a/spring-security-rest-digest-auth/src/test/java/org/baeldung/test/LiveTestSuite.java b/spring-security-rest-digest-auth/src/test/java/org/baeldung/test/LiveTestSuite.java new file mode 100644 index 0000000000..9e141a87cd --- /dev/null +++ b/spring-security-rest-digest-auth/src/test/java/org/baeldung/test/LiveTestSuite.java @@ -0,0 +1,18 @@ +package org.baeldung.test; + +import org.baeldung.client.ClientNoSpringLiveTest; +import org.baeldung.client.ClientWithSpringLiveTest; +import org.baeldung.client.RawClientLiveTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ +// @formatter:off + RawClientLiveTest.class + ,ClientWithSpringLiveTest.class + ,ClientNoSpringLiveTest.class +}) // +public class LiveTestSuite { + +} diff --git a/spring-security-rest-full/.classpath b/spring-security-rest-full/.classpath deleted file mode 100644 index 979639ff7d..0000000000 --- a/spring-security-rest-full/.classpath +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-rest-full/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-security-rest-full/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-security-rest-full/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-rest-full/.externalToolBuilders/org.hibernate.eclipse.console.hibernateBuilder.launch b/spring-security-rest-full/.externalToolBuilders/org.hibernate.eclipse.console.hibernateBuilder.launch deleted file mode 100644 index 9bc0284d26..0000000000 --- a/spring-security-rest-full/.externalToolBuilders/org.hibernate.eclipse.console.hibernateBuilder.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-rest-full/.project b/spring-security-rest-full/.project deleted file mode 100644 index 188b8b07fe..0000000000 --- a/spring-security-rest-full/.project +++ /dev/null @@ -1,53 +0,0 @@ - - - spring-security-rest-full - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.ui.externaltools.ExternalToolBuilder - full,incremental, - - - LaunchConfigHandle - <project>/.externalToolBuilders/org.hibernate.eclipse.console.hibernateBuilder.launch - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.hibernate.eclipse.console.hibernateNature - - diff --git a/spring-security-rest-full/.settings/.jsdtscope b/spring-security-rest-full/.settings/.jsdtscope deleted file mode 100644 index 7b3f0c8b9f..0000000000 --- a/spring-security-rest-full/.settings/.jsdtscope +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-rest-full/.settings/org.eclipse.jdt.core.prefs b/spring-security-rest-full/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 361cd318f6..0000000000 --- a/spring-security-rest-full/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,96 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-security-rest-full/.settings/org.eclipse.jdt.ui.prefs b/spring-security-rest-full/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-security-rest-full/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-security-rest-full/.settings/org.eclipse.m2e.core.prefs b/spring-security-rest-full/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-security-rest-full/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-security-rest-full/.settings/org.eclipse.m2e.wtp.prefs b/spring-security-rest-full/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-security-rest-full/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-security-rest-full/.settings/org.eclipse.wst.common.component b/spring-security-rest-full/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 3b942952f2..0000000000 --- a/spring-security-rest-full/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/spring-security-rest-full/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-security-rest-full/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index f5888c1411..0000000000 --- a/spring-security-rest-full/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/spring-security-rest-full/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-security-rest-full/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-security-rest-full/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-security-rest-full/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-security-rest-full/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-security-rest-full/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-security-rest-full/.settings/org.eclipse.wst.validation.prefs b/spring-security-rest-full/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-security-rest-full/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-security-rest-full/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-security-rest-full/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-security-rest-full/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-security-rest-full/.springBeans b/spring-security-rest-full/.springBeans deleted file mode 100644 index 78c6703708..0000000000 --- a/spring-security-rest-full/.springBeans +++ /dev/null @@ -1,18 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - java:org.baeldung.spring.SecurityWithoutCsrfConfig - - - java:org.baeldung.spring.Application - - - - diff --git a/spring-security-rest-full/README.md b/spring-security-rest-full/README.md index 63ca8c7926..1cbe1191a8 100644 --- a/spring-security-rest-full/README.md +++ b/spring-security-rest-full/README.md @@ -2,6 +2,10 @@ ## REST Example Project with Spring Security +### Courses +The "REST With Spring" Classes: http://bit.ly/restwithspring + +The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [Spring Security Expressions - hasRole Example](http://www.baeldung.com/spring-security-expressions-basic) @@ -11,7 +15,16 @@ - [ETags for REST with Spring](http://www.baeldung.com/2013/01/11/etags-for-rest-with-spring/) - [Error Handling for REST with Spring 3](http://www.baeldung.com/2013/01/31/exception-handling-for-rest-with-spring-3-2/) - [Integration Testing with the Maven Cargo plugin](http://www.baeldung.com/2011/10/16/how-to-set-up-integration-testing-with-the-maven-cargo-plugin/) - +- [Introduction to Spring Data JPA](http://www.baeldung.com/2011/12/22/the-persistence-layer-with-spring-data-jpa/) +- [Project Configuration with Spring](http://www.baeldung.com/2012/03/12/project-configuration-with-spring/) +- [REST Query Language with Spring and JPA Criteria](http://www.baeldung.com/rest-search-language-spring-jpa-criteria) +- [REST Query Language with Spring Data JPA Specifications](http://www.baeldung.com/rest-api-search-language-spring-data-specifications) +- [REST Query Language with Spring Data JPA and QueryDSL](http://www.baeldung.com/rest-api-search-language-spring-data-querydsl) +- [REST Query Language – Advanced Search Operations](http://www.baeldung.com/rest-api-query-search-language-more-operations) +- [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics) +- [REST Query Language with RSQL](http://www.baeldung.com/rest-api-search-language-rsql-fiql) +- [Spring RestTemplate Tutorial](http://www.baeldung.com/rest-template) +- [A Guide to CSRF Protection in Spring Security](http://www.baeldung.com/spring-security-csrf) ### Build the Project ``` diff --git a/spring-security-rest-full/pom.xml b/spring-security-rest-full/pom.xml index 270774ee13..77b11f1cb1 100644 --- a/spring-security-rest-full/pom.xml +++ b/spring-security-rest-full/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-security-rest-full 0.1-SNAPSHOT @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.3.2.RELEASE + 1.3.3.RELEASE @@ -248,11 +248,11 @@ test - - org.hamcrest - hamcrest-core - test - + + + + + org.hamcrest hamcrest-library @@ -427,19 +427,19 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 1.8.2.RELEASE 2.0.0 3.6.2 - 2.5.5 + 2.7.2 1.4.01 @@ -462,13 +462,13 @@ 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 - 1.4.15 + 2.19.1 + 1.4.18 1.1.3 diff --git a/spring-security-rest-full/src/main/java/org/baeldung/spring/Application.java b/spring-security-rest-full/src/main/java/org/baeldung/spring/Application.java index 58a6ad02d8..c44e37fee8 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/spring/Application.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/spring/Application.java @@ -2,8 +2,10 @@ package org.baeldung.spring; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.filter.ShallowEtagHeaderFilter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** @@ -20,4 +22,8 @@ public class Application extends WebMvcConfigurerAdapter { SpringApplication.run(Application.class, args); } + @Bean + public ShallowEtagHeaderFilter shallowEtagHeaderFilter() { + return new ShallowEtagHeaderFilter(); + } } \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/spring/ListenerConfig.java b/spring-security-rest-full/src/main/java/org/baeldung/spring/ListenerConfig.java new file mode 100644 index 0000000000..80af01aeeb --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/spring/ListenerConfig.java @@ -0,0 +1,16 @@ +package org.baeldung.spring; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.request.RequestContextListener; + +public class ListenerConfig implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext sc) throws ServletException { + // Manages the lifecycle of the root application context + sc.addListener(new RequestContextListener()); + } +} \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithoutCsrfConfig.java b/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithoutCsrfConfig.java index 6e3974f86d..aeb2428326 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithoutCsrfConfig.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithoutCsrfConfig.java @@ -44,13 +44,16 @@ public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter { http .csrf().disable() .authorizeRequests() - .antMatchers("/admin/*").hasAnyRole("ROLE_ADMIN") - .anyRequest().authenticated() + .antMatchers("/auth/admin/*").hasRole("ADMIN") + .antMatchers("/auth/*").hasAnyRole("ADMIN","USER") + .antMatchers("/*").permitAll() .and() .httpBasic() .and() // .exceptionHandling().accessDeniedPage("/my-error-page") .exceptionHandling().accessDeniedHandler(accessDeniedHandler) + .and() + .headers().cacheControl().disable() ; // @formatter:on } diff --git a/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java b/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java index 143e52d94e..57e9b32a62 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java @@ -1,10 +1,14 @@ package org.baeldung.spring; +import org.baeldung.web.interceptor.LoggerInterceptor; +import org.baeldung.web.interceptor.SessionTimerInterceptor; +import org.baeldung.web.interceptor.UserInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; @@ -12,7 +16,7 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration @ComponentScan("org.baeldung.web") @EnableWebMvc -public class WebConfig extends WebMvcConfigurerAdapter { +public class WebConfig extends WebMvcConfigurerAdapter{ public WebConfig() { super(); @@ -32,6 +36,14 @@ public class WebConfig extends WebMvcConfigurerAdapter { super.addViewControllers(registry); registry.addViewController("/graph.html"); registry.addViewController("/csrfHome.html"); + registry.addViewController("/homepage.html"); } + @Override + public void addInterceptors(final InterceptorRegistry registry) { + registry.addInterceptor(new LoggerInterceptor()); + registry.addInterceptor(new UserInterceptor()); + registry.addInterceptor(new SessionTimerInterceptor()); + } + } \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/BankController.java b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/BankController.java index 1a4322c611..e87d5f3dd4 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/BankController.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/BankController.java @@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; // to test csrf @Controller +@RequestMapping(value = "/auth/") public class BankController { private final Logger logger = LoggerFactory.getLogger(getClass()); diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/FooController.java b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/FooController.java index 20307447b2..c50e80bec2 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/FooController.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/FooController.java @@ -29,7 +29,7 @@ import org.springframework.web.util.UriComponentsBuilder; import com.google.common.base.Preconditions; @Controller -@RequestMapping(value = "/foos") +@RequestMapping(value = "/auth/foos") public class FooController { @Autowired diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/HomeController.java b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/HomeController.java new file mode 100644 index 0000000000..9c4d14cae3 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/HomeController.java @@ -0,0 +1,14 @@ +package org.baeldung.web.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping(value = "/") +public class HomeController { + + public String index() { + return "homepage"; + } + +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/RootController.java b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/RootController.java index e83b8cf5ba..8b63275b66 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/RootController.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/RootController.java @@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.util.UriTemplate; @Controller +@RequestMapping(value = "/auth/") public class RootController { @Autowired 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 7c28ed8e80..cf46e35e57 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 @@ -37,6 +37,7 @@ import cz.jirutka.rsql.parser.ast.Node; //@EnableSpringDataWebSupport @Controller +@RequestMapping(value = "/auth/") public class UserController { @Autowired diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/LoggerInterceptor.java b/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/LoggerInterceptor.java new file mode 100644 index 0000000000..7c68d3e9c7 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/LoggerInterceptor.java @@ -0,0 +1,76 @@ +package org.baeldung.web.interceptor; + +import com.google.common.base.Strings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Enumeration; + +public class LoggerInterceptor extends HandlerInterceptorAdapter { + + private static Logger log = LoggerFactory.getLogger(LoggerInterceptor.class); + + /** + * Executed before actual handler is executed + **/ + @Override + public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception { + log.info("[preHandle][" + request + "]" + "[" + request.getMethod() + "]" + request.getRequestURI() + getParameters(request)); + return true; + } + + /** + * Executed before after handler is executed + **/ + @Override + public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final ModelAndView modelAndView) throws Exception { + log.info("[postHandle][" + request + "]"); + } + + /** + * Executed after complete request is finished + **/ + @Override + public void afterCompletion(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final Exception ex) throws Exception { + if (ex != null) + ex.printStackTrace(); + log.info("[afterCompletion][" + request + "][exception: " + ex + "]"); + } + + private String getParameters(final HttpServletRequest request) { + final StringBuffer posted = new StringBuffer(); + final Enumeration e = request.getParameterNames(); + if (e != null) + posted.append("?"); + while (e != null && e.hasMoreElements()) { + if (posted.length() > 1) + posted.append("&"); + final String curr = (String) e.nextElement(); + posted.append(curr).append("="); + if (curr.contains("password") || curr.contains("answer") || curr.contains("pwd")) { + posted.append("*****"); + } else { + posted.append(request.getParameter(curr)); + } + } + + final String ip = request.getHeader("X-FORWARDED-FOR"); + final String ipAddr = (ip == null) ? getRemoteAddr(request) : ip; + if (!Strings.isNullOrEmpty(ipAddr)) + posted.append("&_psip=" + ipAddr); + return posted.toString(); + } + + private String getRemoteAddr(final HttpServletRequest request) { + final String ipFromHeader = request.getHeader("X-FORWARDED-FOR"); + if (ipFromHeader != null && ipFromHeader.length() > 0) { + log.debug("ip from proxy - X-FORWARDED-FOR : " + ipFromHeader); + return ipFromHeader; + } + return request.getRemoteAddr(); + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java b/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java new file mode 100644 index 0000000000..f5c1626989 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java @@ -0,0 +1,56 @@ +package org.baeldung.web.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +public class SessionTimerInterceptor extends HandlerInterceptorAdapter { + + private static Logger log = LoggerFactory.getLogger(SessionTimerInterceptor.class); + + private static final long MAX_INACTIVE_SESSION_TIME = 5 * 10000; + + @Autowired + private HttpSession session; + + /** + * Executed before actual handler is executed + **/ + @Override + public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) + throws Exception { + log.info("Pre handle method - check handling start time"); + long startTime = System.currentTimeMillis(); + request.setAttribute("executionTime", startTime); + if (UserInterceptor.isUserLogged()) { + session = request.getSession(); + log.info("Time since last request in this session: {} ms", + System.currentTimeMillis() - request.getSession().getLastAccessedTime()); + if (System.currentTimeMillis() - session.getLastAccessedTime() > MAX_INACTIVE_SESSION_TIME) { + log.warn("Logging out, due to inactive session"); + SecurityContextHolder.clearContext(); + request.logout(); + response.sendRedirect("/spring-security-rest-full/logout"); + } + } + return true; + } + + /** + * Executed before after handler is executed + **/ + @Override + public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler, + final ModelAndView model) throws Exception { + log.info("Post handle method - check execution time of handling"); + long startTime = (Long) request.getAttribute("executionTime"); + log.info("Execution time for handling the request was: {} ms", System.currentTimeMillis() - startTime); + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/UserInterceptor.java b/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/UserInterceptor.java new file mode 100644 index 0000000000..4ba12d0138 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/UserInterceptor.java @@ -0,0 +1,85 @@ +package org.baeldung.web.interceptor; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.SmartView; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +public class UserInterceptor extends HandlerInterceptorAdapter { + + private static Logger log = LoggerFactory.getLogger(UserInterceptor.class); + + /** + * Executed before actual handler is executed + **/ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception { + if (isUserLogged()) { + addToModelUserDetails(request.getSession()); + } + return true; + } + + /** + * Executed before after handler is executed. If view is a redirect view, we don't need to execute postHandle + **/ + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView model) + throws Exception { + if (model != null && !isRedirectView(model)) { + if (isUserLogged()) { + addToModelUserDetails(model); + } + } + } + + /** + * Used before model is generated, based on session + */ + private void addToModelUserDetails(HttpSession session) { + log.info("================= addToModelUserDetails ============================"); + String loggedUsername = SecurityContextHolder.getContext().getAuthentication().getName(); + session.setAttribute("username", loggedUsername); + log.info("user(" + loggedUsername + ") session : " + session); + log.info("================= addToModelUserDetails ============================"); + + } + + /** + * Used when model is available + */ + private void addToModelUserDetails(ModelAndView model) { + log.info("================= addToModelUserDetails ============================"); + String loggedUsername = SecurityContextHolder.getContext().getAuthentication().getName(); + model.addObject("loggedUsername", loggedUsername); + log.trace("session : " + model.getModel()); + log.info("================= addToModelUserDetails ============================"); + + } + + public static boolean isRedirectView(ModelAndView mv) { + + String viewName = mv.getViewName(); + if (viewName.startsWith("redirect:/")) { + return true; + } + + View view = mv.getView(); + return (view != null && view instanceof SmartView && ((SmartView) view).isRedirectView()); + } + + public static boolean isUserLogged() { + try { + return !SecurityContextHolder.getContext().getAuthentication().getName().equals("anonymousUser"); + } catch (Exception e) { + return false; + } + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java b/spring-security-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java index fec03d1ddb..89e3a22d45 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java @@ -17,13 +17,13 @@ public class ActuatorMetricService implements IActuatorMetricService { @Autowired private MetricReaderPublicMetrics publicMetrics; - private final List> statusMetric; + private final List> statusMetricsByMinute; private final List statusList; private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); public ActuatorMetricService() { super(); - statusMetric = new ArrayList>(); + statusMetricsByMinute = new ArrayList>(); statusList = new ArrayList(); } @@ -31,7 +31,7 @@ public class ActuatorMetricService implements IActuatorMetricService { public Object[][] getGraphData() { final Date current = new Date(); final int colCount = statusList.size() + 1; - final int rowCount = statusMetric.size() + 1; + final int rowCount = statusMetricsByMinute.size() + 1; final Object[][] result = new Object[rowCount][colCount]; result[0][0] = "Time"; int j = 1; @@ -41,19 +41,23 @@ public class ActuatorMetricService implements IActuatorMetricService { j++; } - List temp; - List last = new ArrayList(); for (int i = 1; i < rowCount; i++) { - temp = statusMetric.get(i - 1); result[i][0] = dateFormat.format(new Date(current.getTime() - (60000 * (rowCount - i)))); - for (j = 1; j <= temp.size(); j++) { - result[i][j] = temp.get(j - 1) - (last.size() >= j ? last.get(j - 1) : 0); + } + + List minuteOfStatuses; + List last = new ArrayList(); + + for (int i = 1; i < rowCount; i++) { + minuteOfStatuses = statusMetricsByMinute.get(i - 1); + for (j = 1; j <= minuteOfStatuses.size(); j++) { + result[i][j] = minuteOfStatuses.get(j - 1) - (last.size() >= j ? last.get(j - 1) : 0); } while (j < colCount) { result[i][j] = 0; j++; } - last = temp; + last = minuteOfStatuses; } return result; } @@ -62,16 +66,16 @@ public class ActuatorMetricService implements IActuatorMetricService { @Scheduled(fixedDelay = 60000) private void exportMetrics() { - final ArrayList statusCount = initializeCounterList(statusList.size()); + final ArrayList lastMinuteStatuses = initializeStatuses(statusList.size()); for (final Metric counterMetric : publicMetrics.metrics()) { - updateStatusCount(counterMetric, statusCount); + updateMetrics(counterMetric, lastMinuteStatuses); } - statusMetric.add(statusCount); + statusMetricsByMinute.add(lastMinuteStatuses); } - private ArrayList initializeCounterList(final int size) { + private ArrayList initializeStatuses(final int size) { final ArrayList counterList = new ArrayList(); for (int i = 0; i < size; i++) { counterList.add(0); @@ -79,22 +83,26 @@ public class ActuatorMetricService implements IActuatorMetricService { return counterList; } - private void updateStatusCount(final Metric counterMetric, final ArrayList statusCount) { + private void updateMetrics(final Metric counterMetric, final ArrayList statusCount) { String status = ""; int index = -1; int oldCount = 0; if (counterMetric.getName().contains("counter.status.")) { status = counterMetric.getName().substring(15, 18); // example 404, 200 - if (!statusList.contains(status)) { - statusList.add(status); - statusCount.add(0); - } + appendStatusIfNotExist(status, statusCount); index = statusList.indexOf(status); oldCount = statusCount.get(index) == null ? 0 : statusCount.get(index); statusCount.set(index, counterMetric.getValue().intValue() + oldCount); } } + private void appendStatusIfNotExist(final String status, final ArrayList statusCount) { + if (!statusList.contains(status)) { + statusList.add(status); + statusCount.add(0); + } + } + // } \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java b/spring-security-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java index 7df7e199b4..852a9fae99 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java @@ -21,14 +21,14 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService @Autowired private CounterService counter; - private final List> statusMetric; + private final List> statusMetricsByMinute; private final List statusList; private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); public CustomActuatorMetricService() { super(); repo = new InMemoryMetricRepository(); - statusMetric = new ArrayList>(); + statusMetricsByMinute = new ArrayList>(); statusList = new ArrayList(); } @@ -46,7 +46,7 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService public Object[][] getGraphData() { final Date current = new Date(); final int colCount = statusList.size() + 1; - final int rowCount = statusMetric.size() + 1; + final int rowCount = statusMetricsByMinute.size() + 1; final Object[][] result = new Object[rowCount][colCount]; result[0][0] = "Time"; @@ -56,12 +56,15 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService j++; } - List temp; for (int i = 1; i < rowCount; i++) { - temp = statusMetric.get(i - 1); result[i][0] = dateFormat.format(new Date(current.getTime() - (60000 * (rowCount - i)))); - for (j = 1; j <= temp.size(); j++) { - result[i][j] = temp.get(j - 1); + } + + List minuteOfStatuses; + for (int i = 1; i < rowCount; i++) { + minuteOfStatuses = statusMetricsByMinute.get(i - 1); + for (j = 1; j <= minuteOfStatuses.size(); j++) { + result[i][j] = minuteOfStatuses.get(j - 1); } while (j < colCount) { result[i][j] = 0; @@ -87,6 +90,6 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService } } - statusMetric.add(statusCount); + statusMetricsByMinute.add(statusCount); } } \ No newline at end of file diff --git a/spring-security-rest-full/src/main/resources/webSecurityConfig.xml b/spring-security-rest-full/src/main/resources/webSecurityConfig.xml index d6ba952dfd..be6b4d0c27 100644 --- a/spring-security-rest-full/src/main/resources/webSecurityConfig.xml +++ b/spring-security-rest-full/src/main/resources/webSecurityConfig.xml @@ -32,5 +32,9 @@ + + \ No newline at end of file diff --git a/spring-security-rest-full/src/test/java/org/baeldung/TestSuite.java b/spring-security-rest-full/src/test/java/org/baeldung/TestSuite.java new file mode 100644 index 0000000000..52e3607b12 --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/TestSuite.java @@ -0,0 +1,18 @@ +package org.baeldung; + +import org.baeldung.persistence.PersistenceTestSuite; +import org.baeldung.security.SecurityTestSuite; +import org.baeldung.web.LiveTestSuite; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ +// @formatter:off + PersistenceTestSuite.class + ,SecurityTestSuite.class + ,LiveTestSuite.class +}) // +public class TestSuite { + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/client/RestTemplateLiveTest.java b/spring-security-rest-full/src/test/java/org/baeldung/client/RestTemplateLiveTest.java index b6753bdad2..fb40bd9d62 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/client/RestTemplateLiveTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/client/RestTemplateLiveTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -20,8 +21,10 @@ import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.baeldung.persistence.model.Foo; +import org.baeldung.spring.ConfigTest; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -30,6 +33,10 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RequestCallback; import org.springframework.web.client.RestTemplate; @@ -38,10 +45,13 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Charsets; +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { ConfigTest.class }, loader = AnnotationConfigContextLoader.class) +@ActiveProfiles("test") public class RestTemplateLiveTest { private RestTemplate restTemplate; - private static final String fooResourceUrl = "http://localhost:" + APPLICATION_PORT + "/spring-security-rest-full/foos"; + private static final String fooResourceUrl = "http://localhost:" + APPLICATION_PORT + "/foos"; @Before public void beforeTest() { @@ -66,7 +76,7 @@ public class RestTemplateLiveTest { final JsonNode root = mapper.readTree(response.getBody()); final JsonNode name = root.path("name"); - assertThat(name.asText(), is("bar")); + assertNotNull(name); final JsonNode owner = root.path("id"); assertThat(owner.asText(), is("1")); @@ -75,7 +85,7 @@ public class RestTemplateLiveTest { @Test public void givenResourceUrl_whenSendGetForObject_thenReturnsRepoObject() { final Foo foo = restTemplate.getForObject(fooResourceUrl + "/1", Foo.class); - assertThat(foo.getName(), is("bar")); + assertNotNull(foo.getName()); assertThat(foo.getId(), is(1L)); } diff --git a/spring-security-rest-full/src/test/java/org/baeldung/common/web/AbstractLiveTest.java b/spring-security-rest-full/src/test/java/org/baeldung/common/web/AbstractLiveTest.java index 32a736b546..95fce10e45 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/common/web/AbstractLiveTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/common/web/AbstractLiveTest.java @@ -1,16 +1,17 @@ package org.baeldung.common.web; +import static org.baeldung.Consts.APPLICATION_PORT; + +import java.io.Serializable; + +import org.baeldung.test.IMarshaller; +import org.springframework.beans.factory.annotation.Autowired; + import com.google.common.base.Preconditions; import com.google.common.net.HttpHeaders; import com.jayway.restassured.RestAssured; import com.jayway.restassured.response.Response; import com.jayway.restassured.specification.RequestSpecification; -import org.baeldung.test.IMarshaller; -import org.springframework.beans.factory.annotation.Autowired; - -import java.io.Serializable; - -import static org.baeldung.Consts.APPLICATION_PORT; public abstract class AbstractLiveTest { @@ -56,7 +57,7 @@ public abstract class AbstractLiveTest { // protected String getURL() { - return "http://localhost:" + APPLICATION_PORT + "/spring-security-rest-full/foos"; + return "http://localhost:" + APPLICATION_PORT + "/foos"; } protected final RequestSpecification givenAuth() { diff --git a/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfDisabledIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfDisabledIntegrationTest.java deleted file mode 100644 index d223e89fe0..0000000000 --- a/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfDisabledIntegrationTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.baeldung.csrf; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import org.baeldung.spring.PersistenceConfig; -import org.baeldung.spring.SecurityWithoutCsrfConfig; -import org.baeldung.spring.WebConfig; -import org.junit.Test; -import org.springframework.http.MediaType; -import org.springframework.test.context.ContextConfiguration; - -@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) -public class CsrfDisabledIntegrationTest extends CsrfAbstractIntegrationTest { - - @Test - public void givenNotAuth_whenAddFoo_thenUnauthorized() throws Exception { - mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo())).andExpect(status().isUnauthorized()); - } - - @Test - public void givenAuth_whenAddFoo_thenCreated() throws Exception { - mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isCreated()); - } - -} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfEnabledIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfEnabledIntegrationTest.java deleted file mode 100644 index fe6580bd05..0000000000 --- a/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfEnabledIntegrationTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.baeldung.csrf; - -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import org.baeldung.spring.PersistenceConfig; -import org.baeldung.spring.SecurityWithCsrfConfig; -import org.baeldung.spring.WebConfig; -import org.junit.Test; -import org.springframework.http.MediaType; -import org.springframework.test.context.ContextConfiguration; - -@ContextConfiguration(classes = { SecurityWithCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) -public class CsrfEnabledIntegrationTest extends CsrfAbstractIntegrationTest { - - @Test - public void givenNoCsrf_whenAddFoo_thenForbidden() throws Exception { - mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isForbidden()); - } - - @Test - public void givenCsrf_whenAddFoo_thenCreated() throws Exception { - mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser()).with(csrf())).andExpect(status().isCreated()); - } - -} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/PersistenceTestSuite.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/PersistenceTestSuite.java new file mode 100644 index 0000000000..0ce8c0300b --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/PersistenceTestSuite.java @@ -0,0 +1,22 @@ +package org.baeldung.persistence; + +import org.baeldung.persistence.query.JPACriteriaQueryTest; +import org.baeldung.persistence.query.JPAQuerydslTest; +import org.baeldung.persistence.query.JPASpecificationTest; +import org.baeldung.persistence.query.RsqlTest; +import org.baeldung.persistence.service.FooServicePersistenceIntegrationTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + // @formatter:off + RsqlTest.class + ,JPASpecificationTest.class + ,FooServicePersistenceIntegrationTest.class + ,JPAQuerydslTest.class + ,JPACriteriaQueryTest.class +}) // +public class PersistenceTestSuite { + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPACriteriaQueryTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPACriteriaQueryTest.java index b805263cf7..f9f9435d75 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPACriteriaQueryTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPACriteriaQueryTest.java @@ -15,15 +15,15 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { PersistenceConfig.class }) @Transactional -@TransactionConfiguration +@Rollback public class JPACriteriaQueryTest { @Autowired diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPAQuerydslTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPAQuerydslTest.java index 5afd69b8be..b7b38a4fcb 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPAQuerydslTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPAQuerydslTest.java @@ -14,15 +14,15 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { PersistenceConfig.class }) @Transactional -@TransactionConfiguration +@Rollback public class JPAQuerydslTest { @Autowired 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 cd51250cb6..544161dfd5 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 @@ -32,7 +32,7 @@ public class JPASpecificationLiveTest { private User userTom; - private final String URL_PREFIX = "http://localhost:8080/spring-security-rest-full/users/spec?search="; + private final String URL_PREFIX = "http://localhost:8080/users/spec?search="; @Before public void init() { diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationTest.java index 0b8daa5a12..97b2274cf9 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationTest.java @@ -17,15 +17,15 @@ 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.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { PersistenceConfig.class }) @Transactional -@TransactionConfiguration +@Rollback public class JPASpecificationTest { @Autowired diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/RsqlTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/RsqlTest.java index 0b02f533e8..e0deb8d4ec 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/RsqlTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/RsqlTest.java @@ -15,9 +15,9 @@ 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.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.transaction.annotation.Transactional; import cz.jirutka.rsql.parser.RSQLParser; @@ -26,7 +26,7 @@ import cz.jirutka.rsql.parser.ast.Node; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { PersistenceConfig.class }) @Transactional -@TransactionConfiguration +@Rollback public class RsqlTest { @Autowired diff --git a/spring-security-rest-full/src/test/java/org/baeldung/security/SecurityTestSuite.java b/spring-security-rest-full/src/test/java/org/baeldung/security/SecurityTestSuite.java new file mode 100644 index 0000000000..8b754a03ff --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/security/SecurityTestSuite.java @@ -0,0 +1,16 @@ +package org.baeldung.security; + +import org.baeldung.security.csrf.CsrfDisabledIntegrationTest; +import org.baeldung.security.csrf.CsrfEnabledIntegrationTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + // @formatter:off + CsrfEnabledIntegrationTest.class + ,CsrfDisabledIntegrationTest.class +}) // +public class SecurityTestSuite { + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfAbstractIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfAbstractIntegrationTest.java similarity index 86% rename from spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfAbstractIntegrationTest.java rename to spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfAbstractIntegrationTest.java index a94dd554f1..13cb92a745 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfAbstractIntegrationTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfAbstractIntegrationTest.java @@ -1,4 +1,4 @@ -package org.baeldung.csrf; +package org.baeldung.security.csrf; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; @@ -14,6 +14,7 @@ import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.RequestPostProcessor; import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.WebApplicationContext; import com.fasterxml.jackson.core.JsonProcessingException; @@ -21,6 +22,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration +@Transactional public class CsrfAbstractIntegrationTest { @Autowired @@ -42,6 +44,10 @@ public class CsrfAbstractIntegrationTest { return user("user").password("userPass").roles("USER"); } + protected RequestPostProcessor testAdmin() { + return user("admin").password("adminPass").roles("USER", "ADMIN"); + } + protected String createFoo() throws JsonProcessingException { return new ObjectMapper().writeValueAsString(new Foo(randomAlphabetic(6))); } diff --git a/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java new file mode 100644 index 0000000000..63efd870cd --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfDisabledIntegrationTest.java @@ -0,0 +1,44 @@ +package org.baeldung.security.csrf; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.baeldung.spring.PersistenceConfig; +import org.baeldung.spring.SecurityWithoutCsrfConfig; +import org.baeldung.spring.WebConfig; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +public class CsrfDisabledIntegrationTest extends CsrfAbstractIntegrationTest { + + @Test + public void givenNotAuth_whenAddFoo_thenUnauthorized() throws Exception { + mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo())).andExpect(status().isUnauthorized()); + } + + @Test + public void givenAuth_whenAddFoo_thenCreated() throws Exception { + mvc.perform(post("/auth/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isCreated()); + } + + @Test + public void accessMainPageWithoutAuthorization() throws Exception { + mvc.perform(get("/graph.html").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); + } + + @Test + public void accessOtherPages() throws Exception { + mvc.perform(get("/auth/transfer").contentType(MediaType.APPLICATION_JSON).param("accountNo", "1").param("amount", "100")).andExpect(status().isUnauthorized()); // without authorization + mvc.perform(get("/auth/transfer").contentType(MediaType.APPLICATION_JSON).param("accountNo", "1").param("amount", "100").with(testUser())).andExpect(status().isOk()); // with authorization + } + + @Test + public void accessAdminPage() throws Exception { + mvc.perform(get("/auth/admin/x").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isUnauthorized()); // without authorization + mvc.perform(get("/auth/admin/x").contentType(MediaType.APPLICATION_JSON).with(testAdmin())).andExpect(status().isOk()); // with authorization + } + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java new file mode 100644 index 0000000000..c7caf61525 --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java @@ -0,0 +1,26 @@ +package org.baeldung.security.csrf; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.baeldung.spring.PersistenceConfig; +import org.baeldung.spring.WebConfig; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = { SecurityWithCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +public class CsrfEnabledIntegrationTest extends CsrfAbstractIntegrationTest { + + @Test + public void givenNoCsrf_whenAddFoo_thenForbidden() throws Exception { + mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isForbidden()); + } + + @Test + public void givenCsrf_whenAddFoo_thenCreated() throws Exception { + mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser()).with(csrf())).andExpect(status().isCreated()); + } + +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithCsrfConfig.java b/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/SecurityWithCsrfConfig.java similarity index 90% rename from spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithCsrfConfig.java rename to spring-security-rest-full/src/test/java/org/baeldung/security/csrf/SecurityWithCsrfConfig.java index c2a21c3f9e..99b94cd7b5 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithCsrfConfig.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/security/csrf/SecurityWithCsrfConfig.java @@ -1,4 +1,4 @@ -package org.baeldung.spring; +package org.baeldung.security.csrf; import org.baeldung.web.error.CustomAccessDeniedHandler; import org.springframework.beans.factory.annotation.Autowired; @@ -11,10 +11,10 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -// @Configuration -// @EnableAutoConfiguration -// @EnableWebSecurity -// @EnableGlobalMethodSecurity(prePostEnabled = true) +@Configuration +@EnableAutoConfiguration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityWithCsrfConfig extends WebSecurityConfigurerAdapter { @Autowired @@ -47,6 +47,8 @@ public class SecurityWithCsrfConfig extends WebSecurityConfigurerAdapter { .httpBasic() .and() .exceptionHandling().accessDeniedHandler(accessDeniedHandler) + .and() + .headers().cacheControl().disable() ; // @formatter:on } diff --git a/spring-security-rest-full/src/test/java/org/baeldung/web/LiveTestSuite.java b/spring-security-rest-full/src/test/java/org/baeldung/web/LiveTestSuite.java new file mode 100644 index 0000000000..4c26350151 --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/web/LiveTestSuite.java @@ -0,0 +1,19 @@ +package org.baeldung.web; + +import org.baeldung.client.RestTemplateLiveTest; +import org.baeldung.persistence.query.JPASpecificationLiveTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ +// @formatter:off + JPASpecificationLiveTest.class + ,FooDiscoverabilityLiveTest.class + ,FooLiveTest.class + ,MyUserLiveTest.class + ,RestTemplateLiveTest.class +}) // +public class LiveTestSuite { + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/web/MyUserLiveTest.java b/spring-security-rest-full/src/test/java/org/baeldung/web/MyUserLiveTest.java index ea5f609677..835b32c95c 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/web/MyUserLiveTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/web/MyUserLiveTest.java @@ -3,14 +3,15 @@ package org.baeldung.web; import static org.junit.Assert.assertEquals; import org.baeldung.persistence.model.MyUser; -import org.baeldung.spring.Application; +import org.baeldung.spring.ConfigTest; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.context.support.AnnotationConfigContextLoader; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -19,8 +20,8 @@ import com.jayway.restassured.response.Response; import com.jayway.restassured.specification.RequestSpecification; @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = Application.class) -@WebAppConfiguration +@ContextConfiguration(classes = { ConfigTest.class }, loader = AnnotationConfigContextLoader.class) +@ActiveProfiles("test") public class MyUserLiveTest { private ObjectMapper mapper = new ObjectMapper(); diff --git a/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/LoggerInterceptorTest.java b/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/LoggerInterceptorTest.java new file mode 100644 index 0000000000..930ab20262 --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/LoggerInterceptorTest.java @@ -0,0 +1,51 @@ +package org.baeldung.web.interceptor; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.baeldung.spring.PersistenceConfig; +import org.baeldung.spring.SecurityWithoutCsrfConfig; +import org.baeldung.spring.WebConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@Transactional +@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +public class LoggerInterceptorTest { + + @Autowired + WebApplicationContext wac; + @Autowired + MockHttpSession session; + + private MockMvc mockMvc; + + @Before + public void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + } + + /** + * After execution of HTTP GET logs from interceptor will be displayed in + * the console + * + * @throws Exception + */ + @Test + public void testInterceptors() throws Exception { + mockMvc.perform(get("/graph.html")).andExpect(status().isOk()); + } + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorTest.java b/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorTest.java new file mode 100644 index 0000000000..a29de04bb4 --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorTest.java @@ -0,0 +1,56 @@ +package org.baeldung.web.interceptor; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import javax.servlet.http.HttpSession; + +import org.baeldung.spring.PersistenceConfig; +import org.baeldung.spring.SecurityWithoutCsrfConfig; +import org.baeldung.spring.WebConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@Transactional +@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +@WithMockUser(username = "admin", roles = { "USER", "ADMIN" }) +public class SessionTimerInterceptorTest { + + @Autowired + WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + } + + /** + * After execution of HTTP GET logs from interceptor will be displayed in + * the console + */ + @Test + public void testInterceptors() throws Exception { + HttpSession session = mockMvc.perform(get("/auth/admin")).andExpect(status().is2xxSuccessful()).andReturn() + .getRequest().getSession(); + Thread.sleep(51000); + mockMvc.perform(get("/auth/admin").session((MockHttpSession) session)).andExpect(status().is2xxSuccessful()); + } + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/UserInterceptorTest.java b/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/UserInterceptorTest.java new file mode 100644 index 0000000000..0b65311203 --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/UserInterceptorTest.java @@ -0,0 +1,53 @@ +package org.baeldung.web.interceptor; + +import org.baeldung.spring.PersistenceConfig; +import org.baeldung.spring.SecurityWithoutCsrfConfig; +import org.baeldung.spring.WebConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@Transactional +@ContextConfiguration(classes = {SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class}) +@WithMockUser(username = "admin", roles = {"USER", "ADMIN"}) +public class UserInterceptorTest { + + @Autowired + WebApplicationContext wac; + + @Autowired + MockHttpSession session; + + private MockMvc mockMvc; + + @Before + public void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + } + + /** + * After execution of HTTP GET logs from interceptor will be displayed in + * the console + */ + @Test + public void testInterceptors() throws Exception { + mockMvc.perform(get("/auth/admin")) + .andExpect(status().is2xxSuccessful()); + } + +} diff --git a/spring-security-rest/.classpath b/spring-security-rest/.classpath deleted file mode 100644 index 5778c9435e..0000000000 --- a/spring-security-rest/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-security-rest/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch b/spring-security-rest/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch deleted file mode 100644 index 627021fb96..0000000000 --- a/spring-security-rest/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/spring-security-rest/.project b/spring-security-rest/.project deleted file mode 100644 index 9ce15c3fa8..0000000000 --- a/spring-security-rest/.project +++ /dev/null @@ -1,48 +0,0 @@ - - - spring-security-rest - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.springframework.ide.eclipse.core.springnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-security-rest/.settings/.jsdtscope b/spring-security-rest/.settings/.jsdtscope deleted file mode 100644 index facca273ec..0000000000 --- a/spring-security-rest/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-security-rest/.settings/org.eclipse.jdt.core.prefs b/spring-security-rest/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index fb671a82a6..0000000000 --- a/spring-security-rest/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,95 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore -org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/spring-security-rest/.settings/org.eclipse.jdt.ui.prefs b/spring-security-rest/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 471e9b0d81..0000000000 --- a/spring-security-rest/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,55 +0,0 @@ -#Sat Jan 21 23:04:06 EET 2012 -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=true -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_to_enhanced_for_loop=true -sp_cleanup.correct_indentation=true -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=true -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=true -sp_cleanup.make_private_fields_final=false -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=true -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=false -sp_cleanup.on_save_use_additional_actions=true -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=true -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_trailing_whitespaces=true -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=true -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=true -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=true -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true diff --git a/spring-security-rest/.settings/org.eclipse.m2e.core.prefs b/spring-security-rest/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb..0000000000 --- a/spring-security-rest/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/spring-security-rest/.settings/org.eclipse.m2e.wtp.prefs b/spring-security-rest/.settings/org.eclipse.m2e.wtp.prefs deleted file mode 100644 index ef86089622..0000000000 --- a/spring-security-rest/.settings/org.eclipse.m2e.wtp.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.m2e.wtp.enabledProjectSpecificPrefs=false diff --git a/spring-security-rest/.settings/org.eclipse.wst.common.component b/spring-security-rest/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 6782a0c5c7..0000000000 --- a/spring-security-rest/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/spring-security-rest/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-security-rest/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 9b82a337c7..0000000000 --- a/spring-security-rest/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/spring-security-rest/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spring-security-rest/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a480..0000000000 --- a/spring-security-rest/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/spring-security-rest/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spring-security-rest/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6ec..0000000000 --- a/spring-security-rest/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/spring-security-rest/.settings/org.eclipse.wst.validation.prefs b/spring-security-rest/.settings/org.eclipse.wst.validation.prefs deleted file mode 100644 index 0d0aee4f72..0000000000 --- a/spring-security-rest/.settings/org.eclipse.wst.validation.prefs +++ /dev/null @@ -1,15 +0,0 @@ -DELEGATES_PREFERENCE=delegateValidatorList -USER_BUILD_PREFERENCE=enabledBuildValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_MANUAL_PREFERENCE=enabledManualValidatorListorg.eclipse.jst.j2ee.internal.classpathdep.ClasspathDependencyValidator; -USER_PREFERENCE=overrideGlobalPreferencestruedisableAllValidationfalseversion1.2.402.v201212031633 -disabled=06target -eclipse.preferences.version=1 -override=true -suspend=false -vals/org.eclipse.jst.jsf.ui.JSFAppConfigValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPBatchValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.JSPContentValidator/global=FF01 -vals/org.eclipse.jst.jsp.core.TLDValidator/global=FF01 -vals/org.eclipse.wst.dtd.core.dtdDTDValidator/global=FF01 -vals/org.eclipse.wst.jsdt.web.core.JsBatchValidator/global=TF02 -vf.version=3 diff --git a/spring-security-rest/.settings/org.eclipse.wst.ws.service.policy.prefs b/spring-security-rest/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index 9cfcabe16f..0000000000 --- a/spring-security-rest/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/spring-security-rest/.springBeans b/spring-security-rest/.springBeans deleted file mode 100644 index d11fb034bd..0000000000 --- a/spring-security-rest/.springBeans +++ /dev/null @@ -1,14 +0,0 @@ - - - 1 - - - - - - - src/main/webapp/WEB-INF/api-servlet.xml - - - - diff --git a/spring-security-rest/README.md b/spring-security-rest/README.md index a3fce32a9c..bea417a800 100644 --- a/spring-security-rest/README.md +++ b/spring-security-rest/README.md @@ -2,6 +2,13 @@ ## Spring Security for REST Example Project +### Courses +The "REST With Spring" Classes: http://bit.ly/restwithspring + +The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [Spring REST Service Security](http://www.baeldung.com/2011/10/31/securing-a-restful-web-service-with-spring-security-3-1-part-3/) +- [Setting Up Swagger 2 with a Spring REST API](http://www.baeldung.com/swagger-2-documentation-for-spring-rest-api) +- [Custom Error Message Handling for REST API](http://www.baeldung.com/global-error-handler-in-a-spring-rest-api) +- [An Intro to Spring HATEOAS](http://www.baeldung.com/spring-hateoas-tutorial) diff --git a/spring-security-rest/pom.xml b/spring-security-rest/pom.xml index 265da0bbcd..6d492863b4 100644 --- a/spring-security-rest/pom.xml +++ b/spring-security-rest/pom.xml @@ -1,6 +1,7 @@ - + 4.0.0 - org.baeldung + com.baeldung spring-security-rest 0.1-SNAPSHOT @@ -77,6 +78,13 @@ ${org.springframework.version} + + + org.springframework.hateoas + spring-hateoas + ${org.springframework.hateoas.version} + + @@ -92,13 +100,13 @@ ${jstl.version} runtime - + - javax.validation - validation-api - ${javax.validation.version} - - + javax.validation + validation-api + ${javax.validation.version} + + @@ -152,14 +160,15 @@ ${org.springframework.version} test - + - org.springframework.security - spring-security-test - ${org.springframework.security.version} - - - + org.springframework.security + spring-security-test + ${org.springframework.security.version} + test + + + com.jayway.restassured rest-assured @@ -172,7 +181,7 @@ - + junit junit @@ -204,13 +213,13 @@ io.springfox springfox-swagger2 - ${springfox.version} + ${springfox-swagger.version} io.springfox springfox-swagger-ui - ${springfox.version} + ${springfox-swagger.version} @@ -261,7 +270,6 @@ cargo-maven2-plugin ${cargo-maven2-plugin.version} - true jetty8x embedded @@ -283,12 +291,13 @@ - 4.2.4.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE + 0.19.0.RELEASE 4.3.11.Final - 5.1.37 + 5.1.38 1.7.13 @@ -300,8 +309,7 @@ 1.1.0.Final 1.2 2.2.2 - 2.2.2 - + 19.0 3.4 @@ -310,23 +318,22 @@ 1.3 4.12 1.10.19 - 2.4.1 + 2.9.0 - 2.2.2 - 2.2.2 + 2.4.0 4.4.1 4.5 - 2.4.1 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.18.1 - 1.4.15 + 2.19.1 + 1.4.18 - \ No newline at end of file + diff --git a/spring-security-rest/src/main/java/org/baeldung/persistence/model/Customer.java b/spring-security-rest/src/main/java/org/baeldung/persistence/model/Customer.java new file mode 100644 index 0000000000..b302ec057a --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/persistence/model/Customer.java @@ -0,0 +1,60 @@ +package org.baeldung.persistence.model; + +import java.util.Map; + +import org.springframework.hateoas.ResourceSupport; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +@JsonInclude(Include.NON_NULL) +public class Customer extends ResourceSupport { + private String customerId; + private String customerName; + private String companyName; + private Map orders; + + public Customer() { + super(); + } + + public Customer(final String customerId, final String customerName, final String companyName) { + super(); + this.customerId = customerId; + this.customerName = customerName; + this.companyName = companyName; + } + + public String getCustomerId() { + return customerId; + } + + public void setCustomerId(final String customerId) { + this.customerId = customerId; + } + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(final String customerName) { + this.customerName = customerName; + } + + public String getCompanyName() { + return companyName; + } + + public void setCompanyName(final String companyName) { + this.companyName = companyName; + } + + public Map getOrders() { + return orders; + } + + public void setOrders(final Map orders) { + this.orders = orders; + } + +} diff --git a/spring-security-rest/src/main/java/org/baeldung/persistence/model/Order.java b/spring-security-rest/src/main/java/org/baeldung/persistence/model/Order.java new file mode 100644 index 0000000000..ca551423e8 --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/persistence/model/Order.java @@ -0,0 +1,50 @@ +package org.baeldung.persistence.model; + +import org.springframework.hateoas.ResourceSupport; + +public class Order extends ResourceSupport { + private String orderId; + private double price; + private int quantity; + + public Order() { + super(); + } + + public Order(final String orderId, final double price, final int quantity) { + super(); + this.orderId = orderId; + this.price = price; + this.quantity = quantity; + } + + public String getOrderId() { + return orderId; + } + + public void setOrderId(final String orderId) { + this.orderId = orderId; + } + + public double getPrice() { + return price; + } + + public void setPrice(final double price) { + this.price = price; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(final int quantity) { + this.quantity = quantity; + } + + @Override + public String toString() { + return "Order [orderId=" + orderId + ", price=" + price + ", quantity=" + quantity + "]"; + } + +} \ No newline at end of file diff --git a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java index 9abe604def..3302482f48 100644 --- a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java +++ b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java @@ -43,7 +43,8 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { .and() .authorizeRequests() .antMatchers("/api/csrfAttacker*").permitAll() - .antMatchers("/api/**").authenticated() + .antMatchers("/api/customer/**").permitAll() + .antMatchers("/api/foos/**").authenticated() .and() .formLogin() .successHandler(authenticationSuccessHandler) diff --git a/spring-security-rest/src/main/java/org/baeldung/web/controller/CustomerController.java b/spring-security-rest/src/main/java/org/baeldung/web/controller/CustomerController.java new file mode 100644 index 0000000000..532e6b4d3a --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/web/controller/CustomerController.java @@ -0,0 +1,65 @@ +package org.baeldung.web.controller; + +import org.baeldung.persistence.model.Customer; +import org.baeldung.persistence.model.Order; +import org.baeldung.web.service.CustomerService; +import org.baeldung.web.service.OrderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.hateoas.Link; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; +import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn; + +@RestController +@RequestMapping(value = "/customers") +public class CustomerController { + @Autowired + private CustomerService customerService; + + @Autowired + private OrderService orderService; + + @RequestMapping(value = "/{customerId}", method = RequestMethod.GET) + public Customer getCustomerById(@PathVariable final String customerId) { + return customerService.getCustomerDetail(customerId); + } + + @RequestMapping(value = "/{customerId}/{orderId}", method = RequestMethod.GET) + public Order getOrderById(@PathVariable final String customerId, @PathVariable final String orderId) { + return orderService.getOrderByIdForCustomer(customerId, orderId); + } + + @RequestMapping(value = "/{customerId}/orders", method = RequestMethod.GET) + public List getOrdersForCustomer(@PathVariable final String customerId) { + final List orders = orderService.getAllOrdersForCustomer(customerId); + for (final Order order : orders) { + final Link selfLink = linkTo(methodOn(CustomerController.class).getOrderById(customerId, order.getOrderId())).withSelfRel(); + order.add(selfLink); + } + return orders; + } + + @RequestMapping(method = RequestMethod.GET) + public List getAllCustomers() { + final List allCustomers = customerService.allCustomers(); + for (final Customer customer : allCustomers) { + String customerId = customer.getCustomerId(); + Link selfLink = linkTo(CustomerController.class).slash(customerId).withSelfRel(); + customer.add(selfLink); + if (orderService.getAllOrdersForCustomer(customerId).size() > 0) { + List methodLinkBuilder = methodOn(CustomerController.class).getOrdersForCustomer(customerId); + final Link ordersLink = linkTo(methodLinkBuilder).withRel("allOrders"); + customer.add(ordersLink); + } + + } + return allCustomers; + } + +} diff --git a/spring-security-rest/src/main/java/org/baeldung/web/service/CustomerService.java b/spring-security-rest/src/main/java/org/baeldung/web/service/CustomerService.java new file mode 100644 index 0000000000..da016af2d5 --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/web/service/CustomerService.java @@ -0,0 +1,13 @@ +package org.baeldung.web.service; + +import java.util.List; + +import org.baeldung.persistence.model.Customer; + +public interface CustomerService { + + List allCustomers(); + + Customer getCustomerDetail(final String id); + +} diff --git a/spring-security-rest/src/main/java/org/baeldung/web/service/CustomerServiceImpl.java b/spring-security-rest/src/main/java/org/baeldung/web/service/CustomerServiceImpl.java new file mode 100644 index 0000000000..e179de2554 --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/web/service/CustomerServiceImpl.java @@ -0,0 +1,39 @@ +package org.baeldung.web.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.baeldung.persistence.model.Customer; +import org.springframework.stereotype.Service; + +@Service +public class CustomerServiceImpl implements CustomerService { + + private HashMap customerMap; + + public CustomerServiceImpl() { + + customerMap = new HashMap<>(); + + final Customer customerOne = new Customer("10A", "Jane", "ABC Company"); + final Customer customerTwo = new Customer("20B", "Bob", "XYZ Company"); + final Customer customerThree = new Customer("30C", "Tim", "CKV Company"); + + customerMap.put("10A", customerOne); + customerMap.put("20B", customerTwo); + customerMap.put("30C", customerThree); + + } + + @Override + public List allCustomers() { + return new ArrayList<>(customerMap.values()); + } + + @Override + public Customer getCustomerDetail(final String customerId) { + return customerMap.get(customerId); + } + +} diff --git a/spring-security-rest/src/main/java/org/baeldung/web/service/OrderService.java b/spring-security-rest/src/main/java/org/baeldung/web/service/OrderService.java new file mode 100644 index 0000000000..9a23488c50 --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/web/service/OrderService.java @@ -0,0 +1,13 @@ +package org.baeldung.web.service; + +import java.util.List; + +import org.baeldung.persistence.model.Order; + +public interface OrderService { + + List getAllOrdersForCustomer(String customerId); + + Order getOrderByIdForCustomer(String customerId, String orderId); + +} diff --git a/spring-security-rest/src/main/java/org/baeldung/web/service/OrderServiceImpl.java b/spring-security-rest/src/main/java/org/baeldung/web/service/OrderServiceImpl.java new file mode 100644 index 0000000000..1b8e7b0dde --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/web/service/OrderServiceImpl.java @@ -0,0 +1,64 @@ +package org.baeldung.web.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.baeldung.persistence.model.Customer; +import org.baeldung.persistence.model.Order; +import org.springframework.stereotype.Service; + +@Service +public class OrderServiceImpl implements OrderService { + + private HashMap customerMap; + private HashMap customerOneOrderMap; + private HashMap customerTwoOrderMap; + private HashMap customerThreeOrderMap; + + public OrderServiceImpl() { + + customerMap = new HashMap<>(); + customerOneOrderMap = new HashMap<>(); + customerTwoOrderMap = new HashMap<>(); + customerThreeOrderMap = new HashMap<>(); + + customerOneOrderMap.put("001A", new Order("001A", 150.00, 25)); + customerOneOrderMap.put("002A", new Order("002A", 250.00, 15)); + + customerTwoOrderMap.put("002B", new Order("002B", 550.00, 325)); + customerTwoOrderMap.put("002B", new Order("002B", 450.00, 525)); + + final Customer customerOne = new Customer("10A", "Jane", "ABC Company"); + final Customer customerTwo = new Customer("20B", "Bob", "XYZ Company"); + final Customer customerThree = new Customer("30C", "Tim", "CKV Company"); + + customerOne.setOrders(customerOneOrderMap); + customerTwo.setOrders(customerTwoOrderMap); + customerThree.setOrders(customerThreeOrderMap); + customerMap.put("10A", customerOne); + customerMap.put("20B", customerTwo); + customerMap.put("30C", customerThree); + + } + + @Override + public List getAllOrdersForCustomer(final String customerId) { + return new ArrayList<>(customerMap.get(customerId).getOrders().values()); + } + + @Override + public Order getOrderByIdForCustomer(final String customerId, final String orderId) { + + final List orders = (List) customerMap.get(customerId).getOrders().values(); + Order selectedOrder = null; + for (final Order order : orders) { + if (order.getId().equals(orderId)) { + selectedOrder = order; + } + } + return selectedOrder; + + } + +} diff --git a/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java b/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java index 6e03300483..dc3a576b7b 100644 --- a/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java +++ b/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java @@ -11,7 +11,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; import com.jayway.restassured.RestAssured; -import com.jayway.restassured.authentication.FormAuthConfig; import com.jayway.restassured.response.Response; import com.jayway.restassured.specification.RequestSpecification; @@ -19,10 +18,22 @@ import com.jayway.restassured.specification.RequestSpecification; @ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) public class FooLiveTest { private static final String URL_PREFIX = "http://localhost:8080/spring-security-rest"; - private FormAuthConfig formConfig = new FormAuthConfig(URL_PREFIX + "/login", "username", "password"); + // private FormAuthConfig formConfig = new FormAuthConfig(URL_PREFIX + "/login", "temporary", "temporary"); + private String cookie; private RequestSpecification givenAuth() { - return RestAssured.given().auth().form("user", "userPass", formConfig); + // return RestAssured.given().auth().form("user", "userPass", formConfig); + if (cookie == null) + cookie = RestAssured.given().contentType("application/x-www-form-urlencoded").formParam("password", "userPass").formParam("username", "user").post(URL_PREFIX + "/login").getCookie("JSESSIONID"); + return RestAssured.given().cookie("JSESSIONID", cookie); + } + + @Test + public void whenTry_thenOK() { + final Response response = givenAuth().get(URL_PREFIX + "/api/foos"); + assertEquals(200, response.statusCode()); + System.out.println(response.asString()); + } @Test diff --git a/spring-security-rest/src/test/java/org/baeldung/web/SwaggerLiveTest.java b/spring-security-rest/src/test/java/org/baeldung/web/SwaggerLiveTest.java new file mode 100644 index 0000000000..792b3e28ce --- /dev/null +++ b/spring-security-rest/src/test/java/org/baeldung/web/SwaggerLiveTest.java @@ -0,0 +1,20 @@ +package org.baeldung.web; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.response.Response; + +public class SwaggerLiveTest { + private static final String URL_PREFIX = "http://localhost:8080/spring-security-rest/api"; + + @Test + public void whenVerifySpringFoxIsWorking_thenOK() { + final Response response = RestAssured.get(URL_PREFIX + "/v2/api-docs"); + assertEquals(200, response.statusCode()); + System.out.println(response.asString()); + + } +} diff --git a/spring-security-x509/keystore/Makefile b/spring-security-x509/keystore/Makefile new file mode 100644 index 0000000000..5321be9de3 --- /dev/null +++ b/spring-security-x509/keystore/Makefile @@ -0,0 +1,88 @@ +PASSWORD=changeit +KEYSTORE=keystore.jks +HOSTNAME=localhost +CLIENTNAME=cid + +# CN = Common Name +# OU = Organization Unit +# O = Organization Name +# L = Locality Name +# ST = State Name +# C = Country (2-letter Country Code) +# E = Email +DNAME_CA='CN=Baeldung CA,OU=baeldung.com,O=Baeldung,L=SomeCity,ST=SomeState,C=CC' +# For server certificates, the Common Name (CN) must be the hostname +DNAME_HOST='CN=$(HOSTNAME),OU=baeldung.com,O=Baeldung,L=SomeCity,ST=SomeState,C=CC' +DNAME_CLIENT='CN=$(CLIENTNAME),OU=baeldung.com,O=Baeldung,L=SomeCity,ST=SomeState,C=CC' +TRUSTSTORE=truststore.jks + +all: clean create-keystore add-host create-truststore add-client + +create-keystore: + # Generate a certificate authority (CA) + keytool -genkey -alias ca -ext BC=ca:true \ + -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \ + -validity 3650 -dname $(DNAME_CA) \ + -keystore $(KEYSTORE) -storepass $(PASSWORD) + +add-host: + # Generate a host certificate + keytool -genkey -alias $(HOSTNAME) \ + -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \ + -validity 3650 -dname $(DNAME_HOST) \ + -keystore $(KEYSTORE) -storepass $(PASSWORD) + # Generate a host certificate signing request + keytool -certreq -alias $(HOSTNAME) -ext BC=ca:true \ + -keyalg RSA -keysize 4096 -sigalg SHA512withRSA \ + -validity 3650 -file "$(HOSTNAME).csr" \ + -keystore $(KEYSTORE) -storepass $(PASSWORD) + # Generate signed certificate with the certificate authority + keytool -gencert -alias ca \ + -validity 3650 -sigalg SHA512withRSA \ + -infile "$(HOSTNAME).csr" -outfile "$(HOSTNAME).crt" -rfc \ + -keystore $(KEYSTORE) -storepass $(PASSWORD) + # Import signed certificate into the keystore + keytool -import -trustcacerts -alias $(HOSTNAME) \ + -file "$(HOSTNAME).crt" \ + -keystore $(KEYSTORE) -storepass $(PASSWORD) + +export-authority: + # Export certificate authority + keytool -export -alias ca -file ca.crt -rfc \ + -keystore $(KEYSTORE) -storepass $(PASSWORD) + + +create-truststore: export-authority + # Import certificate authority into a new truststore + keytool -import -trustcacerts -noprompt -alias ca -file ca.crt \ + -keystore $(TRUSTSTORE) -storepass $(PASSWORD) + +add-client: + # Generate client certificate + keytool -genkey -alias $(CLIENTNAME) \ + -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \ + -validity 3650 -dname $(DNAME_CLIENT) \ + -keystore $(TRUSTSTORE) -storepass $(PASSWORD) + # Generate a host certificate signing request + keytool -certreq -alias $(CLIENTNAME) -ext BC=ca:true \ + -keyalg RSA -keysize 4096 -sigalg SHA512withRSA \ + -validity 3650 -file "$(CLIENTNAME).csr" \ + -keystore $(TRUSTSTORE) -storepass $(PASSWORD) + # Generate signed certificate with the certificate authority + keytool -gencert -alias ca \ + -validity 3650 -sigalg SHA512withRSA \ + -infile "$(CLIENTNAME).csr" -outfile "$(CLIENTNAME).crt" -rfc \ + -keystore $(KEYSTORE) -storepass $(PASSWORD) + # Import signed certificate into the truststore + keytool -import -trustcacerts -alias $(CLIENTNAME) \ + -file "$(CLIENTNAME).crt" \ + -keystore $(TRUSTSTORE) -storepass $(PASSWORD) + # Export private certificate for importing into a browser + keytool -importkeystore -srcalias $(CLIENTNAME) \ + -srckeystore $(TRUSTSTORE) -srcstorepass $(PASSWORD) \ + -destkeystore "$(CLIENTNAME).p12" -deststorepass $(PASSWORD) \ + -deststoretype PKCS12 + +clean: + # Remove generated artifacts + find . ! -name Makefile -type f -exec rm -f {} \; diff --git a/spring-security-x509/keystore/keystore.jks b/spring-security-x509/keystore/keystore.jks new file mode 100644 index 0000000000..044a820c39 Binary files /dev/null and b/spring-security-x509/keystore/keystore.jks differ diff --git a/spring-security-x509/pom.xml b/spring-security-x509/pom.xml new file mode 100644 index 0000000000..953af761b5 --- /dev/null +++ b/spring-security-x509/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + com.baeldung + spring-security-x509 + 0.0.1-SNAPSHOT + pom + + + spring-security-x509-basic-auth + spring-security-x509-client-auth + + + + org.springframework.boot + spring-boot-starter-parent + 1.4.0.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/spring-security-x509/spring-security-x509-basic-auth/pom.xml b/spring-security-x509/spring-security-x509-basic-auth/pom.xml new file mode 100644 index 0000000000..87fdd64727 --- /dev/null +++ b/spring-security-x509/spring-security-x509-basic-auth/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + basic-secured-server + 0.0.1-SNAPSHOT + jar + + basic-secured-server + Spring x.509 Authentication Demo + + + com.baeldung + spring-security-x509 + 0.0.1-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-security-x509/spring-security-x509-basic-auth/src/main/java/com/baeldung/spring/security/x509/UserController.java b/spring-security-x509/spring-security-x509-basic-auth/src/main/java/com/baeldung/spring/security/x509/UserController.java new file mode 100644 index 0000000000..d4616dd5a6 --- /dev/null +++ b/spring-security-x509/spring-security-x509-basic-auth/src/main/java/com/baeldung/spring/security/x509/UserController.java @@ -0,0 +1,21 @@ +package com.baeldung.spring.security.x509; + +import java.security.Principal; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class UserController { + @PreAuthorize("hasAuthority('ROLE_USER')") + @RequestMapping(value = "/user") + public String user(Model model, Principal principal) { + UserDetails currentUser = (UserDetails) ((Authentication) principal).getPrincipal(); + model.addAttribute("username", currentUser.getUsername()); + return "user"; + } +} diff --git a/spring-security-x509/spring-security-x509-basic-auth/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java b/spring-security-x509/spring-security-x509-basic-auth/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java new file mode 100644 index 0000000000..b99c242408 --- /dev/null +++ b/spring-security-x509/spring-security-x509-basic-auth/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.security.x509; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@SpringBootApplication +@EnableWebSecurity +public class X509AuthenticationServer extends WebSecurityConfigurerAdapter { + + public static void main(String[] args) { + SpringApplication.run(X509AuthenticationServer.class, args); + } + +} diff --git a/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties b/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties new file mode 100644 index 0000000000..f293d6712d --- /dev/null +++ b/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties @@ -0,0 +1,8 @@ +server.ssl.key-store=../keystore/keystore.jks +server.ssl.key-store-password=changeit +server.ssl.key-alias=localhost +server.ssl.key-password=changeit +server.ssl.enabled=true +server.port=8443 +security.user.name=Admin +security.user.password=admin \ No newline at end of file diff --git a/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/templates/user.html b/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/templates/user.html new file mode 100644 index 0000000000..3e36d7b644 --- /dev/null +++ b/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/templates/user.html @@ -0,0 +1,9 @@ + + + + X.509 Authentication Demo + + +

      Hello !

      + + diff --git a/spring-security-x509/spring-security-x509-basic-auth/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java b/spring-security-x509/spring-security-x509-basic-auth/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java new file mode 100644 index 0000000000..0b9a11552a --- /dev/null +++ b/spring-security-x509/spring-security-x509-basic-auth/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java @@ -0,0 +1,14 @@ +package com.baeldung.spring.security.x509; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class X509AuthenticationServerTests { + @Test + public void contextLoads() { + } +} diff --git a/spring-security-x509/spring-security-x509-client-auth/pom.xml b/spring-security-x509/spring-security-x509-client-auth/pom.xml new file mode 100644 index 0000000000..56cef8ea07 --- /dev/null +++ b/spring-security-x509/spring-security-x509-client-auth/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + client-auth-server + 0.0.1-SNAPSHOT + jar + + client-auth-server + Spring x.509 Client Authentication Demo + + + com.baeldung + spring-security-x509 + 0.0.1-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-security-x509/spring-security-x509-client-auth/src/main/java/com/baeldung/spring/security/x509/UserController.java b/spring-security-x509/spring-security-x509-client-auth/src/main/java/com/baeldung/spring/security/x509/UserController.java new file mode 100644 index 0000000000..d4616dd5a6 --- /dev/null +++ b/spring-security-x509/spring-security-x509-client-auth/src/main/java/com/baeldung/spring/security/x509/UserController.java @@ -0,0 +1,21 @@ +package com.baeldung.spring.security.x509; + +import java.security.Principal; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class UserController { + @PreAuthorize("hasAuthority('ROLE_USER')") + @RequestMapping(value = "/user") + public String user(Model model, Principal principal) { + UserDetails currentUser = (UserDetails) ((Authentication) principal).getPrincipal(); + model.addAttribute("username", currentUser.getUsername()); + return "user"; + } +} diff --git a/spring-security-x509/spring-security-x509-client-auth/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java b/spring-security-x509/spring-security-x509-client-auth/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java new file mode 100644 index 0000000000..050423238e --- /dev/null +++ b/spring-security-x509/spring-security-x509-client-auth/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java @@ -0,0 +1,41 @@ +package com.baeldung.spring.security.x509; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +@SpringBootApplication +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class X509AuthenticationServer extends WebSecurityConfigurerAdapter { + public static void main(String[] args) { + SpringApplication.run(X509AuthenticationServer.class, args); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().authenticated().and().x509().subjectPrincipalRegex("CN=(.*?)(?:,|$)").userDetailsService(userDetailsService()); + } + + @Bean + public UserDetailsService userDetailsService() { + return new UserDetailsService() { + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + if (username.equals("cid")) { + return new User(username, "", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + } + throw new UsernameNotFoundException("User not found!"); + } + }; + } +} diff --git a/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties b/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties new file mode 100644 index 0000000000..174eba9f98 --- /dev/null +++ b/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties @@ -0,0 +1,11 @@ +server.ssl.key-store=../keystore/keystore.jks +server.ssl.key-store-password=changeit +server.ssl.key-alias=localhost +server.ssl.key-password=changeit +server.ssl.enabled=true +server.port=8443 +security.user.name=Admin +security.user.password=admin +server.ssl.trust-store=../keystore/truststore.jks +server.ssl.trust-store-password=changeit +server.ssl.client-auth=need \ No newline at end of file diff --git a/spring-security-x509/spring-security-x509-client-auth/src/main/resources/keystore.jks b/spring-security-x509/spring-security-x509-client-auth/src/main/resources/keystore.jks new file mode 100644 index 0000000000..044a820c39 Binary files /dev/null and b/spring-security-x509/spring-security-x509-client-auth/src/main/resources/keystore.jks differ diff --git a/spring-security-x509/spring-security-x509-client-auth/src/main/resources/templates/user.html b/spring-security-x509/spring-security-x509-client-auth/src/main/resources/templates/user.html new file mode 100644 index 0000000000..a35b18bacc --- /dev/null +++ b/spring-security-x509/spring-security-x509-client-auth/src/main/resources/templates/user.html @@ -0,0 +1,9 @@ + + + + X.509 Authentication Demo + + +

      Hello !

      + + diff --git a/spring-security-x509/spring-security-x509-client-auth/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java b/spring-security-x509/spring-security-x509-client-auth/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java new file mode 100644 index 0000000000..0b9a11552a --- /dev/null +++ b/spring-security-x509/spring-security-x509-client-auth/src/test/java/com/baeldung/spring/security/x509/X509AuthenticationServerTests.java @@ -0,0 +1,14 @@ +package com.baeldung.spring.security.x509; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class X509AuthenticationServerTests { + @Test + public void contextLoads() { + } +} diff --git a/spring-spel/pom.xml b/spring-spel/pom.xml new file mode 100644 index 0000000000..12b7164e27 --- /dev/null +++ b/spring-spel/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + com.baeldung + spel + 1.0-SNAPSHOT + + + + junit + junit + 4.12 + + + org.hamcrest + hamcrest-all + 1.3 + + + org.springframework + spring-context + 4.0.6.RELEASE + + + org.springframework + spring-test + 4.0.6.RELEASE + test + + + + + + maven-compiler-plugin + 3.3 + + true + true + 1.8 + 1.8 + UTF-8 + true + true + + + + + + \ No newline at end of file diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/SpelProgram.java b/spring-spel/src/main/java/com/baeldung/spring/spel/SpelProgram.java new file mode 100644 index 0000000000..3ad9e7d05d --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/SpelProgram.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.spel; + +import com.baeldung.spring.spel.examples.SpelConditional; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class SpelProgram { + public static void main(String[] args) { + ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); + SpelConditional spelCollections = (SpelConditional) context.getBean("spelConditional"); + + // Here you can choose which bean do you want to load instead of spelConditional: spelCollections, spelLogical, etc. + + System.out.println(spelCollections); + } + +} diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/entity/Car.java b/spring-spel/src/main/java/com/baeldung/spring/spel/entity/Car.java new file mode 100644 index 0000000000..6ad665bcba --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/entity/Car.java @@ -0,0 +1,91 @@ +package com.baeldung.spring.spel.entity; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component("someCar") +public class Car { + @Value("Some make") + private String make; + @Value("Some model") + private String model; + @Value("#{engine}") + private Engine engine; + @Value("#{engine.horsePower}") + private int horsePower; + @Value("2007") + private int yearOfProduction; + @Value("#{engine.capacity >= 3000}") + private boolean isBigEngine; + @Value("#{someCar.yearOfProduction > 2016}") + private boolean isNewCar; + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public Engine getEngine() { + return engine; + } + + public void setEngine(Engine engine) { + this.engine = engine; + } + + public int getHorsePower() { + return horsePower; + } + + public void setHorsePower(int horsePower) { + this.horsePower = horsePower; + } + + public int getYearOfProduction() { + return yearOfProduction; + } + + public void setYearOfProduction(int yearOfProduction) { + this.yearOfProduction = yearOfProduction; + } + + public boolean isBigEngine() { + return isBigEngine; + } + + public void setBigEngine(boolean bigEngine) { + isBigEngine = bigEngine; + } + + public boolean isNewCar() { + return isNewCar; + } + + public void setNewCar(boolean newCar) { + isNewCar = newCar; + } + + @Override + public String toString() { + return "Car{" + + "make='" + make + '\'' + + ", model='" + model + '\'' + + ", engine=" + engine + + ", horsePower=" + horsePower + + ", yearOfProduction=" + yearOfProduction + + ", isBigEngine=" + isBigEngine + + ", isNewCar=" + isNewCar + + '}'; + } +} diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/entity/CarPark.java b/spring-spel/src/main/java/com/baeldung/spring/spel/entity/CarPark.java new file mode 100644 index 0000000000..6475405383 --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/entity/CarPark.java @@ -0,0 +1,48 @@ +package com.baeldung.spring.spel.entity; + +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component("carPark") +public class CarPark { + private List cars = new ArrayList<>(); + private Map carsByDriver = new HashMap<>(); + + public CarPark() { + Car model1 = new Car(); + model1.setMake("Good company"); + model1.setModel("Model1"); + model1.setYearOfProduction(1998); + + Car model2 = new Car(); + model2.setMake("Good company"); + model2.setModel("Model2"); + model2.setYearOfProduction(2005); + + cars.add(model1); + cars.add(model2); + + carsByDriver.put("Driver1", model1); + carsByDriver.put("Driver2", model2); + } + + public List getCars() { + return cars; + } + + public void setCars(List cars) { + this.cars = cars; + } + + public Map getCarsByDriver() { + return carsByDriver; + } + + public void setCarsByDriver(Map carsByDriver) { + this.carsByDriver = carsByDriver; + } +} diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/entity/Engine.java b/spring-spel/src/main/java/com/baeldung/spring/spel/entity/Engine.java new file mode 100644 index 0000000000..9b9d125170 --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/entity/Engine.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.spel.entity; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component("engine") +public class Engine { + @Value("3200") + private int capacity; + @Value("250") + private int horsePower; + @Value("6") + private int numberOfCylinders; + + public int getCapacity() { + return capacity; + } + + public void setCapacity(int capacity) { + this.capacity = capacity; + } + + public int getHorsePower() { + return horsePower; + } + + public void setHorsePower(int horsePower) { + this.horsePower = horsePower; + } + + public int getNumberOfCylinders() { + return numberOfCylinders; + } + + public void setNumberOfCylinders(int numberOfCylinders) { + this.numberOfCylinders = numberOfCylinders; + } + + @Override + public String toString() { + return "Engine{" + + "capacity=" + capacity + + ", horsePower=" + horsePower + + ", numberOfCylinders=" + numberOfCylinders + + '}'; + } +} diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelArithmetic.java b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelArithmetic.java new file mode 100644 index 0000000000..ba21c87931 --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelArithmetic.java @@ -0,0 +1,131 @@ +package com.baeldung.spring.spel.examples; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component("spelArithmetic") +public class SpelArithmetic { + @Value("#{19 + 1}") + private double add; + + @Value("#{'Some string ' + 'plus other string'}") + private String addString; + + @Value("#{20 - 1}") + private double subtract; + + @Value("#{10 * 2}") + private double multiply; + + @Value("#{36 / 2}") + private double divide; + @Value("#{36 div 2}") + private double divideAlphabetic; + + @Value("#{37 % 10}") + private double modulo; + @Value("#{37 mod 10}") + private double moduloAlphabetic; + + @Value("#{2 ^ 9}") + private double powerOf; + + @Value("#{(2 + 2) * 2 + 9}") + private double brackets; + + public double getAdd() { + return add; + } + + public void setAdd(double add) { + this.add = add; + } + + public String getAddString() { + return addString; + } + + public void setAddString(String addString) { + this.addString = addString; + } + + public double getSubtract() { + return subtract; + } + + public void setSubtract(double subtract) { + this.subtract = subtract; + } + + public double getMultiply() { + return multiply; + } + + public void setMultiply(double multiply) { + this.multiply = multiply; + } + + public double getDivide() { + return divide; + } + + public void setDivide(double divide) { + this.divide = divide; + } + + public double getDivideAlphabetic() { + return divideAlphabetic; + } + + public void setDivideAlphabetic(double divideAlphabetic) { + this.divideAlphabetic = divideAlphabetic; + } + + public double getModulo() { + return modulo; + } + + public void setModulo(double modulo) { + this.modulo = modulo; + } + + public double getModuloAlphabetic() { + return moduloAlphabetic; + } + + public void setModuloAlphabetic(double moduloAlphabetic) { + this.moduloAlphabetic = moduloAlphabetic; + } + + public double getPowerOf() { + return powerOf; + } + + public void setPowerOf(double powerOf) { + this.powerOf = powerOf; + } + + public double getBrackets() { + return brackets; + } + + public void setBrackets(double brackets) { + this.brackets = brackets; + } + + @Override + public String toString() { + return "SpelArithmetic{" + + "add=" + add + + ", addString='" + addString + '\'' + + ", subtract=" + subtract + + ", multiply=" + multiply + + ", divide=" + divide + + ", divideAlphabetic=" + divideAlphabetic + + ", modulo=" + modulo + + ", moduloAlphabetic=" + moduloAlphabetic + + ", powerOf=" + powerOf + + ", brackets=" + brackets + + '}'; + } +} diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelCollections.java b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelCollections.java new file mode 100644 index 0000000000..6c606bbd75 --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelCollections.java @@ -0,0 +1,59 @@ +package com.baeldung.spring.spel.examples; + +import com.baeldung.spring.spel.entity.Car; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component("spelCollections") +public class SpelCollections { + @Value("#{carPark.carsByDriver['Driver1']}") + private Car driver1Car; + @Value("#{carPark.carsByDriver['Driver2']}") + private Car driver2Car; + @Value("#{carPark.cars[0]}") + private Car firstCarInPark; + @Value("#{carPark.cars.size()}") + private Integer numberOfCarsInPark; + + public Car getDriver1Car() { + return driver1Car; + } + + public void setDriver1Car(Car driver1Car) { + this.driver1Car = driver1Car; + } + + public Car getDriver2Car() { + return driver2Car; + } + + public void setDriver2Car(Car driver2Car) { + this.driver2Car = driver2Car; + } + + public Car getFirstCarInPark() { + return firstCarInPark; + } + + public void setFirstCarInPark(Car firstCarInPark) { + this.firstCarInPark = firstCarInPark; + } + + public Integer getNumberOfCarsInPark() { + return numberOfCarsInPark; + } + + public void setNumberOfCarsInPark(Integer numberOfCarsInPark) { + this.numberOfCarsInPark = numberOfCarsInPark; + } + + @Override + public String toString() { + return "[" + + "driver1Car=" + driver1Car + + ", driver2Car=" + driver2Car + + ", firstCarInPark=" + firstCarInPark + + ", numberOfCarsInPark=" + numberOfCarsInPark + + ']'; + } +} diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelConditional.java b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelConditional.java new file mode 100644 index 0000000000..6e255c0425 --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelConditional.java @@ -0,0 +1,49 @@ +package com.baeldung.spring.spel.examples; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component("spelConditional") +public class SpelConditional { + @Value("#{false ? 'There was true value' : 'Something went wrong. There was false value'}") + private String ternary; + + @Value("#{someCar.model != null ? someCar.model : 'Unknown model'}") + private String ternary2; + + @Value("#{someCar.model?:'Unknown model'}") + private String elvis; + + public String getTernary() { + return ternary; + } + + public void setTernary(String ternary) { + this.ternary = ternary; + } + + public String getTernary2() { + return ternary2; + } + + public void setTernary2(String ternary2) { + this.ternary2 = ternary2; + } + + public String getElvis() { + return elvis; + } + + public void setElvis(String elvis) { + this.elvis = elvis; + } + + @Override + public String toString() { + return "SpelConditional{" + + "ternary='" + ternary + '\'' + + ", ternary2='" + ternary2 + '\'' + + ", elvis='" + elvis + '\'' + + '}'; + } +} diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelLogical.java b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelLogical.java new file mode 100644 index 0000000000..09b4e35c9d --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelLogical.java @@ -0,0 +1,82 @@ +package com.baeldung.spring.spel.examples; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component("spelLogical") +public class SpelLogical { + @Value("#{250 > 200 && 200 < 4000}") + private boolean and; + @Value("#{250 > 200 and 200 < 4000}") + private boolean andAlphabetic; + + @Value("#{400 > 300 || 150 < 100}") + private boolean or; + @Value("#{400 > 300 or 150 < 100}") + private boolean orAlphabetic; + + @Value("#{!true}") + private boolean not; + @Value("#{not true}") + private boolean notAlphabetic; + + public boolean isAnd() { + return and; + } + + public void setAnd(boolean and) { + this.and = and; + } + + public boolean isAndAlphabetic() { + return andAlphabetic; + } + + public void setAndAlphabetic(boolean andAlphabetic) { + this.andAlphabetic = andAlphabetic; + } + + public boolean isOr() { + return or; + } + + public void setOr(boolean or) { + this.or = or; + } + + public boolean isOrAlphabetic() { + return orAlphabetic; + } + + public void setOrAlphabetic(boolean orAlphabetic) { + this.orAlphabetic = orAlphabetic; + } + + public boolean isNot() { + return not; + } + + public void setNot(boolean not) { + this.not = not; + } + + public boolean isNotAlphabetic() { + return notAlphabetic; + } + + public void setNotAlphabetic(boolean notAlphabetic) { + this.notAlphabetic = notAlphabetic; + } + + @Override + public String toString() { + return "SpelLogical{" + + "and=" + and + + ", andAlphabetic=" + andAlphabetic + + ", or=" + or + + ", orAlphabetic=" + orAlphabetic + + ", not=" + not + + ", notAlphabetic=" + notAlphabetic + + '}'; + } +} diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelParser.java b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelParser.java new file mode 100644 index 0000000000..f7063d4c46 --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelParser.java @@ -0,0 +1,30 @@ +package com.baeldung.spring.spel.examples; + +import com.baeldung.spring.spel.entity.Car; +import com.baeldung.spring.spel.entity.CarPark; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.SpelParserConfiguration; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +public class SpelParser { + public static void main(String[] args) { + Car car = new Car(); + car.setMake("Good manufacturer"); + car.setModel("Model 3"); + car.setYearOfProduction(2014); + + CarPark carPark = new CarPark(); + + SpelParserConfiguration config = new SpelParserConfiguration(true, true); + + StandardEvaluationContext context = new StandardEvaluationContext(carPark); + + ExpressionParser expressionParser = new SpelExpressionParser(config); + expressionParser.parseExpression("cars[0]").setValue(context, car); + + Car result = carPark.getCars().get(0); + + System.out.println(result); + } +} diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelRegex.java b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelRegex.java new file mode 100644 index 0000000000..a08142ca1c --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelRegex.java @@ -0,0 +1,74 @@ +package com.baeldung.spring.spel.examples; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component("spelRegex") +public class SpelRegex { + + @Value("#{100 matches '\\d+' }") + private boolean validNumericStringResult; + + @Value("#{'100fghdjf' matches '\\d+' }") + private boolean invalidNumericStringResult; + + @Value("#{'valid alphabetic string' matches '[a-zA-Z\\s]+' }") + private boolean validAlphabeticStringResult; + + @Value("#{'invalid alphabetic string #$1' matches '[a-zA-Z\\s]+' }") + private boolean invalidAlphabeticStringResult; + + @Value("#{engine.horsePower matches '\\d+'}") + private boolean validFormatOfHorsePower; + + public boolean isValidNumericStringResult() { + return validNumericStringResult; + } + + public void setValidNumericStringResult(boolean validNumericStringResult) { + this.validNumericStringResult = validNumericStringResult; + } + + public boolean isInvalidNumericStringResult() { + return invalidNumericStringResult; + } + + public void setInvalidNumericStringResult(boolean invalidNumericStringResult) { + this.invalidNumericStringResult = invalidNumericStringResult; + } + + public boolean isValidAlphabeticStringResult() { + return validAlphabeticStringResult; + } + + public void setValidAlphabeticStringResult(boolean validAlphabeticStringResult) { + this.validAlphabeticStringResult = validAlphabeticStringResult; + } + + public boolean isInvalidAlphabeticStringResult() { + return invalidAlphabeticStringResult; + } + + public void setInvalidAlphabeticStringResult(boolean invalidAlphabeticStringResult) { + this.invalidAlphabeticStringResult = invalidAlphabeticStringResult; + } + + public boolean isValidFormatOfHorsePower() { + return validFormatOfHorsePower; + } + + public void setValidFormatOfHorsePower(boolean validFormatOfHorsePower) { + this.validFormatOfHorsePower = validFormatOfHorsePower; + } + + @Override + public String toString() { + return "SpelRegex{" + + "validNumericStringResult=" + validNumericStringResult + + ", invalidNumericStringResult=" + invalidNumericStringResult + + ", validAlphabeticStringResult=" + validAlphabeticStringResult + + ", invalidAlphabeticStringResult=" + invalidAlphabeticStringResult + + ", validFormatOfHorsePower=" + validFormatOfHorsePower + + '}'; + } +} diff --git a/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelRelational.java b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelRelational.java new file mode 100644 index 0000000000..b811595429 --- /dev/null +++ b/spring-spel/src/main/java/com/baeldung/spring/spel/examples/SpelRelational.java @@ -0,0 +1,229 @@ +package com.baeldung.spring.spel.examples; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component("spelRelational") +public class SpelRelational { + @Value("#{1 == 1}") + private boolean equal; + + @Value("#{1 eq 1}") + private boolean equalAlphabetic; + + @Value("#{1 != 1}") + private boolean notEqual; + + @Value("#{1 ne 1}") + private boolean notEqualAlphabetic; + + @Value("#{1 < 1}") + private boolean lessThan; + + @Value("#{1 lt 1}") + private boolean lessThanAlphabetic; + + @Value("#{1 <= 1}") + private boolean lessThanOrEqual; + + @Value("#{1 le 1}") + private boolean lessThanOrEqualAlphabetic; + + @Value("#{1 > 1}") + private boolean greaterThan; + + @Value("#{1 gt 1}") + private boolean greaterThanAlphabetic; + + @Value("#{9 >= 6}") + private boolean greaterThanOrEqual; + + @Value("#{9 ge 6}") + private boolean greaterThanOrEqualAlphabetic; + + @Value("#{250 > 200 && 200 < 4000}") + private boolean and; + + @Value("#{250 > 200 and 200 < 4000}") + private boolean andAlphabetic; + + @Value("#{400 > 300 || 150 < 100}") + private boolean or; + + @Value("#{400 > 300 or 150 < 100}") + private boolean orAlphabetic; + + @Value("#{!true}") + private boolean not; + + @Value("#{not true}") + private boolean notAlphabetic; + + public boolean isEqual() { + return equal; + } + + public void setEqual(boolean equal) { + this.equal = equal; + } + + public boolean isEqualAlphabetic() { + return equalAlphabetic; + } + + public void setEqualAlphabetic(boolean equalAlphabetic) { + this.equalAlphabetic = equalAlphabetic; + } + + public boolean isNotEqual() { + return notEqual; + } + + public void setNotEqual(boolean notEqual) { + this.notEqual = notEqual; + } + + public boolean isNotEqualAlphabetic() { + return notEqualAlphabetic; + } + + public void setNotEqualAlphabetic(boolean notEqualAlphabetic) { + this.notEqualAlphabetic = notEqualAlphabetic; + } + + public boolean isLessThan() { + return lessThan; + } + + public void setLessThan(boolean lessThan) { + this.lessThan = lessThan; + } + + public boolean isLessThanAlphabetic() { + return lessThanAlphabetic; + } + + public void setLessThanAlphabetic(boolean lessThanAlphabetic) { + this.lessThanAlphabetic = lessThanAlphabetic; + } + + public boolean isLessThanOrEqual() { + return lessThanOrEqual; + } + + public void setLessThanOrEqual(boolean lessThanOrEqual) { + this.lessThanOrEqual = lessThanOrEqual; + } + + public boolean isLessThanOrEqualAlphabetic() { + return lessThanOrEqualAlphabetic; + } + + public void setLessThanOrEqualAlphabetic(boolean lessThanOrEqualAlphabetic) { + this.lessThanOrEqualAlphabetic = lessThanOrEqualAlphabetic; + } + + public boolean isGreaterThan() { + return greaterThan; + } + + public void setGreaterThan(boolean greaterThan) { + this.greaterThan = greaterThan; + } + + public boolean isGreaterThanAlphabetic() { + return greaterThanAlphabetic; + } + + public void setGreaterThanAlphabetic(boolean greaterThanAlphabetic) { + this.greaterThanAlphabetic = greaterThanAlphabetic; + } + + public boolean isGreaterThanOrEqual() { + return greaterThanOrEqual; + } + + public void setGreaterThanOrEqual(boolean greaterThanOrEqual) { + this.greaterThanOrEqual = greaterThanOrEqual; + } + + public boolean isGreaterThanOrEqualAlphabetic() { + return greaterThanOrEqualAlphabetic; + } + + public void setGreaterThanOrEqualAlphabetic(boolean greaterThanOrEqualAlphabetic) { + this.greaterThanOrEqualAlphabetic = greaterThanOrEqualAlphabetic; + } + + public boolean isAnd() { + return and; + } + + public void setAnd(boolean and) { + this.and = and; + } + + public boolean isAndAlphabetic() { + return andAlphabetic; + } + + public void setAndAlphabetic(boolean andAlphabetic) { + this.andAlphabetic = andAlphabetic; + } + + public boolean isOr() { + return or; + } + + public void setOr(boolean or) { + this.or = or; + } + + public boolean isOrAlphabetic() { + return orAlphabetic; + } + + public void setOrAlphabetic(boolean orAlphabetic) { + this.orAlphabetic = orAlphabetic; + } + + public boolean isNot() { + return not; + } + + public void setNot(boolean not) { + this.not = not; + } + + public boolean isNotAlphabetic() { + return notAlphabetic; + } + + public void setNotAlphabetic(boolean notAlphabetic) { + this.notAlphabetic = notAlphabetic; + } + + @Override + public String toString() { + return "SpelRelational{" + + "equal=" + equal + + ", equalAlphabetic=" + equalAlphabetic + + ", notEqual=" + notEqual + + ", notEqualAlphabetic=" + notEqualAlphabetic + + ", lessThan=" + lessThan + + ", lessThanAlphabetic=" + lessThanAlphabetic + + ", lessThanOrEqual=" + lessThanOrEqual + + ", lessThanOrEqualAlphabetic=" + lessThanOrEqualAlphabetic + + ", greaterThan=" + greaterThan + + ", greaterThanAlphabetic=" + greaterThanAlphabetic + + ", greaterThanOrEqual=" + greaterThanOrEqual + + ", greaterThanOrEqualAlphabetic=" + greaterThanOrEqualAlphabetic + + ", and=" + and + + ", andAlphabetic=" + andAlphabetic + + ", or=" + or + + ", orAlphabetic=" + orAlphabetic + + ", not=" + not + + ", notAlphabetic=" + notAlphabetic + + '}'; + } +} diff --git a/spring-spel/src/main/resources/applicationContext.xml b/spring-spel/src/main/resources/applicationContext.xml new file mode 100644 index 0000000000..998addae67 --- /dev/null +++ b/spring-spel/src/main/resources/applicationContext.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/spring-spel/src/test/java/com/baeldung/spel/SpelTest.java b/spring-spel/src/test/java/com/baeldung/spel/SpelTest.java new file mode 100644 index 0000000000..5cf18bc1d2 --- /dev/null +++ b/spring-spel/src/test/java/com/baeldung/spel/SpelTest.java @@ -0,0 +1,105 @@ +package com.baeldung.spel; + +import com.baeldung.spring.spel.examples.*; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = {"classpath:applicationContext.xml"}) +public class SpelTest { + + @Autowired + private SpelArithmetic spelArithmetic = new SpelArithmetic(); + + @Autowired + private SpelCollections spelCollections = new SpelCollections(); + + @Autowired + private SpelConditional spelConditional = new SpelConditional(); + + @Autowired + private SpelLogical spelLogical = new SpelLogical(); + + @Autowired + private SpelRegex spelRegex = new SpelRegex(); + + @Autowired + private SpelRelational spelRelational = new SpelRelational(); + + @Test + public void testArithmetic() throws Exception { + assertThat(spelArithmetic.getAdd(), equalTo(20.0)); + assertThat(spelArithmetic.getAddString(), equalTo("Some string plus other string")); + assertThat(spelArithmetic.getSubtract(), equalTo(19.0)); + assertThat(spelArithmetic.getMultiply(), equalTo(20.0)); + assertThat(spelArithmetic.getDivide(), equalTo(18.0)); + assertThat(spelArithmetic.getDivideAlphabetic(), equalTo(18.0)); + assertThat(spelArithmetic.getModulo(), equalTo(7.0)); + assertThat(spelArithmetic.getModuloAlphabetic(), equalTo(7.0)); + assertThat(spelArithmetic.getPowerOf(), equalTo(512.0)); + assertThat(spelArithmetic.getBrackets(), equalTo(17.0)); + } + + @Test + public void testCollections() throws Exception { + assertThat(spelCollections.getDriver1Car().getModel(), equalTo("Model1")); + assertThat(spelCollections.getDriver2Car().getModel(), equalTo("Model2")); + assertThat(spelCollections.getFirstCarInPark().getModel(), equalTo("Model1")); + assertThat(spelCollections.getNumberOfCarsInPark(), equalTo(2)); + } + + @Test + public void testConditional() throws Exception { + assertThat(spelConditional.getTernary(), equalTo("Something went wrong. There was false value")); + assertThat(spelConditional.getTernary2(), equalTo("Some model")); + assertThat(spelConditional.getElvis(), equalTo("Some model")); + } + + @Test + public void testLogical() throws Exception { + assertThat(spelLogical.isAnd(), equalTo(true)); + assertThat(spelLogical.isAndAlphabetic(), equalTo(true)); + assertThat(spelLogical.isOr(), equalTo(true)); + assertThat(spelLogical.isOrAlphabetic(), equalTo(true)); + assertThat(spelLogical.isNot(), equalTo(false)); + assertThat(spelLogical.isNotAlphabetic(), equalTo(false)); + } + + @Test + public void testRegex() throws Exception { + assertThat(spelRegex.isValidNumericStringResult(), equalTo(true)); + assertThat(spelRegex.isInvalidNumericStringResult(), equalTo(false)); + assertThat(spelRegex.isValidAlphabeticStringResult(), equalTo(true)); + assertThat(spelRegex.isInvalidAlphabeticStringResult(), equalTo(false)); + assertThat(spelRegex.isValidFormatOfHorsePower(), equalTo(true)); + } + + @Test + public void testRelational() throws Exception { + assertThat(spelRelational.isEqual(), equalTo(true)); + assertThat(spelRelational.isEqualAlphabetic(), equalTo(true)); + assertThat(spelRelational.isNotEqual(), equalTo(false)); + assertThat(spelRelational.isNotEqualAlphabetic(), equalTo(false)); + assertThat(spelRelational.isLessThan(), equalTo(false)); + assertThat(spelRelational.isLessThanAlphabetic(), equalTo(false)); + assertThat(spelRelational.isLessThanOrEqual(), equalTo(true)); + assertThat(spelRelational.isLessThanOrEqualAlphabetic(), equalTo(true)); + assertThat(spelRelational.isGreaterThan(), equalTo(false)); + assertThat(spelRelational.isGreaterThanAlphabetic(), equalTo(false)); + assertThat(spelRelational.isGreaterThanOrEqual(), equalTo(true)); + assertThat(spelRelational.isGreaterThanOrEqualAlphabetic(), equalTo(true)); + assertThat(spelRelational.isAnd(), equalTo(true)); + assertThat(spelRelational.isAndAlphabetic(), equalTo(true)); + assertThat(spelRelational.isOr(), equalTo(true)); + assertThat(spelRelational.isOrAlphabetic(), equalTo(true)); + assertThat(spelRelational.isNot(), equalTo(false)); + assertThat(spelRelational.isNotAlphabetic(), equalTo(false)); + } +} diff --git a/spring-spel/src/test/resources/applicationContext.xml b/spring-spel/src/test/resources/applicationContext.xml new file mode 100644 index 0000000000..998addae67 --- /dev/null +++ b/spring-spel/src/test/resources/applicationContext.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/spring-thymeleaf/pom.xml b/spring-thymeleaf/pom.xml index 16e6849f93..a13f1de4c7 100644 --- a/spring-thymeleaf/pom.xml +++ b/spring-thymeleaf/pom.xml @@ -5,57 +5,69 @@ spring-thymeleaf 0.1-SNAPSHOT war - - 1.7 - - 4.1.8.RELEASE - 3.0.1 - + + 1.8 + + 4.3.3.RELEASE + 3.0.1 + 1.7.12 1.1.3 - - 2.1.4.RELEASE - - 1.1.0.Final - 5.1.2.Final - - 3.3 - 2.6 - 2.18.1 - 1.4.15 - - - - - org.springframework - spring-context - ${org.springframework-version} - - - - commons-logging - commons-logging - - - - - org.springframework - spring-webmvc - ${org.springframework-version} - - - - org.thymeleaf - thymeleaf - ${org.thymeleaf-version} - - - org.thymeleaf - thymeleaf-spring4 - ${org.thymeleaf-version} - - - + + 3.0.1.RELEASE + + 1.1.0.Final + 5.1.2.Final + + + 3.5.1 + 2.6 + 2.19.1 + 1.4.18 + + + + + + org.springframework + spring-context + ${org.springframework-version} + + + + commons-logging + commons-logging + + + + + org.springframework + spring-webmvc + ${org.springframework-version} + + + + org.springframework.security + spring-security-web + 4.1.3.RELEASE + + + org.springframework.security + spring-security-config + 4.1.3.RELEASE + + + + org.thymeleaf + thymeleaf + ${org.thymeleaf-version} + + + org.thymeleaf + thymeleaf-spring4 + ${org.thymeleaf-version} + + org.slf4j slf4j-api @@ -78,55 +90,81 @@ log4j-over-slf4j ${org.slf4j.version} - - - javax.servlet - javax.servlet-api - ${javax.servlet-version} - provided - - - - javax.validation - validation-api - ${javax.validation-version} - - - org.hibernate - hibernate-validator - ${org.hibernate-version} - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${java-version} - ${java-version} - - - - org.apache.maven.plugins - maven-war-plugin - ${maven-war-plugin.version} - - false - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - - - - - + + + javax.servlet + javax.servlet-api + ${javax.servlet-version} + provided + + + + javax.validation + validation-api + ${javax.validation-version} + + + org.hibernate + hibernate-validator + ${org.hibernate-version} + + + + + org.springframework + spring-test + 4.1.3.RELEASE + test + + + + + org.springframework.security + spring-security-test + 4.1.3.RELEASE + test + + + + + junit + junit + 4.12 + test + + +
      + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java-version} + ${java-version} + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + false + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + + + + org.codehaus.cargo cargo-maven2-plugin @@ -146,6 +184,7 @@ - - + + +
      diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/InitSecurity.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/InitSecurity.java new file mode 100644 index 0000000000..956db4a0e5 --- /dev/null +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/InitSecurity.java @@ -0,0 +1,11 @@ +package com.baeldung.thymeleaf.config; + +import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; + +public class InitSecurity extends AbstractSecurityWebApplicationInitializer { + + public InitSecurity() { + super(WebMVCSecurity.class); + + } +} diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebApp.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebApp.java index 89ad7e601e..3104f45ab5 100644 --- a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebApp.java +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebApp.java @@ -9,28 +9,28 @@ import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatche */ public class WebApp extends AbstractAnnotationConfigDispatcherServletInitializer { - public WebApp() { - super(); - } + public WebApp() { + super(); + } - @Override - protected Class[] getRootConfigClasses() { - return null; - } + @Override + protected Class[] getRootConfigClasses() { + return null; + } - @Override - protected Class[] getServletConfigClasses() { - return new Class[] { WebMVCConfig.class }; - } + @Override + protected Class[] getServletConfigClasses() { + return new Class[] { WebMVCConfig.class, WebMVCSecurity.class, InitSecurity.class }; + } - @Override - protected String[] getServletMappings() { - return new String[] { "/" }; - } + @Override + protected String[] getServletMappings() { + return new String[] { "/" }; + } - @Override - protected void customizeRegistration(final Dynamic registration) { - super.customizeRegistration(registration); - } + @Override + protected void customizeRegistration(final Dynamic registration) { + super.customizeRegistration(registration); + } } diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java index 51c60247a1..444b780673 100644 --- a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java @@ -1,18 +1,27 @@ package com.baeldung.thymeleaf.config; -import com.baeldung.thymeleaf.formatter.NameFormatter; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Description; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.format.FormatterRegistry; +import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.thymeleaf.TemplateEngine; import org.thymeleaf.spring4.SpringTemplateEngine; +import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver; import org.thymeleaf.spring4.view.ThymeleafViewResolver; -import org.thymeleaf.templateresolver.ServletContextTemplateResolver; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ITemplateResolver; + +import com.baeldung.thymeleaf.formatter.NameFormatter; +import com.baeldung.thymeleaf.utils.ArrayUtil; + @Configuration @EnableWebMvc @@ -21,36 +30,76 @@ import org.thymeleaf.templateresolver.ServletContextTemplateResolver; * Java configuration file that is used for Spring MVC and Thymeleaf * configurations */ -public class WebMVCConfig extends WebMvcConfigurerAdapter { +public class WebMVCConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware { - @Bean - @Description("Thymeleaf Template Resolver") - public ServletContextTemplateResolver templateResolver() { - ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(); - templateResolver.setPrefix("/WEB-INF/views/"); - templateResolver.setSuffix(".html"); - templateResolver.setTemplateMode("HTML5"); + private ApplicationContext applicationContext; - return templateResolver; + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; } @Bean - @Description("Thymeleaf Template Engine") - public SpringTemplateEngine templateEngine() { - SpringTemplateEngine templateEngine = new SpringTemplateEngine(); - templateEngine.setTemplateResolver(templateResolver()); - - return templateEngine; + public ViewResolver htmlViewResolver() { + ThymeleafViewResolver resolver = new ThymeleafViewResolver(); + resolver.setTemplateEngine(templateEngine(htmlTemplateResolver())); + resolver.setContentType("text/html"); + resolver.setCharacterEncoding("UTF-8"); + resolver.setViewNames(ArrayUtil.array("*.html")); + return resolver; } - + @Bean - @Description("Thymeleaf View Resolver") - public ThymeleafViewResolver viewResolver() { - ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); - viewResolver.setTemplateEngine(templateEngine()); - viewResolver.setOrder(1); - return viewResolver; - } + public ViewResolver javascriptViewResolver() { + ThymeleafViewResolver resolver = new ThymeleafViewResolver(); + resolver.setTemplateEngine(templateEngine(javascriptTemplateResolver())); + resolver.setContentType("application/javascript"); + resolver.setCharacterEncoding("UTF-8"); + resolver.setViewNames(ArrayUtil.array("*.js")); + return resolver; + } + + @Bean + public ViewResolver plainViewResolver() { + ThymeleafViewResolver resolver = new ThymeleafViewResolver(); + resolver.setTemplateEngine(templateEngine(plainTemplateResolver())); + resolver.setContentType("text/plain"); + resolver.setCharacterEncoding("UTF-8"); + resolver.setViewNames(ArrayUtil.array("*.txt")); + return resolver; + } + + private TemplateEngine templateEngine(ITemplateResolver templateResolver) { + SpringTemplateEngine engine = new SpringTemplateEngine(); + engine.setTemplateResolver(templateResolver); + return engine; + } + + private ITemplateResolver htmlTemplateResolver() { + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setApplicationContext(applicationContext); + resolver.setPrefix("/WEB-INF/views/"); + resolver.setCacheable(false); + resolver.setTemplateMode(TemplateMode.HTML); + return resolver; + } + + private ITemplateResolver javascriptTemplateResolver() { + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setApplicationContext(applicationContext); + resolver.setPrefix("/WEB-INF/js/"); + resolver.setCacheable(false); + resolver.setTemplateMode(TemplateMode.JAVASCRIPT); + return resolver; + } + + private ITemplateResolver plainTemplateResolver() { + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setApplicationContext(applicationContext); + resolver.setPrefix("/WEB-INF/txt/"); + resolver.setCacheable(false); + resolver.setTemplateMode(TemplateMode.TEXT); + return resolver; + } @Bean @Description("Spring Message Resolver") diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCSecurity.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCSecurity.java new file mode 100644 index 0000000000..37844a2976 --- /dev/null +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCSecurity.java @@ -0,0 +1,49 @@ +package com.baeldung.thymeleaf.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) +public class WebMVCSecurity extends WebSecurityConfigurerAdapter { + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + public WebMVCSecurity() { + super(); + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser("user1").password("user1Pass").authorities("ROLE_USER"); + } + + @Override + public void configure(final WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + http + .authorizeRequests() + .anyRequest() + .authenticated() + .and() + .httpBasic() + ; + } + +} diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsController.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsController.java new file mode 100644 index 0000000000..f30b9b2078 --- /dev/null +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsController.java @@ -0,0 +1,33 @@ +package com.baeldung.thymeleaf.controller; + +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.HashSet; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * Controller to test expression utility objects: dates, + * + */ +@Controller +public class ExpressionUtilityObjectsController { + + @RequestMapping(value = "/objects", method = RequestMethod.GET) + public String getDates(Model model) { + model.addAttribute("date", new Date()); + model.addAttribute("calendar", Calendar.getInstance()); + model.addAttribute("num", Math.random() * 10); + model.addAttribute("string", "new text"); + model.addAttribute("emptyString", ""); + model.addAttribute("nullString", null); + model.addAttribute("array", new int[] { 1, 3, 4, 5 }); + model.addAttribute("set", new HashSet(Arrays.asList(1, 3, 8))); + return "objects.html"; + } + +} diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java index a28d059acc..f1a394cac4 100644 --- a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java @@ -21,7 +21,7 @@ public class HomeController { DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.getDefault()); model.addAttribute("serverTime", dateFormat.format(new Date())); - return "home"; + return "home.html"; } } diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/InliningController.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/InliningController.java new file mode 100644 index 0000000000..9e3f14ac8e --- /dev/null +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/InliningController.java @@ -0,0 +1,33 @@ +package com.baeldung.thymeleaf.controller; + +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import com.baeldung.thymeleaf.utils.StudentUtils; + +@Controller +public class InliningController { + + @RequestMapping(value = "/html", method = RequestMethod.GET) + public String getExampleHTML(Model model) { + model.addAttribute("title", "Baeldung"); + model.addAttribute("description", "Thymeleaf tutorial"); + return "inliningExample.html"; + } + + @RequestMapping(value = "/js", method = RequestMethod.GET) + public String getExampleJS(Model model) { + model.addAttribute("students", StudentUtils.buildStudents()); + return "studentCheck.js"; + } + + @RequestMapping(value = "/plain", method = RequestMethod.GET) + public String getExamplePlain(Model model) { + model.addAttribute("username", SecurityContextHolder.getContext().getAuthentication().getName()); + model.addAttribute("students", StudentUtils.buildStudents()); + return "studentsList.txt"; + } +} diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java index 912eb521f4..1f40046caa 100644 --- a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java @@ -1,11 +1,9 @@ package com.baeldung.thymeleaf.controller; -import java.util.ArrayList; import java.util.List; import javax.validation.Valid; -import com.baeldung.thymeleaf.model.Student; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; @@ -13,6 +11,9 @@ import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import com.baeldung.thymeleaf.model.Student; +import com.baeldung.thymeleaf.utils.StudentUtils; + /** * Handles requests for the student model. * @@ -24,46 +25,26 @@ public class StudentController { public String saveStudent(@Valid @ModelAttribute Student student, BindingResult errors, Model model) { if (!errors.hasErrors()) { // get mock objects - List students = buildStudents(); + List students = StudentUtils.buildStudents(); // add current student students.add(student); model.addAttribute("students", students); } - return ((errors.hasErrors()) ? "addStudent" : "listStudents"); + return ((errors.hasErrors()) ? "addStudent.html" : "listStudents.html"); } @RequestMapping(value = "/addStudent", method = RequestMethod.GET) public String addStudent(Model model) { model.addAttribute("student", new Student()); - return "addStudent"; + return "addStudent.html"; } @RequestMapping(value = "/listStudents", method = RequestMethod.GET) public String listStudent(Model model) { - model.addAttribute("students", buildStudents()); + model.addAttribute("students", StudentUtils.buildStudents()); - return "listStudents"; + return "listStudents.html"; } - private List buildStudents() { - List students = new ArrayList(); - - Student student1 = new Student(); - student1.setId(1001); - student1.setName("John Smith"); - student1.setGender('M'); - student1.setPercentage(Float.valueOf("80.45")); - - students.add(student1); - - Student student2 = new Student(); - student2.setId(1002); - student2.setName("Jane Williams"); - student2.setGender('F'); - student2.setPercentage(Float.valueOf("60.25")); - - students.add(student2); - return students; - } } diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Student.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Student.java index bce99f286c..202c04358a 100644 --- a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Student.java +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Student.java @@ -12,49 +12,49 @@ import javax.validation.constraints.NotNull; */ public class Student implements Serializable { - private static final long serialVersionUID = -8582553475226281591L; + private static final long serialVersionUID = -8582553475226281591L; - @NotNull(message = "Student ID is required.") - @Min(value = 1000, message = "Student ID must be at least 4 digits.") - private Integer id; + @NotNull(message = "Student ID is required.") + @Min(value = 1000, message = "Student ID must be at least 4 digits.") + private Integer id; - @NotNull(message = "Student name is required.") - private String name; + @NotNull(message = "Student name is required.") + private String name; - @NotNull(message = "Student gender is required.") - private Character gender; + @NotNull(message = "Student gender is required.") + private Character gender; - private Float percentage; + private Float percentage; - public Integer getId() { - return id; - } + public Integer getId() { + return id; + } - public void setId(Integer id) { - this.id = id; - } + public void setId(Integer id) { + this.id = id; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public Character getGender() { - return gender; - } + public Character getGender() { + return gender; + } - public void setGender(Character gender) { - this.gender = gender; - } + public void setGender(Character gender) { + this.gender = gender; + } - public Float getPercentage() { - return percentage; - } + public Float getPercentage() { + return percentage; + } - public void setPercentage(Float percentage) { - this.percentage = percentage; - } + public void setPercentage(Float percentage) { + this.percentage = percentage; + } } diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/ArrayUtil.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/ArrayUtil.java new file mode 100644 index 0000000000..d85c70c1b7 --- /dev/null +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/ArrayUtil.java @@ -0,0 +1,8 @@ +package com.baeldung.thymeleaf.utils; + +public class ArrayUtil { + + public static String[] array(String... args) { + return args; + } +} \ No newline at end of file diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/StudentUtils.java b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/StudentUtils.java new file mode 100644 index 0000000000..f7ed254641 --- /dev/null +++ b/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/StudentUtils.java @@ -0,0 +1,34 @@ +package com.baeldung.thymeleaf.utils; + +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.thymeleaf.model.Student; + +public class StudentUtils { + + private static List students = new ArrayList(); + + public static List buildStudents() { + if (students.isEmpty()){ + Student student1 = new Student(); + student1.setId(1001); + student1.setName("John Smith"); + student1.setGender('M'); + student1.setPercentage(Float.valueOf("80.45")); + + students.add(student1); + + Student student2 = new Student(); + student2.setId(1002); + student2.setName("Jane Williams"); + student2.setGender('F'); + student2.setPercentage(Float.valueOf("60.25")); + + students.add(student2); + } + + return students; + } + +} diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/js/studentCheck.js b/spring-thymeleaf/src/main/webapp/WEB-INF/js/studentCheck.js new file mode 100644 index 0000000000..625e0b37e5 --- /dev/null +++ b/spring-thymeleaf/src/main/webapp/WEB-INF/js/studentCheck.js @@ -0,0 +1,2 @@ +var count = [[${students.size()}]]; +alert("Number of students in group: " + count); diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/txt/studentsList.txt b/spring-thymeleaf/src/main/webapp/WEB-INF/txt/studentsList.txt new file mode 100644 index 0000000000..b27796c6ab --- /dev/null +++ b/spring-thymeleaf/src/main/webapp/WEB-INF/txt/studentsList.txt @@ -0,0 +1,8 @@ +Dear [(${username})], + +This is the list of our students: +[# th:each="s : ${students}"] + - [(${s.name})]. ID: [(${s.id})] +[/] +Thanks, +The Baeldung University \ No newline at end of file diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/csrfAttack.html b/spring-thymeleaf/src/main/webapp/WEB-INF/views/csrfAttack.html new file mode 100644 index 0000000000..7674caa854 --- /dev/null +++ b/spring-thymeleaf/src/main/webapp/WEB-INF/views/csrfAttack.html @@ -0,0 +1,12 @@ + + + + + + +
      + + +
      + + \ No newline at end of file diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/inliningExample.html b/spring-thymeleaf/src/main/webapp/WEB-INF/views/inliningExample.html new file mode 100644 index 0000000000..cd20746c3a --- /dev/null +++ b/spring-thymeleaf/src/main/webapp/WEB-INF/views/inliningExample.html @@ -0,0 +1,12 @@ + + + + +Inlining example + + +

      Title of tutorial: [[${title}]]

      +

      Description: [(${description})]

      + + \ No newline at end of file diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/listStudents.html b/spring-thymeleaf/src/main/webapp/WEB-INF/views/listStudents.html index c25de9eb17..a894e41e88 100644 --- a/spring-thymeleaf/src/main/webapp/WEB-INF/views/listStudents.html +++ b/spring-thymeleaf/src/main/webapp/WEB-INF/views/listStudents.html @@ -4,6 +4,15 @@ Student List + +

      Student List

      diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/objects.html b/spring-thymeleaf/src/main/webapp/WEB-INF/views/objects.html new file mode 100644 index 0000000000..b2a23a7c0f --- /dev/null +++ b/spring-thymeleaf/src/main/webapp/WEB-INF/views/objects.html @@ -0,0 +1,47 @@ + + + + +Expression utility objects + + +

      Date expression utility

      +

      +

      +

      +

      +

      + +

      Calendar expression utility

      +

      +

      +

      +

      +

      + +

      Numbers expression utility

      +

      +

      +

      + +

      +

      + +

      + +

      Calendar expression utility

      +

      +

      +

      +

      +

      +

      + +

      Aggregates expression utility

      +

      +

      +

      +

      + + \ No newline at end of file diff --git a/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerTest.java b/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerTest.java new file mode 100644 index 0000000000..f6a79b7570 --- /dev/null +++ b/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerTest.java @@ -0,0 +1,58 @@ +package com.baeldung.thymeleaf.controller; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + +import javax.servlet.Filter; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.thymeleaf.config.InitSecurity; +import com.baeldung.thymeleaf.config.WebApp; +import com.baeldung.thymeleaf.config.WebMVCConfig; +import com.baeldung.thymeleaf.config.WebMVCSecurity; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { WebApp.class, WebMVCConfig.class, WebMVCSecurity.class, InitSecurity.class }) +public class ExpressionUtilityObjectsControllerTest { + + @Autowired + WebApplicationContext wac; + @Autowired + MockHttpSession session; + + private MockMvc mockMvc; + + @Autowired + private Filter springSecurityFilterChain; + + protected RequestPostProcessor testUser() { + return user("user1").password("user1Pass").roles("USER"); + } + + @Before + public void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build(); + } + + @Test + public void testGetDates() throws Exception{ + mockMvc.perform(get("/objects").with(testUser()).with(csrf())).andExpect(status().isOk()).andExpect(view().name("objects.html")); + } + +} diff --git a/spring-thymeleaf/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java b/spring-thymeleaf/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java new file mode 100644 index 0000000000..3542571bbc --- /dev/null +++ b/spring-thymeleaf/src/test/java/org/baeldung/security/csrf/CsrfEnabledIntegrationTest.java @@ -0,0 +1,78 @@ +package org.baeldung.security.csrf; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import javax.servlet.Filter; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.thymeleaf.config.InitSecurity; +import com.baeldung.thymeleaf.config.WebApp; +import com.baeldung.thymeleaf.config.WebMVCConfig; +import com.baeldung.thymeleaf.config.WebMVCSecurity; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = { WebApp.class, WebMVCConfig.class, WebMVCSecurity.class, InitSecurity.class }) +public class CsrfEnabledIntegrationTest { + + @Autowired + WebApplicationContext wac; + @Autowired + MockHttpSession session; + + private MockMvc mockMvc; + + @Autowired + private Filter springSecurityFilterChain; + + protected RequestPostProcessor testUser() { + return user("user1").password("user1Pass").roles("USER"); + } + + @Before + public void setup() { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build(); + } + + @Test + public void addStudentWithoutCSRF() throws Exception { + mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON).param("id", "1234567").param("name", "Joe").param("gender", "M").with(testUser())).andExpect(status().isForbidden()); + } + + @Test + public void addStudentWithCSRF() throws Exception { + mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON).param("id", "1234567").param("name", "Joe").param("gender", "M").with(testUser()).with(csrf())).andExpect(status().isOk()); + } + + @Test + public void htmlInliningTest() throws Exception { + mockMvc.perform(get("/html").with(testUser()).with(csrf())).andExpect(status().isOk()).andExpect(view().name("inliningExample.html")); + } + + @Test + public void jsInliningTest() throws Exception { + mockMvc.perform(get("/js").with(testUser()).with(csrf())).andExpect(status().isOk()).andExpect(view().name("studentCheck.js")); + } + + @Test + public void plainInliningTest() throws Exception { + mockMvc.perform(get("/plain").with(testUser()).with(csrf())).andExpect(status().isOk()).andExpect(view().name("studentsList.txt")); + } + +} diff --git a/spring-userservice/.springBeans b/spring-userservice/.springBeans new file mode 100644 index 0000000000..ff32b84d3b --- /dev/null +++ b/spring-userservice/.springBeans @@ -0,0 +1,15 @@ + + + 1 + + + + + + + + + + + + diff --git a/spring-userservice/README.md b/spring-userservice/README.md new file mode 100644 index 0000000000..097afc5fc1 --- /dev/null +++ b/spring-userservice/README.md @@ -0,0 +1 @@ +spring-userservice is using a in memory derby db. Right click -> run on server to run the project \ No newline at end of file diff --git a/spring-userservice/pom.xml b/spring-userservice/pom.xml new file mode 100644 index 0000000000..93b01ee49c --- /dev/null +++ b/spring-userservice/pom.xml @@ -0,0 +1,320 @@ + + 4.0.0 + spring-userservice + spring-userservice + 0.0.1-SNAPSHOT + war + + + + + + + org.springframework + spring-orm + ${org.springframework.version} + + + org.springframework + spring-context + ${org.springframework.version} + + + + + + org.hibernate + hibernate-entitymanager + ${hibernate.version} + + + org.hibernate + hibernate-ehcache + ${hibernate.version} + + + xml-apis + xml-apis + 1.4.01 + + + org.javassist + javassist + ${javassist.version} + + + mysql + mysql-connector-java + ${mysql-connector-java.version} + runtime + + + org.springframework.data + spring-data-jpa + ${spring-data-jpa.version} + + + com.h2database + h2 + ${h2.version} + + + + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + + + javax.el + javax.el-api + 2.2.5 + + + + + + com.google.guava + guava + ${guava.version} + + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + test + + + + org.springframework + spring-test + ${org.springframework.version} + test + + + + junit + junit + ${junit.version} + test + + + + org.hamcrest + hamcrest-core + ${org.hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + org.springframework + spring-core + ${org.springframework.version} + + + org.springframework + spring-web + ${org.springframework.version} + + + org.springframework + spring-webmvc + ${org.springframework.version} + + + + org.springframework.security + spring-security-core + ${org.springframework.security.version} + + + org.springframework.security + spring-security-web + ${org.springframework.security.version} + + + org.springframework.security + spring-security-config + ${org.springframework.security.version} + + + + org.apache.derby + derby + 10.12.1.1 + + + org.apache.derby + derbyclient + 10.12.1.1 + + + org.apache.derby + derbynet + 10.12.1.1 + + + org.apache.derby + derbytools + 10.12.1.1 + + + taglibs + standard + 1.1.2 + + + org.springframework.security + spring-security-taglibs + 4.1.3.RELEASE + + + javax.servlet.jsp.jstl + jstl-api + 1.2 + + + org.springframework.boot + spring-boot-test + 1.4.1.RELEASE + + + org.springframework.boot + spring-boot + 1.4.1.RELEASE + + + javax.servlet + javax.servlet-api + 3.1.0 + + + + + spring-userservice + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + + + + + + + + + org.codehaus.cargo + cargo-maven2-plugin + ${cargo-maven2-plugin.version} + + true + + jetty8x + embedded + + + + + + + 8082 + + + + + + + + + + + + 4.1.3.RELEASE + 4.3.2.RELEASE + 3.20.0-GA + + + 5.2.2.Final + 5.1.38 + 1.10.2.RELEASE + 1.4.192 + + + 1.7.13 + 1.1.3 + + + 5.2.2.Final + + + 19.0 + 3.4 + + + 1.3 + 4.12 + 1.10.19 + + 4.4.1 + 4.5 + + 2.9.0 + + + 3.5.1 + 2.6 + 2.19.1 + 2.7 + 1.4.18 + + + + + + \ No newline at end of file diff --git a/spring-userservice/src/main/java/org/baeldung/custom/config/MvcConfig.java b/spring-userservice/src/main/java/org/baeldung/custom/config/MvcConfig.java new file mode 100644 index 0000000000..4a9e737a92 --- /dev/null +++ b/spring-userservice/src/main/java/org/baeldung/custom/config/MvcConfig.java @@ -0,0 +1,42 @@ +package org.baeldung.custom.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; + +@EnableWebMvc +@Configuration +@ComponentScan(basePackages = { "org.baeldung.security" }) +public class MvcConfig extends WebMvcConfigurerAdapter { + + public MvcConfig() { + super(); + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + + registry.addViewController("/"); + registry.addViewController("/index"); + registry.addViewController("/login"); + registry.addViewController("/register"); + } + + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/view/"); + bean.setSuffix(".jsp"); + + return bean; + } +} diff --git a/spring-userservice/src/main/java/org/baeldung/custom/config/PersistenceDerbyJPAConfig.java b/spring-userservice/src/main/java/org/baeldung/custom/config/PersistenceDerbyJPAConfig.java new file mode 100644 index 0000000000..6be7053b78 --- /dev/null +++ b/spring-userservice/src/main/java/org/baeldung/custom/config/PersistenceDerbyJPAConfig.java @@ -0,0 +1,89 @@ +package org.baeldung.custom.config; + +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.baeldung.user.dao.MyUserDAO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-derby.properties" }) +public class PersistenceDerbyJPAConfig { + + @Autowired + private Environment env; + + public PersistenceDerbyJPAConfig() { + super(); + } + + // beans + + @Bean + public LocalContainerEntityManagerFactoryBean myEmf() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + + return em; + } + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(emf); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache")); + hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache")); + // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); + return hibernateProperties; + } + + @Bean + public MyUserDAO myUserDAO() { + final MyUserDAO myUserDAO = new MyUserDAO(); + return myUserDAO; + } +} \ No newline at end of file diff --git a/spring-userservice/src/main/java/org/baeldung/custom/config/SecSecurityConfig.java b/spring-userservice/src/main/java/org/baeldung/custom/config/SecSecurityConfig.java new file mode 100644 index 0000000000..44df02980f --- /dev/null +++ b/spring-userservice/src/main/java/org/baeldung/custom/config/SecSecurityConfig.java @@ -0,0 +1,75 @@ +package org.baeldung.custom.config; + +import org.baeldung.security.MyUserDetailsService; +import org.baeldung.user.service.MyUserService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +@EnableWebSecurity +@Profile("!https") +public class SecSecurityConfig extends WebSecurityConfigurerAdapter { + + public SecSecurityConfig() { + super(); + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + // @formatter:off + auth.authenticationProvider(authenticationProvider()); + // @formatter:on + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http + .csrf().disable() + .authorizeRequests() + .antMatchers("/*").permitAll() + .and() + .formLogin() + .loginPage("/login") + .loginProcessingUrl("/login") + .defaultSuccessUrl("/",true) + .failureUrl("/login?error=true") + .and() + .logout() + .logoutUrl("/logout") + .deleteCookies("JSESSIONID") + .logoutSuccessUrl("/"); + // @formatter:on + } + + @Bean + public DaoAuthenticationProvider authenticationProvider() { + final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + authProvider.setUserDetailsService(myUserDetailsService()); + authProvider.setPasswordEncoder(encoder()); + return authProvider; + } + + @Bean + public PasswordEncoder encoder() { + return new BCryptPasswordEncoder(11); + } + + @Bean + public MyUserDetailsService myUserDetailsService() { + return new MyUserDetailsService(); + } + + @Bean + public MyUserService myUserService() { + return new MyUserService(); + } +} diff --git a/spring-userservice/src/main/java/org/baeldung/persistence/model/MyUser.java b/spring-userservice/src/main/java/org/baeldung/persistence/model/MyUser.java new file mode 100644 index 0000000000..804d391641 --- /dev/null +++ b/spring-userservice/src/main/java/org/baeldung/persistence/model/MyUser.java @@ -0,0 +1,50 @@ +package org.baeldung.persistence.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(schema = "spring_custom_user_service") +public class MyUser { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + + @Column(unique = true, nullable = false) + private String username; + + @Column(nullable = false) + private String password; + + public MyUser() { + } + + public int getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(final String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(final String password) { + this.password = password; + } +} diff --git a/spring-userservice/src/main/java/org/baeldung/security/MyUserDetailsService.java b/spring-userservice/src/main/java/org/baeldung/security/MyUserDetailsService.java new file mode 100644 index 0000000000..fe97984af8 --- /dev/null +++ b/spring-userservice/src/main/java/org/baeldung/security/MyUserDetailsService.java @@ -0,0 +1,35 @@ +package org.baeldung.security; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; + +import org.baeldung.persistence.model.MyUser; +import org.baeldung.user.dao.MyUserDAO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service("userDetailsService") +public class MyUserDetailsService implements UserDetailsService { + + @Autowired + MyUserDAO myUserDAO; + + @Override + public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { + final MyUser user = myUserDAO.findByUsername(username); + + if (user == null) { + throw new UsernameNotFoundException("No user found with username: " + username); + } + return new User(user.getUsername(), user.getPassword(), Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))); + + } + +} diff --git a/spring-userservice/src/main/java/org/baeldung/security/UserController.java b/spring-userservice/src/main/java/org/baeldung/security/UserController.java new file mode 100644 index 0000000000..b1c96e72c0 --- /dev/null +++ b/spring-userservice/src/main/java/org/baeldung/security/UserController.java @@ -0,0 +1,52 @@ +package org.baeldung.security; + +import javax.annotation.Resource; + +import org.baeldung.user.service.MyUserService; +import org.baeldung.web.MyUserDto; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +public class UserController { + + @Resource + MyUserService myUserService; + + @RequestMapping(value = "/register", method = RequestMethod.POST) + public String registerUserAccount(final MyUserDto accountDto, final Model model) { + final Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + model.addAttribute("name", auth.getName()); + try { + myUserService.registerNewUserAccount(accountDto); + model.addAttribute("message", "Registration successful"); + return "index"; + } + catch(final Exception exc){ + model.addAttribute("message", "Registration failed"); + + return "index"; + } + } + + @RequestMapping(value = "/", method = RequestMethod.GET) + public String getHomepage(final Model model) { + final Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + model.addAttribute("name", auth.getName()); + return "index"; + } + + @RequestMapping(value = "/register", method = RequestMethod.GET) + public String getRegister() { + return "register"; + } + + @RequestMapping(value = "/login", method = RequestMethod.GET) + public String getLogin() { + return "login"; + } +} diff --git a/spring-userservice/src/main/java/org/baeldung/user/dao/MyUserDAO.java b/spring-userservice/src/main/java/org/baeldung/user/dao/MyUserDAO.java new file mode 100644 index 0000000000..4cc9f61b4a --- /dev/null +++ b/spring-userservice/src/main/java/org/baeldung/user/dao/MyUserDAO.java @@ -0,0 +1,46 @@ +package org.baeldung.user.dao; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import org.baeldung.persistence.model.MyUser; +import org.springframework.stereotype.Repository; + +@Repository +public class MyUserDAO { + + @PersistenceContext + private EntityManager entityManager; + + public MyUser findByUsername(final String username) { + final Query query = entityManager.createQuery("from MyUser where username=:username", MyUser.class); + query.setParameter("username", username); + final List result = query.getResultList(); + if (result != null && result.size() > 0) { + return result.get(0); + } else + return null; + } + + public MyUser save(final MyUser user) { + entityManager.persist(user); + return user; + } + + public void removeUserByUsername(String username) { + final Query query = entityManager.createQuery("delete from MyUser where username=:username"); + query.setParameter("username", username); + query.executeUpdate(); + } + + public EntityManager getEntityManager() { + return entityManager; + } + + public void setEntityManager(final EntityManager entityManager) { + this.entityManager = entityManager; + } +} diff --git a/spring-userservice/src/main/java/org/baeldung/user/service/MyUserService.java b/spring-userservice/src/main/java/org/baeldung/user/service/MyUserService.java new file mode 100644 index 0000000000..1e05541998 --- /dev/null +++ b/spring-userservice/src/main/java/org/baeldung/user/service/MyUserService.java @@ -0,0 +1,49 @@ +package org.baeldung.user.service; + +import org.baeldung.persistence.model.MyUser; +import org.baeldung.user.dao.MyUserDAO; +import org.baeldung.web.MyUserDto; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class MyUserService { + + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + MyUserDAO myUserDAO; + + public MyUser registerNewUserAccount(final MyUserDto accountDto) throws Exception { + if (usernameExists(accountDto.getUsername())) { + throw new Exception("There is an account with that username: " + accountDto.getUsername()); + } + final MyUser user = new MyUser(); + + user.setUsername(accountDto.getUsername()); + user.setPassword(passwordEncoder.encode(accountDto.getPassword())); + return myUserDAO.save(user); + } + + public MyUser getUserByUsername(final String username) { + final MyUser user = myUserDAO.findByUsername(username); + return user; + } + + public void removeUserByUsername(String username){ + myUserDAO.removeUserByUsername(username); + } + + private boolean usernameExists(final String username) { + final MyUser user = myUserDAO.findByUsername(username); + if (user != null) { + return true; + } + return false; + } + +} diff --git a/spring-userservice/src/main/java/org/baeldung/web/MyUserDto.java b/spring-userservice/src/main/java/org/baeldung/web/MyUserDto.java new file mode 100644 index 0000000000..c572208913 --- /dev/null +++ b/spring-userservice/src/main/java/org/baeldung/web/MyUserDto.java @@ -0,0 +1,29 @@ +package org.baeldung.web; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +public class MyUserDto { + @NotNull + @Size(min = 1) + private String username; + + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(final String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(final String password) { + this.password = password; + } + +} diff --git a/spring-userservice/src/main/resources/persistence-derby.properties b/spring-userservice/src/main/resources/persistence-derby.properties new file mode 100644 index 0000000000..e808fdc288 --- /dev/null +++ b/spring-userservice/src/main/resources/persistence-derby.properties @@ -0,0 +1,12 @@ +# jdbc.X +jdbc.driverClassName=org.apache.derby.jdbc.EmbeddedDriver +jdbc.url=jdbc:derby:memory:spring_custom_user_service;create=true +jdbc.user=tutorialuser +jdbc.pass=tutorialpass + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.DerbyDialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create +hibernate.cache.use_second_level_cache=false +hibernate.cache.use_query_cache=false \ No newline at end of file diff --git a/spring-userservice/src/main/webapp/META-INF/MANIFEST.MF b/spring-userservice/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..254272e1c0 --- /dev/null +++ b/spring-userservice/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/spring-userservice/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml b/spring-userservice/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml new file mode 100644 index 0000000000..25d1d4d22f --- /dev/null +++ b/spring-userservice/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /WEB-INF/views/ + + + .jsp + + + + + + + + + + + + + + + ${hibernate.hbm2ddl.auto} + ${hibernate.dialect} + ${hibernate.cache.use_second_level_cache} + ${hibernate.cache.use_query_cache} + + + + + + + + + + + + + + + + + + + diff --git a/spring-userservice/src/main/webapp/WEB-INF/views/index.jsp b/spring-userservice/src/main/webapp/WEB-INF/views/index.jsp new file mode 100644 index 0000000000..0c89257cd2 --- /dev/null +++ b/spring-userservice/src/main/webapp/WEB-INF/views/index.jsp @@ -0,0 +1,35 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@ taglib prefix="c" + uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %> + + + + + +Welcome! + + + + + + + +Register +

      + +Login + +

      +${message } +

      + +Hello, ${name }! +
      +
      +Logout +
      + + + \ No newline at end of file diff --git a/spring-userservice/src/main/webapp/WEB-INF/views/login.jsp b/spring-userservice/src/main/webapp/WEB-INF/views/login.jsp new file mode 100644 index 0000000000..29431f426d --- /dev/null +++ b/spring-userservice/src/main/webapp/WEB-INF/views/login.jsp @@ -0,0 +1,29 @@ +<%@ taglib prefix="c" + uri="http://java.sun.com/jsp/jstl/core" %> + + + + + +

      Login

      + +
      + +
      + + + + + + + + + + + +
      User:
      Password:
      + + + Username or password invalid! + + \ No newline at end of file diff --git a/spring-userservice/src/main/webapp/WEB-INF/views/register.jsp b/spring-userservice/src/main/webapp/WEB-INF/views/register.jsp new file mode 100644 index 0000000000..e6e9d373a0 --- /dev/null +++ b/spring-userservice/src/main/webapp/WEB-INF/views/register.jsp @@ -0,0 +1,23 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@ taglib prefix="c" + uri="http://java.sun.com/jsp/jstl/core" %> + + + + +Welcome! + + + + + +Register here:

      +
      +Username:
      +Password:
      + +
      + + + \ No newline at end of file diff --git a/spring-userservice/src/main/webapp/WEB-INF/web.xml b/spring-userservice/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..b526774179 --- /dev/null +++ b/spring-userservice/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,51 @@ + + + + Spring MVC Application + + + + + + mvc-dispatcher + org.springframework.web.servlet.DispatcherServlet + 1 + + + mvc-dispatcher + / + + + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + springSecurityFilterChain + /* + + + + index.jsp + + + \ No newline at end of file diff --git a/spring-userservice/src/test/java/org/baeldung/userservice/CustomUserDetailsServiceTest.java b/spring-userservice/src/test/java/org/baeldung/userservice/CustomUserDetailsServiceTest.java new file mode 100644 index 0000000000..6e1cd67e06 --- /dev/null +++ b/spring-userservice/src/test/java/org/baeldung/userservice/CustomUserDetailsServiceTest.java @@ -0,0 +1,85 @@ +package org.baeldung.userservice; + +import org.baeldung.custom.config.MvcConfig; +import org.baeldung.custom.config.PersistenceDerbyJPAConfig; +import org.baeldung.custom.config.SecSecurityConfig; +import org.baeldung.user.service.MyUserService; +import org.baeldung.web.MyUserDto; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import static org.junit.Assert.*; + +import java.util.logging.Level; +import java.util.logging.Logger; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = { MvcConfig.class, PersistenceDerbyJPAConfig.class, SecSecurityConfig.class }) +@WebAppConfiguration +public class CustomUserDetailsServiceTest { + + private static final Logger LOG = Logger.getLogger("CustomUserDetailsServiceTest"); + + public static final String USERNAME = "user"; + public static final String PASSWORD = "pass"; + public static final String USERNAME2 = "user2"; + + @Autowired + MyUserService myUserService; + + @Autowired + AuthenticationProvider authenticationProvider; + + @Test + public void givenExistingUser_whenAuthenticate_thenRetrieveFromDb() { + try { + MyUserDto userDTO = new MyUserDto(); + userDTO.setUsername(USERNAME); + userDTO.setPassword(PASSWORD); + + myUserService.registerNewUserAccount(userDTO); + + UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(USERNAME, PASSWORD); + Authentication authentication = authenticationProvider.authenticate(auth); + + assertEquals(authentication.getName(), USERNAME); + + } catch (Exception exc) { + LOG.log(Level.SEVERE, "Error creating account"); + } finally { + myUserService.removeUserByUsername(USERNAME); + } + } + + @Test (expected = BadCredentialsException.class) + public void givenIncorrectUser_whenAuthenticate_thenBadCredentialsException() { + try { + MyUserDto userDTO = new MyUserDto(); + userDTO.setUsername(USERNAME); + userDTO.setPassword(PASSWORD); + + try { + myUserService.registerNewUserAccount(userDTO); + } + catch (Exception exc) { + LOG.log(Level.SEVERE, "Error creating account"); + } + + UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(USERNAME2, PASSWORD); + Authentication authentication = authenticationProvider.authenticate(auth); + } + finally { + myUserService.removeUserByUsername(USERNAME); + } + } + +} diff --git a/spring-zuul/.project b/spring-zuul/.project deleted file mode 100644 index cc40816960..0000000000 --- a/spring-zuul/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - spring-zuul - - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.m2e.core.maven2Nature - - diff --git a/spring-zuul/README.md b/spring-zuul/README.md new file mode 100644 index 0000000000..41a77f70c8 --- /dev/null +++ b/spring-zuul/README.md @@ -0,0 +1,7 @@ +========= + +## Spring REST with a Zuul + + +### Relevant Articles: +- [Spring REST with a Zuul Proxy](http://www.baeldung.com/spring-rest-with-zuul-proxy) diff --git a/spring-zuul/pom.xml b/spring-zuul/pom.xml index 6ad1d0be34..75ff467527 100644 --- a/spring-zuul/pom.xml +++ b/spring-zuul/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-zuul 1.0.0-SNAPSHOT @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.3.1.RELEASE + 1.3.3.RELEASE @@ -65,19 +65,19 @@ - 4.2.2.RELEASE - 4.0.3.RELEASE + 4.2.5.RELEASE + 4.0.4.RELEASE - 2.5.1 + 2.7.2 1.7.12 1.1.3 - 18.0 + 19.0 3.3.2 @@ -88,13 +88,13 @@ 4.4 4.4 - 2.4.0 + 2.9.0 - 3.3 + 3.5.1 2.6 - 2.19 - 1.4.16 + 2.19.1 + 1.4.18 diff --git a/spring-zuul/spring-zuul-foos-resource/.classpath b/spring-zuul/spring-zuul-foos-resource/.classpath deleted file mode 100644 index 0cad5db2d0..0000000000 --- a/spring-zuul/spring-zuul-foos-resource/.classpath +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-zuul/spring-zuul-foos-resource/.project b/spring-zuul/spring-zuul-foos-resource/.project deleted file mode 100644 index 8d04c873fb..0000000000 --- a/spring-zuul/spring-zuul-foos-resource/.project +++ /dev/null @@ -1,48 +0,0 @@ - - - spring-zuul-foos-resource - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-zuul/spring-zuul-foos-resource/pom.xml b/spring-zuul/spring-zuul-foos-resource/pom.xml index 6d5e0e52cf..56ca1959ca 100644 --- a/spring-zuul/spring-zuul-foos-resource/pom.xml +++ b/spring-zuul/spring-zuul-foos-resource/pom.xml @@ -6,7 +6,7 @@ war - org.baeldung + com.baeldung spring-zuul 1.0.0-SNAPSHOT diff --git a/spring-zuul/spring-zuul-ui/.classpath b/spring-zuul/spring-zuul-ui/.classpath deleted file mode 100644 index 5c3ac53820..0000000000 --- a/spring-zuul/spring-zuul-ui/.classpath +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-zuul/spring-zuul-ui/.project b/spring-zuul/spring-zuul-ui/.project deleted file mode 100644 index ec0f2cde81..0000000000 --- a/spring-zuul/spring-zuul-ui/.project +++ /dev/null @@ -1,48 +0,0 @@ - - - spring-zuul-ui - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - org.springframework.ide.eclipse.core.springbuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.springframework.ide.eclipse.core.springnature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/spring-zuul/spring-zuul-ui/pom.xml b/spring-zuul/spring-zuul-ui/pom.xml index 65a025f849..9eaf4b7c45 100644 --- a/spring-zuul/spring-zuul-ui/pom.xml +++ b/spring-zuul/spring-zuul-ui/pom.xml @@ -6,7 +6,7 @@ war - org.baeldung + com.baeldung spring-zuul 1.0.0-SNAPSHOT diff --git a/src/main/java/org/baeldung/event/OnRegistrationCompleteEvent.java b/src/main/java/org/baeldung/event/OnRegistrationCompleteEvent.java deleted file mode 100644 index 9094099ecc..0000000000 --- a/src/main/java/org/baeldung/event/OnRegistrationCompleteEvent.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.baeldung.event; - -import java.util.Locale; - -import org.baeldung.persistence.model.User; -import org.springframework.context.ApplicationEvent; - -@SuppressWarnings("serial") -public class OnRegistrationCompleteEvent extends ApplicationEvent { - - private final String appUrl; - private final Locale locale; - private final User user; - - public OnRegistrationCompleteEvent(User user, Locale locale, String appUrl) { - super(user); - this.user = user; - this.locale = locale; - this.appUrl = appUrl; - } - - public String getAppUrl() { - return appUrl; - } - - public Locale getLocale() { - return locale; - } - - public User getUser() { - return user; - } -} diff --git a/src/main/java/org/baeldung/event/listener/RegistrationListener.java b/src/main/java/org/baeldung/event/listener/RegistrationListener.java deleted file mode 100644 index 5c848c7433..0000000000 --- a/src/main/java/org/baeldung/event/listener/RegistrationListener.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.baeldung.event.listener; - -import java.util.UUID; - -import org.baeldung.event.OnRegistrationCompleteEvent; -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.service.IUserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationListener; -import org.springframework.context.MessageSource; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.stereotype.Component; - -@Component -public class RegistrationListener implements ApplicationListener { - @Autowired - private IUserService service; - - @Autowired - private MessageSource messages; - - @Autowired - private JavaMailSender mailSender; - - @Override - public void onApplicationEvent(OnRegistrationCompleteEvent event) { - this.confirmRegistration(event); - } - - private void confirmRegistration(OnRegistrationCompleteEvent event) { - User user = event.getUser(); - String token = UUID.randomUUID().toString(); - service.createVerificationTokenForUser(user, token); - - String recipientAddress = user.getEmail(); - String subject = "Registration Confirmation"; - String confirmationUrl = event.getAppUrl() + "/regitrationConfirm.html?token=" + token; - String message = messages.getMessage("message.regSucc", null, event.getLocale()); - SimpleMailMessage email = new SimpleMailMessage(); - email.setTo(recipientAddress); - email.setSubject(subject); - email.setText(message + " \r\n" + "http://localhost:8080" + confirmationUrl); - mailSender.send(email); - } -} diff --git a/src/main/java/org/baeldung/hashing/HashGenerator.java b/src/main/java/org/baeldung/hashing/HashGenerator.java deleted file mode 100644 index bf9620a052..0000000000 --- a/src/main/java/org/baeldung/hashing/HashGenerator.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.baeldung.hashing; - -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; - -public class HashGenerator { - - public String getHashedPassword(String password) { - BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - String hashedPassword = passwordEncoder.encode(password); - return hashedPassword; - } -} diff --git a/src/main/java/org/baeldung/persistence/dao/UserRepository.java b/src/main/java/org/baeldung/persistence/dao/UserRepository.java deleted file mode 100644 index 12f07d8692..0000000000 --- a/src/main/java/org/baeldung/persistence/dao/UserRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.baeldung.persistence.dao; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.baeldung.persistence.model.User; - -public interface UserRepository extends JpaRepository { - public User findByEmail(String email); - - public void delete(User user); - -} diff --git a/src/main/java/org/baeldung/persistence/dao/VerificationTokenRepository.java b/src/main/java/org/baeldung/persistence/dao/VerificationTokenRepository.java deleted file mode 100644 index f9fc850d41..0000000000 --- a/src/main/java/org/baeldung/persistence/dao/VerificationTokenRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.baeldung.persistence.dao; - -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.model.VerificationToken; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface VerificationTokenRepository extends JpaRepository { - - public VerificationToken findByToken(String token); - - public VerificationToken findByUser(User user); -} diff --git a/src/main/java/org/baeldung/persistence/model/Role.java b/src/main/java/org/baeldung/persistence/model/Role.java deleted file mode 100644 index b6d495a266..0000000000 --- a/src/main/java/org/baeldung/persistence/model/Role.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.baeldung.persistence.model; - -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; -import javax.persistence.Table; - -@Entity -@Table -public class Role { - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - @OneToOne(targetEntity = User.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL) - @JoinColumn(name = "user_id") - private User user; - - private Integer role; - - public Role() { - super(); - } - - public Role(Integer role) { - super(); - this.role = role; - } - - public Role(Integer role, User user) { - super(); - this.role = role; - this.user = user; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public Integer getRole() { - return role; - } - - public void setRole(Integer role) { - this.role = role; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((role == null) ? 0 : role.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final Role role = (Role) obj; - if (!role.equals(role.role)) - return false; - return true; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Role [role=").append(role).append("]").append("[id=").append(id).append("]"); - return builder.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/baeldung/persistence/model/User.java b/src/main/java/org/baeldung/persistence/model/User.java deleted file mode 100644 index d2d56cec53..0000000000 --- a/src/main/java/org/baeldung/persistence/model/User.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.baeldung.persistence.model; - -import javax.persistence.CascadeType; -//ERASE -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.OneToOne; - -@Entity -public class User { - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String firstName; - - private String lastName; - - private String email; - - private String password; - - private boolean enabled; - - // ERASE - @Column(name = "token_expired") - private boolean tokenExpired; - - @OneToOne(mappedBy = "user", fetch = FetchType.EAGER, cascade = CascadeType.ALL) - private Role role; - - public User() { - super(); - this.enabled = false; - this.tokenExpired = false; - } - - // - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getEmail() { - return email; - } - - public void setEmail(String username) { - this.email = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Role getRole() { - return role; - } - - public void setRole(Role role) { - this.role = role; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public boolean isTokenExpired() { - return tokenExpired; - } - - public void setTokenExpired(boolean expired) { - this.tokenExpired = expired; - } - - // - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((email == null) ? 0 : email.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final User user = (User) obj; - if (!email.equals(user.email)) - return false; - return true; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("User [firstName=").append(firstName).append("]").append("[lastName=").append(lastName).append("]").append("[username").append(email).append("]"); - return builder.toString(); - } - -} \ No newline at end of file diff --git a/src/main/java/org/baeldung/persistence/model/VerificationToken.java b/src/main/java/org/baeldung/persistence/model/VerificationToken.java deleted file mode 100644 index d7556fdf5b..0000000000 --- a/src/main/java/org/baeldung/persistence/model/VerificationToken.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.baeldung.persistence.model; - -import java.util.Calendar; -import java.sql.Date; -import java.sql.Timestamp; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToOne; - -@Entity -public class VerificationToken { - - private static final int EXPIRATION = 60 * 24; - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String token; - - @OneToOne(targetEntity = User.class, fetch = FetchType.EAGER) - @JoinColumn(nullable = false, name = "user_id") - private User user; - - @Column(name = "expiry_date") - private Date expiryDate; - - public VerificationToken() { - super(); - } - - public VerificationToken(String token) { - super(); - - this.token = token; - this.expiryDate = calculateExpiryDate(EXPIRATION); - } - - public VerificationToken(String token, User user) { - super(); - - this.token = token; - this.user = user; - this.expiryDate = calculateExpiryDate(EXPIRATION); - } - - // - - public String getToken() { - return token; - } - - public void setToken(String token) { - this.token = token; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public Date getExpiryDate() { - return expiryDate; - } - - public void setExpiryDate(Date expiryDate) { - this.expiryDate = expiryDate; - } - - private Date calculateExpiryDate(int expiryTimeInMinutes) { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Timestamp(cal.getTime().getTime())); - cal.add(Calendar.MINUTE, expiryTimeInMinutes); - return new Date(cal.getTime().getTime()); - } - - // - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((expiryDate == null) ? 0 : expiryDate.hashCode()); - result = prime * result + ((token == null) ? 0 : token.hashCode()); - result = prime * result + ((user == null) ? 0 : user.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - VerificationToken other = (VerificationToken) obj; - if (expiryDate == null) { - if (other.expiryDate != null) - return false; - } else if (!expiryDate.equals(other.expiryDate)) - return false; - if (token == null) { - if (other.token != null) - return false; - } else if (!token.equals(other.token)) - return false; - if (user == null) { - if (other.user != null) - return false; - } else if (!user.equals(other.user)) - return false; - return true; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("Token [String=").append(token).append("]").append("[Expires").append(expiryDate).append("]"); - return builder.toString(); - } - -} diff --git a/src/main/java/org/baeldung/persistence/service/IUserService.java b/src/main/java/org/baeldung/persistence/service/IUserService.java deleted file mode 100644 index bc1c9bc9a3..0000000000 --- a/src/main/java/org/baeldung/persistence/service/IUserService.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.baeldung.persistence.service; - -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.model.VerificationToken; -import org.baeldung.validation.service.EmailExistsException; - -public interface IUserService { - - User registerNewUserAccount(UserDto accountDto) throws EmailExistsException; - - User getUser(String verificationToken); - - void saveRegisteredUser(User user); - - void deleteUser(User user); - - void createVerificationTokenForUser(User user, String token); - - VerificationToken getVerificationToken(String VerificationToken); - -} diff --git a/src/main/java/org/baeldung/persistence/service/UserDto.java b/src/main/java/org/baeldung/persistence/service/UserDto.java deleted file mode 100644 index 29a59be2fc..0000000000 --- a/src/main/java/org/baeldung/persistence/service/UserDto.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.baeldung.persistence.service; - -import javax.validation.constraints.NotNull; - -import org.baeldung.validation.service.PasswordMatches; -import org.baeldung.validation.service.ValidEmail; -import org.hibernate.validator.constraints.NotEmpty; - -@PasswordMatches -public class UserDto { - @NotNull - @NotEmpty - private String firstName; - - @NotNull - @NotEmpty - private String lastName; - - @NotNull - @NotEmpty - private String password; - - @NotNull - @NotEmpty - private String matchingPassword; - - @ValidEmail - @NotNull - @NotEmpty - private String email; - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - private Integer role; - - public Integer getRole() { - return role; - } - - public void setRole(Integer role) { - this.role = role; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getMatchingPassword() { - return matchingPassword; - } - - public void setMatchingPassword(String matchingPassword) { - this.matchingPassword = matchingPassword; - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append("User [firstName=").append(firstName).append("]").append("[lastName=").append(lastName).append("]").append("[email").append(email).append("]").append("[password").append(password).append("]"); - return builder.toString(); - } -} diff --git a/src/main/java/org/baeldung/persistence/service/UserService.java b/src/main/java/org/baeldung/persistence/service/UserService.java deleted file mode 100644 index a0b8ed4a4b..0000000000 --- a/src/main/java/org/baeldung/persistence/service/UserService.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.baeldung.persistence.service; - -import javax.transaction.Transactional; - -import org.baeldung.hashing.HashGenerator; -import org.baeldung.persistence.dao.UserRepository; -import org.baeldung.persistence.dao.VerificationTokenRepository; -import org.baeldung.persistence.model.Role; -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.model.VerificationToken; -import org.baeldung.validation.service.EmailExistsException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -@Transactional -public class UserService implements IUserService { - @Autowired - private UserRepository repository; - - @Autowired - private VerificationTokenRepository tokenRepository; - - @Autowired - private HashGenerator hashGenerator; - - @Override - public User registerNewUserAccount(UserDto accountDto) throws EmailExistsException { - if (emailExist(accountDto.getEmail())) { - throw new EmailExistsException("There is an account with that email adress: " + accountDto.getEmail()); - } - User user = new User(); - user.setFirstName(accountDto.getFirstName()); - user.setLastName(accountDto.getLastName()); - String hashedPassword = hashGenerator.getHashedPassword(accountDto.getPassword()); - user.setPassword(hashedPassword); - user.setEmail(accountDto.getEmail()); - user.setRole(new Role(Integer.valueOf(1), user)); - return repository.save(user); - } - - @Override - public User getUser(String verificationToken) { - User user = tokenRepository.findByToken(verificationToken).getUser(); - return user; - } - - @Override - public VerificationToken getVerificationToken(String VerificationToken) { - return tokenRepository.findByToken(VerificationToken); - } - - @Override - public void saveRegisteredUser(User user) { - repository.save(user); - } - - @Override - public void deleteUser(User user) { - repository.delete(user); - } - - @Override - public void createVerificationTokenForUser(User user, String token) { - VerificationToken myToken = new VerificationToken(token, user); - tokenRepository.save(myToken); - } - - private boolean emailExist(String email) { - User user = repository.findByEmail(email); - if (user != null) { - return true; - } - return false; - } - -} diff --git a/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java b/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java deleted file mode 100644 index a4cdc708d9..0000000000 --- a/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.baeldung.security; - -import java.io.IOException; -import java.util.Collection; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.web.DefaultRedirectStrategy; -import org.springframework.security.web.RedirectStrategy; -import org.springframework.security.web.WebAttributes; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; - -public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler { - private final Logger logger = LoggerFactory.getLogger(getClass()); - - private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); - - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { - handle(request, response, authentication); - HttpSession session = request.getSession(false); - if (session != null) { - session.setMaxInactiveInterval(30); - } - clearAuthenticationAttributes(request); - } - - protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { - String targetUrl = determineTargetUrl(authentication); - - if (response.isCommitted()) { - logger.debug("Response has already been committed. Unable to redirect to " + targetUrl); - return; - } - - redirectStrategy.sendRedirect(request, response, targetUrl); - } - - protected String determineTargetUrl(Authentication authentication) { - boolean isUser = false; - boolean isAdmin = false; - Collection authorities = authentication.getAuthorities(); - for (GrantedAuthority grantedAuthority : authorities) { - if (grantedAuthority.getAuthority().equals("ROLE_USER")) { - isUser = true; - break; - } else if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) { - isAdmin = true; - break; - } - } - if (isUser) { - return "/homepage.html?user=" + authentication.getName(); - } else if (isAdmin) { - return "/console.html"; - } else { - throw new IllegalStateException(); - } - } - - protected void clearAuthenticationAttributes(HttpServletRequest request) { - HttpSession session = request.getSession(false); - if (session == null) { - return; - } - session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); - } - - public void setRedirectStrategy(RedirectStrategy redirectStrategy) { - this.redirectStrategy = redirectStrategy; - } - - protected RedirectStrategy getRedirectStrategy() { - return redirectStrategy; - } -} \ No newline at end of file diff --git a/src/main/java/org/baeldung/security/MyUserDetailsService.java b/src/main/java/org/baeldung/security/MyUserDetailsService.java deleted file mode 100644 index a103504055..0000000000 --- a/src/main/java/org/baeldung/security/MyUserDetailsService.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.baeldung.security; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.baeldung.persistence.dao.UserRepository; -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.service.IUserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.MessageSource; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -@Transactional -public class MyUserDetailsService implements UserDetailsService { - - @Autowired - private UserRepository userRepository; - @Autowired - private IUserService service; - @Autowired - private MessageSource messages; - - public MyUserDetailsService() { - - } - - public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { - boolean enabled = true; - boolean accountNonExpired = true; - boolean credentialsNonExpired = true; - boolean accountNonLocked = true; - try { - User user = userRepository.findByEmail(email); - if (user == null) { - return new org.springframework.security.core.userdetails.User(" ", " ", enabled, true, true, true, getAuthorities(new Integer(1))); - } - - return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), user.isEnabled(), accountNonExpired, credentialsNonExpired, accountNonLocked, getAuthorities(user.getRole().getRole())); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private Collection getAuthorities(Integer role) { - List authList = getGrantedAuthorities(getRoles(role)); - return authList; - } - - public List getRoles(Integer role) { - List roles = new ArrayList(); - if (role.intValue() == 2) { - roles.add("ROLE_ADMIN"); - } else if (role.intValue() == 1) { - roles.add("ROLE_USER"); - } - return roles; - } - - private static List getGrantedAuthorities(List roles) { - List authorities = new ArrayList(); - for (String role : roles) { - authorities.add(new SimpleGrantedAuthority(role)); - } - return authorities; - } -} diff --git a/src/main/java/org/baeldung/spring/AppConfig.java b/src/main/java/org/baeldung/spring/AppConfig.java deleted file mode 100644 index 4708c53a14..0000000000 --- a/src/main/java/org/baeldung/spring/AppConfig.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.baeldung.spring; - -import java.util.Properties; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.PropertySource; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; -import org.springframework.core.env.Environment; -import org.springframework.mail.javamail.JavaMailSenderImpl; - -@Configuration -@ComponentScan(basePackages = { "org.baeldung.event.service", "org.baeldung.event", "org.baeldung.persistence.service", "org.baeldung.persistence.dao" }) -@Import({ MvcConfig.class, PersistenceJPAConfig.class, SecSecurityConfig.class }) -@PropertySource("classpath:application.properties") -public class AppConfig { - @Autowired - private Environment env; - - @Bean - public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() { - return new PropertySourcesPlaceholderConfigurer(); - } - - @Bean - public JavaMailSenderImpl javaMailSenderImpl() { - JavaMailSenderImpl mailSenderImpl = new JavaMailSenderImpl(); - mailSenderImpl.setHost(env.getProperty("smtp.host")); - mailSenderImpl.setPort(env.getProperty("smtp.port", Integer.class)); - mailSenderImpl.setProtocol(env.getProperty("smtp.protocol")); - mailSenderImpl.setUsername(env.getProperty("smtp.username")); - mailSenderImpl.setPassword(env.getProperty("smtp.password")); - Properties javaMailProps = new Properties(); - javaMailProps.put("mail.smtp.auth", true); - javaMailProps.put("mail.smtp.starttls.enable", true); - mailSenderImpl.setJavaMailProperties(javaMailProps); - return mailSenderImpl; - } - -} \ No newline at end of file diff --git a/src/main/java/org/baeldung/spring/MvcConfig.java b/src/main/java/org/baeldung/spring/MvcConfig.java deleted file mode 100644 index 3294ac2788..0000000000 --- a/src/main/java/org/baeldung/spring/MvcConfig.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.baeldung.spring; - -import java.util.Locale; - -import org.baeldung.hashing.HashGenerator; -import org.baeldung.validation.service.EmailValidator; -import org.baeldung.validation.service.PasswordMatchesValidator; -import org.springframework.context.MessageSource; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.ReloadableResourceBundleMessageSource; -import org.springframework.web.servlet.LocaleResolver; -import org.springframework.web.servlet.ViewResolver; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -import org.springframework.web.servlet.i18n.CookieLocaleResolver; -import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; -import org.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.JstlView; - -@Configuration -@ComponentScan(basePackages = { "org.baeldung.web.controller", "org.baeldung.persistence.service", "org.baeldung.persistence.dao" }) -@EnableWebMvc -public class MvcConfig extends WebMvcConfigurerAdapter { - - public MvcConfig() { - super(); - } - - // API - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); - registry.addViewController("/login.html"); - registry.addViewController("/logout.html"); - registry.addViewController("/homepage.html"); - registry.addViewController("/expiredAccount.html"); - registry.addViewController("/regitrationConfirm.html"); - registry.addViewController("/badUser.html"); - registry.addViewController("/emailError.html"); - registry.addViewController("/home.html"); - registry.addViewController("/invalidSession.html"); - registry.addViewController("/console.html"); - registry.addViewController("/admin.html"); - registry.addViewController("/registration.html"); - registry.addViewController("/successRegister.html"); - } - - @Bean - public ViewResolver viewResolver() { - final InternalResourceViewResolver bean = new InternalResourceViewResolver(); - bean.setViewClass(JstlView.class); - bean.setPrefix("/WEB-INF/view/"); - bean.setSuffix(".jsp"); - return bean; - } - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**").addResourceLocations("/", "/resources/"); - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); - localeChangeInterceptor.setParamName("lang"); - registry.addInterceptor(localeChangeInterceptor); - } - - @Bean - public LocaleResolver localeResolver() { - CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver(); - cookieLocaleResolver.setDefaultLocale(Locale.ENGLISH); - return cookieLocaleResolver; - } - - @Bean - public MessageSource messageSource() { - ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); - messageSource.setBasename("classpath:messages"); - messageSource.setUseCodeAsDefaultMessage(true); - messageSource.setDefaultEncoding("UTF-8"); - messageSource.setCacheSeconds(0); - return messageSource; - } - - @Bean - public EmailValidator usernameValidator() { - EmailValidator userNameValidator = new EmailValidator(); - return userNameValidator; - } - - @Bean - public PasswordMatchesValidator passwordMatchesValidator() { - PasswordMatchesValidator passwordMatchesValidator = new PasswordMatchesValidator(); - return passwordMatchesValidator; - } - - // DIC 7 - @Bean - public HashGenerator hashGenerator() { - HashGenerator hashGenerator = new HashGenerator(); - return hashGenerator; - } - -} \ No newline at end of file diff --git a/src/main/java/org/baeldung/spring/PersistenceJPAConfig.java b/src/main/java/org/baeldung/spring/PersistenceJPAConfig.java deleted file mode 100644 index 0baac30ec1..0000000000 --- a/src/main/java/org/baeldung/spring/PersistenceJPAConfig.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.baeldung.spring; - -import java.util.Properties; -import javax.sql.DataSource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.PropertySource; -import org.springframework.core.env.Environment; -import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; -import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -@Configuration -@EnableTransactionManagement -@PropertySource({ "classpath:application.properties" }) -@ComponentScan({ "org.baeldung.persistence.model" }) -@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao") -public class PersistenceJPAConfig { - - @Autowired - private Environment env; - - public PersistenceJPAConfig() { - super(); - } - - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); - em.setDataSource(dataSource()); - em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); - final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); - em.setJpaVendorAdapter(vendorAdapter); - em.setJpaProperties(additionalProperties()); - return em; - } - - @Bean - public DataSource dataSource() { - final DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); - dataSource.setUrl(env.getProperty("jdbc.url")); - dataSource.setUsername(env.getProperty("jdbc.user")); - dataSource.setPassword(env.getProperty("jdbc.pass")); - return dataSource; - } - - @Bean - public JpaTransactionManager transactionManager() { - JpaTransactionManager transactionManager = new JpaTransactionManager(); - transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); - return transactionManager; - } - - @Bean - public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { - return new PersistenceExceptionTranslationPostProcessor(); - } - - final Properties additionalProperties() { - final Properties hibernateProperties = new Properties(); - hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); - hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); - return hibernateProperties; - } - -} diff --git a/src/main/java/org/baeldung/spring/SecSecurityConfig.java b/src/main/java/org/baeldung/spring/SecSecurityConfig.java deleted file mode 100644 index 4da114c78b..0000000000 --- a/src/main/java/org/baeldung/spring/SecSecurityConfig.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.baeldung.spring; - -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; - -@Configuration -@ImportResource({ "classpath:webSecurityConfig.xml" }) -public class SecSecurityConfig { - - public SecSecurityConfig() { - super(); - } - -} diff --git a/src/main/java/org/baeldung/validation/service/EmailExistsException.java b/src/main/java/org/baeldung/validation/service/EmailExistsException.java deleted file mode 100644 index 7b60bb9f08..0000000000 --- a/src/main/java/org/baeldung/validation/service/EmailExistsException.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.baeldung.validation.service; - -@SuppressWarnings("serial") -public class EmailExistsException extends Throwable { - - public EmailExistsException(String message) { - super(message); - } -} diff --git a/src/main/java/org/baeldung/validation/service/EmailValidator.java b/src/main/java/org/baeldung/validation/service/EmailValidator.java deleted file mode 100644 index 1ff8c4251f..0000000000 --- a/src/main/java/org/baeldung/validation/service/EmailValidator.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.baeldung.validation.service; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -public class EmailValidator implements ConstraintValidator { - private Pattern pattern; - private Matcher matcher; - private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; - - @Override - public void initialize(ValidEmail constraintAnnotation) { - } - - @Override - public boolean isValid(String username, ConstraintValidatorContext context) { - return (validateEmail(username)); - } - - private boolean validateEmail(String email) { - pattern = Pattern.compile(EMAIL_PATTERN); - matcher = pattern.matcher(email); - return matcher.matches(); - } -} diff --git a/src/main/java/org/baeldung/validation/service/PasswordMatches.java b/src/main/java/org/baeldung/validation/service/PasswordMatches.java deleted file mode 100644 index 63cfb297f0..0000000000 --- a/src/main/java/org/baeldung/validation/service/PasswordMatches.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.baeldung.validation.service; - -import javax.validation.Constraint; -import javax.validation.Payload; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -@Target({ TYPE, ANNOTATION_TYPE }) -@Retention(RUNTIME) -@Constraint(validatedBy = PasswordMatchesValidator.class) -@Documented -public @interface PasswordMatches { - - String message() default "Passwords don't match"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/src/main/java/org/baeldung/validation/service/PasswordMatchesValidator.java b/src/main/java/org/baeldung/validation/service/PasswordMatchesValidator.java deleted file mode 100644 index 99f569957b..0000000000 --- a/src/main/java/org/baeldung/validation/service/PasswordMatchesValidator.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.baeldung.validation.service; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -import org.baeldung.persistence.service.UserDto; - -public class PasswordMatchesValidator implements ConstraintValidator { - - @Override - public void initialize(PasswordMatches constraintAnnotation) { - } - - @Override - public boolean isValid(Object obj, ConstraintValidatorContext context) { - UserDto user = (UserDto) obj; - return user.getPassword().equals(user.getMatchingPassword()); - } -} diff --git a/src/main/java/org/baeldung/validation/service/UserValidator.java b/src/main/java/org/baeldung/validation/service/UserValidator.java deleted file mode 100644 index 45de9e3a94..0000000000 --- a/src/main/java/org/baeldung/validation/service/UserValidator.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.validation.service; - -import org.baeldung.persistence.service.UserDto; -import org.springframework.validation.Errors; -import org.springframework.validation.ValidationUtils; -import org.springframework.validation.Validator; - -public class UserValidator implements Validator { - - @Override - public boolean supports(Class clazz) { - return UserDto.class.isAssignableFrom(clazz); - } - - @Override - public void validate(Object obj, Errors errors) { - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "message.firstName", "Firstname is required."); - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "message.lastName", "LastName is required."); - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "message.password", "LastName is required."); - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "message.username", "UserName is required."); - } - -} diff --git a/src/main/java/org/baeldung/validation/service/ValidEmail.java b/src/main/java/org/baeldung/validation/service/ValidEmail.java deleted file mode 100644 index df852351c3..0000000000 --- a/src/main/java/org/baeldung/validation/service/ValidEmail.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.baeldung.validation.service; - -import javax.validation.Constraint; -import javax.validation.Payload; -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -@Target({ TYPE, FIELD, ANNOTATION_TYPE }) -@Retention(RUNTIME) -@Constraint(validatedBy = EmailValidator.class) -@Documented -public @interface ValidEmail { - - String message() default "Invalid Email"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} diff --git a/src/main/java/org/baeldung/web/controller/RegistrationController.java b/src/main/java/org/baeldung/web/controller/RegistrationController.java deleted file mode 100644 index 69709c9190..0000000000 --- a/src/main/java/org/baeldung/web/controller/RegistrationController.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.baeldung.web.controller; - -import java.util.Calendar; -import java.util.Locale; - -import javax.validation.Valid; - -import org.baeldung.persistence.model.User; -import org.baeldung.persistence.model.VerificationToken; -import org.baeldung.persistence.service.UserDto; -import org.baeldung.persistence.service.IUserService; -import org.baeldung.event.OnRegistrationCompleteEvent; -import org.baeldung.validation.service.EmailExistsException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.MessageSource; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.validation.BindingResult; -import org.springframework.validation.Errors; -import org.springframework.web.bind.annotation.ModelAttribute; -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.context.request.WebRequest; -import org.springframework.web.servlet.ModelAndView; - -@Controller -public class RegistrationController { - - private final Logger LOGGER = LoggerFactory.getLogger(getClass()); - - @Autowired - private IUserService service; - - @Autowired - private MessageSource messages; - - @Autowired - private JavaMailSender mailSender; - - @Autowired - private ApplicationEventPublisher eventPublisher; - - public RegistrationController() { - - } - - @RequestMapping(value = "/user/registration", method = RequestMethod.GET) - public String showRegistrationForm(WebRequest request, Model model) { - LOGGER.debug("Rendering registration page."); - UserDto accountDto = new UserDto(); - model.addAttribute("user", accountDto); - return "registration"; - } - - @RequestMapping(value = "/regitrationConfirm", method = RequestMethod.GET) - public String confirmRegistration(WebRequest request, Model model, @RequestParam("token") String token) { - Locale locale = request.getLocale(); - - VerificationToken verificationToken = service.getVerificationToken(token); - if (verificationToken == null) { - String message = messages.getMessage("auth.message.invalidToken", null, locale); - model.addAttribute("message", message); - return "redirect:/badUser.html?lang=" + locale.getLanguage(); - } - - User user = verificationToken.getUser(); - Calendar cal = Calendar.getInstance(); - if ((verificationToken.getExpiryDate().getTime() - cal.getTime().getTime()) <= 0) { - model.addAttribute("message", messages.getMessage("auth.message.expired", null, locale)); - return "redirect:/badUser.html?lang=" + locale.getLanguage(); - } - - user.setEnabled(true); - service.saveRegisteredUser(user); - return "redirect:/login.html?lang=" + locale.getLanguage(); - } - - @RequestMapping(value = "/user/registration", method = RequestMethod.POST) - public ModelAndView registerUserAccount(@ModelAttribute("user") @Valid UserDto accountDto, BindingResult result, WebRequest request, Errors errors) { - LOGGER.debug("Registering user account with information: {}", accountDto); - if (result.hasErrors()) { - return new ModelAndView("registration", "user", accountDto); - } - - User registered = createUserAccount(accountDto); - if (registered == null) { - result.rejectValue("email", "message.regError"); - } - try { - String appUrl = request.getContextPath(); - eventPublisher.publishEvent(new OnRegistrationCompleteEvent(registered, request.getLocale(), appUrl)); - } catch (Exception me) { - return new ModelAndView("emailError", "user", accountDto); - } - return new ModelAndView("successRegister", "user", accountDto); - } - - private User createUserAccount(UserDto accountDto) { - User registered = null; - try { - registered = service.registerNewUserAccount(accountDto); - } catch (EmailExistsException e) { - return null; - } - return registered; - } -} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index b4b219646e..0000000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1,17 +0,0 @@ -################### DataSource Configuration ########################## -jdbc.driverClassName=com.mysql.jdbc.Driver -jdbc.url=jdbc:mysql://localhost:3306/AUTHDATA -jdbc.user=root -###jdbc.pass=admin### -init-db=false -################### Hibernate Configuration ########################## -hibernate.dialect=org.hibernate.dialect.MySQLDialect -hibernate.show_sql=true -hibernate.hbm2ddl.auto=validate -################### JavaMail Configuration ########################## -smtp.host=smtp.gmail.com -smtp.port=465 -smtp.protocol=smtps -smtp.username=egmp777@gmail.com -smtp.password=biiikupozvjvistz -support.email=egmp777@gmail.com diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml deleted file mode 100644 index 1146dade63..0000000000 --- a/src/main/resources/logback.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - web - %date [%thread] %-5level %logger{36} - %message%n - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties deleted file mode 100644 index 1a66bbc0f4..0000000000 --- a/src/main/resources/messages_en.properties +++ /dev/null @@ -1,55 +0,0 @@ -message.username=Username required -message.password=Password required -message.unauth=Unauthorized Access !! -message.badCredentials=Invalid Username or Password -message.sessionExpired=Session Timed Out -message.logoutError=Sorry, error logging out -message.logoutSucc=You logged out successfully -message.regSucc=You registered successfully. We will send you a confirmation message to your email account. -message.regError=An account for that username/email already exists. Please enter a different username. -message.lastName=Last name is required -message.firstName=First name required -message.badEmail=Invalid email address -message.email.config.error=Error in java mail configuration -token.message=Your token is: -auth.message.disabled=Your account is disabled please check your mail and click on the confirmation link -auth.message.expired=Your registration token has expired. Please register again. -auth.message.invalidUser=This username is invalid, or does not exist. -auth.message.invalidToken=Invalid account confirmation token. -label.user.email=Email: -label.user.firstName=First name: -label.user.lastName=Last name: -label.user.password=Password: -label.user.confirmPass=Confirm password -label.form.submit=Submit -label.form.title=Registration Form -label.form.loginLink=Back to login -label.login=Login here -label.form.loginTitle=Login -label.form.loginEmail=Email -label.form.loginPass=Password -label.form.loginEnglish=English -label.form.loginSpanish=Spanish -label.form.loginSignUp=Sign up -label.pages.logout=Logout -label.pages.admin=Administrator -label.pages.home.title=Home -label.pages.home.message=Welcome Home -label.pages.admin.message=Welcome Admin -label.pages.user.message=Welcome User -label.successRegister.title=Registration Success -label.badUser.title=Invalid Link -ValidEmail.user.email=Invalid email address! -UniqueUsername.user.username=An account with that username/email already exists -NotNull.user.firstName=First name required -NotEmpty.user.firstName=First name required -NotNull.user.lastName=Last name required -NotEmpty.user.lastName=Last name required -NotNull.user.username=Username(Email) required -NotEmpty.user.username=Username(Email) required -NotNull.user.password=Password required -NotEmpty.user.password=Password required -NotNull.user.matchingPassword=Required -NotEmpty.user.matchingPassword=Required -PasswordMatches.user:Password does not match! -Email.user.email=Invalid Username (Email) \ No newline at end of file diff --git a/src/main/resources/messages_es_ES.properties b/src/main/resources/messages_es_ES.properties deleted file mode 100644 index a22263b9ba..0000000000 --- a/src/main/resources/messages_es_ES.properties +++ /dev/null @@ -1,55 +0,0 @@ -message.username=Por favor ingrese el nombre de usuario -message.password=Por favor ingrese una clave -message.unauth=Acceso denegado !! -message.badCredentials=Usuario o clave invalida -message.sessionExpired=La sesion expiro -message.logoutError=Lo sentimos, hubo problemas al salir -message.logoutSucc=Salida con exito -message.regSucc=Se registro correctamente. Le enviaremos un mensaje de confirmacion a su direccion de email. -message.regError=Ya existe una cuenta con ese nombre de usuario. Ingrese un nombre de usuario diferente. -message.lastName=Por favor ingrese su apellido -message.firstName=Por favor ingrese su nombre -message.badEmail=Direccion de correo no es valida -message.email.config.error=Error en configuracion de java mail -token.message=Su token es: -auth.message.disabled=Su cuenta no esta habilitada. Hemos enviado a su correo un link para habilitar su cuenta. -auth.message.expired=Su ficha de registro ha caducado, por favor registrese de nuevo. -auth.message.invalidUser=Este nombre de usuario es invalido o no existe. -auth.message.invalidToken=Codigo de confirmacion incorrecto. -label.user.email=Correo Electronico: -label.user.firstName=Nombre: -label.user.lastName=Apellido: -label.user.password=Contrasenia: -label.user.confirmPass=Confirme la contrasenia -label.form.submit=Enviar -label.form.title=Formulario de Registro -label.login=Autehtifiquese aqui -label.form.loginTitle=Ingreso -label.form.loginLink=Regrese a autentificacion -label.form.loginEmail=Correo Electronico -label.form.loginPass=Contrasenia -label.form.loginEnglish=Ingles -label.form.loginSpanish=Espaniol -label.form.loginSignUp=Registrese -label.pages.logout=Salir -label.pages.admin=Administrador -label.pages.home.title=Inicio -label.pages.home.message=Bienveni@ a Casa -label.pages.admin.message=Bienvenid@ Admin -label.pages.user.message=Bienvenid@ Usuari@ -label.successRegister.title=Registro Exitoso -label.badUser.title=Enlace Invalido -ValidEmail.user.email=Cuenta correo invlida! -UniqueUsername.user.username=Ya existe una cuenta con ese nombre de usuario -NotNull.user.firstName=Por favor ingrese su nombre -NotEmpty.user.firstName=Por favor ingrese su nombre -NotNull.user.lastName=Por favor ingrese su apellido -NotEmpty.user.lastName=Por favor ingrese su apellido -NotNull.user.username=Por favor ingrese su cuenta de email -NotEmpty.user.username=Por favor ingrese su cuenta de email -NotNull.user.password=Por favor ingrese su clave -NotEmpty.user.password=Por favor ingrese su contraseña -NotNull.user.matchingPassword=Campo obligatirio -NotEmpty.user.matchingPassword=Campo obligatrio -PasswordMatches.user:Las claves no coinciden! -Email.user.email=Email no es valido diff --git a/src/main/resources/webSecurityConfig.xml b/src/main/resources/webSecurityConfig.xml deleted file mode 100644 index 0a05c24026..0000000000 --- a/src/main/resources/webSecurityConfig.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/webapp/META-INF/MANIFEST.MF b/src/main/webapp/META-INF/MANIFEST.MF deleted file mode 100644 index 5e9495128c..0000000000 --- a/src/main/webapp/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - diff --git a/src/main/webapp/WEB-INF/mvc-servlet.xml b/src/main/webapp/WEB-INF/mvc-servlet.xml deleted file mode 100644 index 94bd63e068..0000000000 --- a/src/main/webapp/WEB-INF/mvc-servlet.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/view/admin.jsp b/src/main/webapp/WEB-INF/view/admin.jsp deleted file mode 100644 index 7456f2ebae..0000000000 --- a/src/main/webapp/WEB-INF/view/admin.jsp +++ /dev/null @@ -1,29 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - - -" rel="stylesheet"> -<spring:message code="label.pages.home.title"></spring:message> - - -
      -
      - - - - -

      - -

      -
      - "> "> -
      -
      - - diff --git a/src/main/webapp/WEB-INF/view/badUser.jsp b/src/main/webapp/WEB-INF/view/badUser.jsp deleted file mode 100644 index 348caac58a..0000000000 --- a/src/main/webapp/WEB-INF/view/badUser.jsp +++ /dev/null @@ -1,24 +0,0 @@ -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> - -<%@ page session="true"%> - - -" rel="stylesheet"> - <spring:message -code="label.badUser.title"></spring:message> - - -

      -
      - ${param.message} -

      -
      -"> - - - diff --git a/src/main/webapp/WEB-INF/view/console.jsp b/src/main/webapp/WEB-INF/view/console.jsp deleted file mode 100644 index da04eac57d..0000000000 --- a/src/main/webapp/WEB-INF/view/console.jsp +++ /dev/null @@ -1,29 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - -" rel="stylesheet"> - - -
      -
      -

      This is the landing page for the admin

      - - This text is only visible to a user -
      -
      - - This text is only visible to an admin -
      -
      - "> "> -
      -
      - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/view/emailError.jsp b/src/main/webapp/WEB-INF/view/emailError.jsp deleted file mode 100644 index ca94dbdfb0..0000000000 --- a/src/main/webapp/WEB-INF/view/emailError.jsp +++ /dev/null @@ -1,19 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - -" rel="stylesheet"> -<spring:message code="label.pages.home.title"></spring:message> - - -
      -
      -

      - -

      - -
      -
      - - - diff --git a/src/main/webapp/WEB-INF/view/expiredAccount.jsp b/src/main/webapp/WEB-INF/view/expiredAccount.jsp deleted file mode 100644 index a8f732c312..0000000000 --- a/src/main/webapp/WEB-INF/view/expiredAccount.jsp +++ /dev/null @@ -1,23 +0,0 @@ -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> - -<%@ page session="true"%> - - - -" rel="stylesheet"> - <spring:message code="label.pages.home.title"></spring:message> - - -

      - -

      -
      -"> - - - diff --git a/src/main/webapp/WEB-INF/view/home.jsp b/src/main/webapp/WEB-INF/view/home.jsp deleted file mode 100644 index 68819f09f4..0000000000 --- a/src/main/webapp/WEB-INF/view/home.jsp +++ /dev/null @@ -1,22 +0,0 @@ -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> -<%@ page session="true"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - - -" rel="stylesheet"> -<spring:message code="label.pages.home.title"></spring:message> - - -
      -
      -

      - -

      - "> -
      -
      - - - diff --git a/src/main/webapp/WEB-INF/view/homepage.jsp b/src/main/webapp/WEB-INF/view/homepage.jsp deleted file mode 100644 index 2d2942b44e..0000000000 --- a/src/main/webapp/WEB-INF/view/homepage.jsp +++ /dev/null @@ -1,35 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ page session="true"%> - - -" rel="stylesheet"> -<spring:message code="label.pages.home.title"></spring:message> - - - -
      - -
      - - -
      -
      - - - -
      -
      - ${param.user} - "> "> "> -
      -
      - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/view/invalidSession.jsp b/src/main/webapp/WEB-INF/view/invalidSession.jsp deleted file mode 100644 index 4e62083a52..0000000000 --- a/src/main/webapp/WEB-INF/view/invalidSession.jsp +++ /dev/null @@ -1,20 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - -" rel="stylesheet"> -<spring:message code="label.pages.home.title"></spring:message> - - -
      -
      -

      - -

      - "> -
      -
      - - - diff --git a/src/main/webapp/WEB-INF/view/login.jsp b/src/main/webapp/WEB-INF/view/login.jsp deleted file mode 100644 index 7ffa78c777..0000000000 --- a/src/main/webapp/WEB-INF/view/login.jsp +++ /dev/null @@ -1,94 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> - -<%@ page session="true"%> - - - - - -
      - -
      -
      - -
      - -
      -
      - -
      - - -
      -
      -
      -
      - - - -" rel="stylesheet"> -<spring:message code="label.pages.home.title"></spring:message> - - - -
      -
      -

      - -

      - - | -
      - - - - - - - - - - - - -
      />
      - -
      -
      Current Locale : ${pageContext.response.locale}
      "> -
      -
      - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/view/logout.jsp b/src/main/webapp/WEB-INF/view/logout.jsp deleted file mode 100644 index b83c558577..0000000000 --- a/src/main/webapp/WEB-INF/view/logout.jsp +++ /dev/null @@ -1,32 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> - - - -" rel="stylesheet"> - -
      - -
      -
      - -<spring:message code="label.pages.home.title"></spring:message> - - - -
      -
      - -
      - -
      -
      - "> -
      -
      - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/view/registration.jsp b/src/main/webapp/WEB-INF/view/registration.jsp deleted file mode 100644 index 0d6781a5db..0000000000 --- a/src/main/webapp/WEB-INF/view/registration.jsp +++ /dev/null @@ -1,64 +0,0 @@ - -<%@ page contentType="text/html;charset=UTF-8" language="java"%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> -<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@ page session="false"%> - - -" rel="stylesheet"> - -<spring:message code="label.form.title"></spring:message> - - -
      -
      -

      - -

      - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - -
      -
      "> -
      -
      - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/view/regitrationConfirm.jsp b/src/main/webapp/WEB-INF/view/regitrationConfirm.jsp deleted file mode 100644 index cdbeea5169..0000000000 --- a/src/main/webapp/WEB-INF/view/regitrationConfirm.jsp +++ /dev/null @@ -1,22 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> - -<%@ page session="true"%> - - - - - -" rel="stylesheet"> - -<spring:message code="label.pages.home.title"></spring:message> - - - - - "> - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/view/successRegister.jsp b/src/main/webapp/WEB-INF/view/successRegister.jsp deleted file mode 100644 index d6ae764618..0000000000 --- a/src/main/webapp/WEB-INF/view/successRegister.jsp +++ /dev/null @@ -1,27 +0,0 @@ -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> -<%@ taglib prefix="sec" - uri="http://www.springframework.org/security/tags"%> -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> - -<%@ page session="true"%> - - - - -" rel="stylesheet"> - -<spring:message code="label.pages.home.title"></spring:message> - - -
      -
      -
      - -
      - "> -
      -
      - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 26ac5be1e0..0000000000 --- a/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - contextClass - - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - contextConfigLocation - org.baeldung.spring - - - - org.springframework.web.context.ContextLoaderListener - - - - mvc - org.springframework.web.servlet.DispatcherServlet - 1 - - - mvc - / - - - - springSecurityFilterChain - org.springframework.web.filter.DelegatingFilterProxy - - - springSecurityFilterChain - /* - - - localizationFilter - org.springframework.web.filter.RequestContextFilter - - - localizationFilter - /* - - - \ No newline at end of file diff --git a/src/main/webapp/resources/bootstrap.css b/src/main/webapp/resources/bootstrap.css deleted file mode 100644 index a5b7ccc211..0000000000 --- a/src/main/webapp/resources/bootstrap.css +++ /dev/null @@ -1,6167 +0,0 @@ -/*! - * Bootstrap v2.3.2 - * - * Copyright 2013 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world by @mdo and @fat. - */ - -.clearfix { - *zoom: 1; -} - -.clearfix:before, -.clearfix:after { - display: table; - line-height: 0; - content: ""; -} - -.clearfix:after { - clear: both; -} - -.hide-text { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} - -.input-block-level { - display: block; - width: 100%; - min-height: 30px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section { - display: block; -} - -audio, -canvas, -video { - display: inline-block; - *display: inline; - *zoom: 1; -} - -audio:not([controls]) { - display: none; -} - -html { - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -a:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -a:hover, -a:active { - outline: 0; -} - -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -img { - width: auto\9; - height: auto; - max-width: 100%; - vertical-align: middle; - border: 0; - -ms-interpolation-mode: bicubic; -} - -#map_canvas img, -.google-maps img { - max-width: none; -} - -button, -input, -select, -textarea { - margin: 0; - font-size: 100%; - vertical-align: middle; -} - -button, -input { - *overflow: visible; - line-height: normal; -} - -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} - -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} - -label, -select, -button, -input[type="button"], -input[type="reset"], -input[type="submit"], -input[type="radio"], -input[type="checkbox"] { - cursor: pointer; -} - -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} - -input[type="search"]::-webkit-search-decoration, -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; -} - -textarea { - overflow: auto; - vertical-align: top; -} - -@media print { - * { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - .ir a:after, - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - @page { - margin: 0.5cm; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } -} - -body { - margin: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 20px; - color: #333333; - background-color: #ffffff; -} - -a { - color: #0088cc; - text-decoration: none; -} - -a:hover, -a:focus { - color: #005580; - text-decoration: underline; -} - -.img-rounded { - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.img-polaroid { - padding: 4px; - background-color: #fff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -} - -.img-circle { - -webkit-border-radius: 500px; - -moz-border-radius: 500px; - border-radius: 500px; -} - -.row { - margin-left: -20px; - *zoom: 1; -} - -.row:before, -.row:after { - display: table; - line-height: 0; - content: ""; -} - -.row:after { - clear: both; -} - -[class*="span"] { - float: left; - min-height: 1px; - margin-left: 20px; -} - -.container, -.navbar-static-top .container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} - -.span12 { - width: 940px; -} - -.span11 { - width: 860px; -} - -.span10 { - width: 780px; -} - -.span9 { - width: 700px; -} - -.span8 { - width: 620px; -} - -.span7 { - width: 540px; -} - -.span6 { - width: 460px; -} - -.span5 { - width: 380px; -} - -.span4 { - width: 300px; -} - -.span3 { - width: 220px; -} - -.span2 { - width: 140px; -} - -.span1 { - width: 60px; -} - -.offset12 { - margin-left: 980px; -} - -.offset11 { - margin-left: 900px; -} - -.offset10 { - margin-left: 820px; -} - -.offset9 { - margin-left: 740px; -} - -.offset8 { - margin-left: 660px; -} - -.offset7 { - margin-left: 580px; -} - -.offset6 { - margin-left: 500px; -} - -.offset5 { - margin-left: 420px; -} - -.offset4 { - margin-left: 340px; -} - -.offset3 { - margin-left: 260px; -} - -.offset2 { - margin-left: 180px; -} - -.offset1 { - margin-left: 100px; -} - -.row-fluid { - width: 100%; - *zoom: 1; -} - -.row-fluid:before, -.row-fluid:after { - display: table; - line-height: 0; - content: ""; -} - -.row-fluid:after { - clear: both; -} - -.row-fluid [class*="span"] { - display: block; - float: left; - width: 100%; - min-height: 30px; - margin-left: 2.127659574468085%; - *margin-left: 2.074468085106383%; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.row-fluid [class*="span"]:first-child { - margin-left: 0; -} - -.row-fluid .controls-row [class*="span"] + [class*="span"] { - margin-left: 2.127659574468085%; -} - -.row-fluid .span12 { - width: 100%; - *width: 99.94680851063829%; -} - -.row-fluid .span11 { - width: 91.48936170212765%; - *width: 91.43617021276594%; -} - -.row-fluid .span10 { - width: 82.97872340425532%; - *width: 82.92553191489361%; -} - -.row-fluid .span9 { - width: 74.46808510638297%; - *width: 74.41489361702126%; -} - -.row-fluid .span8 { - width: 65.95744680851064%; - *width: 65.90425531914893%; -} - -.row-fluid .span7 { - width: 57.44680851063829%; - *width: 57.39361702127659%; -} - -.row-fluid .span6 { - width: 48.93617021276595%; - *width: 48.88297872340425%; -} - -.row-fluid .span5 { - width: 40.42553191489362%; - *width: 40.37234042553192%; -} - -.row-fluid .span4 { - width: 31.914893617021278%; - *width: 31.861702127659576%; -} - -.row-fluid .span3 { - width: 23.404255319148934%; - *width: 23.351063829787233%; -} - -.row-fluid .span2 { - width: 14.893617021276595%; - *width: 14.840425531914894%; -} - -.row-fluid .span1 { - width: 6.382978723404255%; - *width: 6.329787234042553%; -} - -.row-fluid .offset12 { - margin-left: 104.25531914893617%; - *margin-left: 104.14893617021275%; -} - -.row-fluid .offset12:first-child { - margin-left: 102.12765957446808%; - *margin-left: 102.02127659574467%; -} - -.row-fluid .offset11 { - margin-left: 95.74468085106382%; - *margin-left: 95.6382978723404%; -} - -.row-fluid .offset11:first-child { - margin-left: 93.61702127659574%; - *margin-left: 93.51063829787232%; -} - -.row-fluid .offset10 { - margin-left: 87.23404255319149%; - *margin-left: 87.12765957446807%; -} - -.row-fluid .offset10:first-child { - margin-left: 85.1063829787234%; - *margin-left: 84.99999999999999%; -} - -.row-fluid .offset9 { - margin-left: 78.72340425531914%; - *margin-left: 78.61702127659572%; -} - -.row-fluid .offset9:first-child { - margin-left: 76.59574468085106%; - *margin-left: 76.48936170212764%; -} - -.row-fluid .offset8 { - margin-left: 70.2127659574468%; - *margin-left: 70.10638297872339%; -} - -.row-fluid .offset8:first-child { - margin-left: 68.08510638297872%; - *margin-left: 67.9787234042553%; -} - -.row-fluid .offset7 { - margin-left: 61.70212765957446%; - *margin-left: 61.59574468085106%; -} - -.row-fluid .offset7:first-child { - margin-left: 59.574468085106375%; - *margin-left: 59.46808510638297%; -} - -.row-fluid .offset6 { - margin-left: 53.191489361702125%; - *margin-left: 53.085106382978715%; -} - -.row-fluid .offset6:first-child { - margin-left: 51.063829787234035%; - *margin-left: 50.95744680851063%; -} - -.row-fluid .offset5 { - margin-left: 44.68085106382979%; - *margin-left: 44.57446808510638%; -} - -.row-fluid .offset5:first-child { - margin-left: 42.5531914893617%; - *margin-left: 42.4468085106383%; -} - -.row-fluid .offset4 { - margin-left: 36.170212765957444%; - *margin-left: 36.06382978723405%; -} - -.row-fluid .offset4:first-child { - margin-left: 34.04255319148936%; - *margin-left: 33.93617021276596%; -} - -.row-fluid .offset3 { - margin-left: 27.659574468085104%; - *margin-left: 27.5531914893617%; -} - -.row-fluid .offset3:first-child { - margin-left: 25.53191489361702%; - *margin-left: 25.425531914893618%; -} - -.row-fluid .offset2 { - margin-left: 19.148936170212764%; - *margin-left: 19.04255319148936%; -} - -.row-fluid .offset2:first-child { - margin-left: 17.02127659574468%; - *margin-left: 16.914893617021278%; -} - -.row-fluid .offset1 { - margin-left: 10.638297872340425%; - *margin-left: 10.53191489361702%; -} - -.row-fluid .offset1:first-child { - margin-left: 8.51063829787234%; - *margin-left: 8.404255319148938%; -} - -[class*="span"].hide, -.row-fluid [class*="span"].hide { - display: none; -} - -[class*="span"].pull-right, -.row-fluid [class*="span"].pull-right { - float: right; -} - -.container { - margin-right: auto; - margin-left: auto; - *zoom: 1; -} - -.container:before, -.container:after { - display: table; - line-height: 0; - content: ""; -} - -.container:after { - clear: both; -} - -.container-fluid { - padding-right: 20px; - padding-left: 20px; - *zoom: 1; -} - -.container-fluid:before, -.container-fluid:after { - display: table; - line-height: 0; - content: ""; -} - -.container-fluid:after { - clear: both; -} - -p { - margin: 0 0 10px; -} - -.lead { - margin-bottom: 20px; - font-size: 21px; - font-weight: 200; - line-height: 30px; -} - -small { - font-size: 85%; -} - -strong { - font-weight: bold; -} - -em { - font-style: italic; -} - -cite { - font-style: normal; -} - -.muted { - color: #999999; -} - -a.muted:hover, -a.muted:focus { - color: #808080; -} - -.text-warning { - color: #c09853; -} - -a.text-warning:hover, -a.text-warning:focus { - color: #a47e3c; -} - -.text-error { - color: #b94a48; -} - -a.text-error:hover, -a.text-error:focus { - color: #953b39; -} - -.text-info { - color: #3a87ad; -} - -a.text-info:hover, -a.text-info:focus { - color: #2d6987; -} - -.text-success { - color: #468847; -} - -a.text-success:hover, -a.text-success:focus { - color: #356635; -} - -.text-left { - text-align: left; -} - -.text-right { - text-align: right; -} - -.text-center { - text-align: center; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - margin: 10px 0; - font-family: inherit; - font-weight: bold; - line-height: 20px; - color: inherit; - text-rendering: optimizelegibility; -} - -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small { - font-weight: normal; - line-height: 1; - color: #999999; -} - -h1, -h2, -h3 { - line-height: 40px; -} - -h1 { - font-size: 38.5px; -} - -h2 { - font-size: 31.5px; -} - -h3 { - font-size: 24.5px; -} - -h4 { - font-size: 17.5px; -} - -h5 { - font-size: 14px; -} - -h6 { - font-size: 11.9px; -} - -h1 small { - font-size: 24.5px; -} - -h2 small { - font-size: 17.5px; -} - -h3 small { - font-size: 14px; -} - -h4 small { - font-size: 14px; -} - -.page-header { - padding-bottom: 9px; - margin: 20px 0 30px; - border-bottom: 1px solid #eeeeee; -} - -ul, -ol { - padding: 0; - margin: 0 0 10px 25px; -} - -ul ul, -ul ol, -ol ol, -ol ul { - margin-bottom: 0; -} - -li { - line-height: 20px; -} - -ul.unstyled, -ol.unstyled { - margin-left: 0; - list-style: none; -} - -ul.inline, -ol.inline { - margin-left: 0; - list-style: none; -} - -ul.inline > li, -ol.inline > li { - display: inline-block; - *display: inline; - padding-right: 5px; - padding-left: 5px; - *zoom: 1; -} - -dl { - margin-bottom: 20px; -} - -dt, -dd { - line-height: 20px; -} - -dt { - font-weight: bold; -} - -dd { - margin-left: 10px; -} - -.dl-horizontal { - *zoom: 1; -} - -.dl-horizontal:before, -.dl-horizontal:after { - display: table; - line-height: 0; - content: ""; -} - -.dl-horizontal:after { - clear: both; -} - -.dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; -} - -.dl-horizontal dd { - margin-left: 180px; -} - -hr { - margin: 20px 0; - border: 0; - border-top: 1px solid #eeeeee; - border-bottom: 1px solid #ffffff; -} - -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #999999; -} - -abbr.initialism { - font-size: 90%; - text-transform: uppercase; -} - -blockquote { - padding: 0 0 0 15px; - margin: 0 0 20px; - border-left: 5px solid #eeeeee; -} - -blockquote p { - margin-bottom: 0; - font-size: 17.5px; - font-weight: 300; - line-height: 1.25; -} - -blockquote small { - display: block; - line-height: 20px; - color: #999999; -} - -blockquote small:before { - content: '\2014 \00A0'; -} - -blockquote.pull-right { - float: right; - padding-right: 15px; - padding-left: 0; - border-right: 5px solid #eeeeee; - border-left: 0; -} - -blockquote.pull-right p, -blockquote.pull-right small { - text-align: right; -} - -blockquote.pull-right small:before { - content: ''; -} - -blockquote.pull-right small:after { - content: '\00A0 \2014'; -} - -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} - -address { - display: block; - margin-bottom: 20px; - font-style: normal; - line-height: 20px; -} - -code, -pre { - padding: 0 3px 2px; - font-family: Monaco, Menlo, Consolas, "Courier New", monospace; - font-size: 12px; - color: #333333; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -code { - padding: 2px 4px; - color: #d14; - white-space: nowrap; - background-color: #f7f7f9; - border: 1px solid #e1e1e8; -} - -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 20px; - word-break: break-all; - word-wrap: break-word; - white-space: pre; - white-space: pre-wrap; - background-color: #f5f5f5; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -pre.prettyprint { - margin-bottom: 20px; -} - -pre code { - padding: 0; - color: inherit; - white-space: pre; - white-space: pre-wrap; - background-color: transparent; - border: 0; -} - -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} - -form { - margin: 0 0 20px; -} - -fieldset { - padding: 0; - margin: 0; - border: 0; -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: 40px; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} - -legend small { - font-size: 15px; - color: #999999; -} - -label, -input, -button, -select, -textarea { - font-size: 14px; - font-weight: normal; - line-height: 20px; -} - -input, -button, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -} - -label { - display: block; - margin-bottom: 5px; -} - -select, -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - display: inline-block; - height: 30px; - padding: 4px 6px; - margin-bottom: 10px; - font-size: 14px; - line-height: 20px; - color: #555555; - vertical-align: middle; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -input, -textarea, -.uneditable-input { - width: 206px; -} - -textarea { - height: auto; -} - -textarea, -input[type="text"], -input[type="password"], -input[type="datetime"], -input[type="datetime-local"], -input[type="date"], -input[type="month"], -input[type="time"], -input[type="week"], -input[type="number"], -input[type="email"], -input[type="url"], -input[type="search"], -input[type="tel"], -input[type="color"], -.uneditable-input { - background-color: #ffffff; - border: 1px solid #cccccc; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; - -moz-transition: border linear 0.2s, box-shadow linear 0.2s; - -o-transition: border linear 0.2s, box-shadow linear 0.2s; - transition: border linear 0.2s, box-shadow linear 0.2s; -} - -textarea:focus, -input[type="text"]:focus, -input[type="password"]:focus, -input[type="datetime"]:focus, -input[type="datetime-local"]:focus, -input[type="date"]:focus, -input[type="month"]:focus, -input[type="time"]:focus, -input[type="week"]:focus, -input[type="number"]:focus, -input[type="email"]:focus, -input[type="url"]:focus, -input[type="search"]:focus, -input[type="tel"]:focus, -input[type="color"]:focus, -.uneditable-input:focus { - border-color: rgba(82, 168, 236, 0.8); - outline: 0; - outline: thin dotted \9; - /* IE6-9 */ - - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); -} - -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - *margin-top: 0; - line-height: normal; -} - -input[type="file"], -input[type="image"], -input[type="submit"], -input[type="reset"], -input[type="button"], -input[type="radio"], -input[type="checkbox"] { - width: auto; -} - -select, -input[type="file"] { - height: 30px; - /* In IE7, the height of the select element cannot be changed by height, only font-size */ - - *margin-top: 4px; - /* For IE7, add top margin to align select with labels */ - - line-height: 30px; -} - -select { - width: 220px; - background-color: #ffffff; - border: 1px solid #cccccc; -} - -select[multiple], -select[size] { - height: auto; -} - -select:focus, -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.uneditable-input, -.uneditable-textarea { - color: #999999; - cursor: not-allowed; - background-color: #fcfcfc; - border-color: #cccccc; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); -} - -.uneditable-input { - overflow: hidden; - white-space: nowrap; -} - -.uneditable-textarea { - width: auto; - height: auto; -} - -input:-moz-placeholder, -textarea:-moz-placeholder { - color: #999999; -} - -input:-ms-input-placeholder, -textarea:-ms-input-placeholder { - color: #999999; -} - -input::-webkit-input-placeholder, -textarea::-webkit-input-placeholder { - color: #999999; -} - -.radio, -.checkbox { - min-height: 20px; - padding-left: 20px; -} - -.radio input[type="radio"], -.checkbox input[type="checkbox"] { - float: left; - margin-left: -20px; -} - -.controls > .radio:first-child, -.controls > .checkbox:first-child { - padding-top: 5px; -} - -.radio.inline, -.checkbox.inline { - display: inline-block; - padding-top: 5px; - margin-bottom: 0; - vertical-align: middle; -} - -.radio.inline + .radio.inline, -.checkbox.inline + .checkbox.inline { - margin-left: 10px; -} - -.input-mini { - width: 60px; -} - -.input-small { - width: 90px; -} - -.input-medium { - width: 150px; -} - -.input-large { - width: 210px; -} - -.input-xlarge { - width: 270px; -} - -.input-xxlarge { - width: 530px; -} - -input[class*="span"], -select[class*="span"], -textarea[class*="span"], -.uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"] { - float: none; - margin-left: 0; -} - -.input-append input[class*="span"], -.input-append .uneditable-input[class*="span"], -.input-prepend input[class*="span"], -.input-prepend .uneditable-input[class*="span"], -.row-fluid input[class*="span"], -.row-fluid select[class*="span"], -.row-fluid textarea[class*="span"], -.row-fluid .uneditable-input[class*="span"], -.row-fluid .input-prepend [class*="span"], -.row-fluid .input-append [class*="span"] { - display: inline-block; -} - -input, -textarea, -.uneditable-input { - margin-left: 0; -} - -.controls-row [class*="span"] + [class*="span"] { - margin-left: 20px; -} - -input.span12, -textarea.span12, -.uneditable-input.span12 { - width: 926px; -} - -input.span11, -textarea.span11, -.uneditable-input.span11 { - width: 846px; -} - -input.span10, -textarea.span10, -.uneditable-input.span10 { - width: 766px; -} - -input.span9, -textarea.span9, -.uneditable-input.span9 { - width: 686px; -} - -input.span8, -textarea.span8, -.uneditable-input.span8 { - width: 606px; -} - -input.span7, -textarea.span7, -.uneditable-input.span7 { - width: 526px; -} - -input.span6, -textarea.span6, -.uneditable-input.span6 { - width: 446px; -} - -input.span5, -textarea.span5, -.uneditable-input.span5 { - width: 366px; -} - -input.span4, -textarea.span4, -.uneditable-input.span4 { - width: 286px; -} - -input.span3, -textarea.span3, -.uneditable-input.span3 { - width: 206px; -} - -input.span2, -textarea.span2, -.uneditable-input.span2 { - width: 126px; -} - -input.span1, -textarea.span1, -.uneditable-input.span1 { - width: 46px; -} - -.controls-row { - *zoom: 1; -} - -.controls-row:before, -.controls-row:after { - display: table; - line-height: 0; - content: ""; -} - -.controls-row:after { - clear: both; -} - -.controls-row [class*="span"], -.row-fluid .controls-row [class*="span"] { - float: left; -} - -.controls-row .checkbox[class*="span"], -.controls-row .radio[class*="span"] { - padding-top: 5px; -} - -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - cursor: not-allowed; - background-color: #eeeeee; -} - -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"][readonly], -input[type="checkbox"][readonly] { - background-color: transparent; -} - -.control-group.warning .control-label, -.control-group.warning .help-block, -.control-group.warning .help-inline { - color: #c09853; -} - -.control-group.warning .checkbox, -.control-group.warning .radio, -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - color: #c09853; -} - -.control-group.warning input, -.control-group.warning select, -.control-group.warning textarea { - border-color: #c09853; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.warning input:focus, -.control-group.warning select:focus, -.control-group.warning textarea:focus { - border-color: #a47e3c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; -} - -.control-group.warning .input-prepend .add-on, -.control-group.warning .input-append .add-on { - color: #c09853; - background-color: #fcf8e3; - border-color: #c09853; -} - -.control-group.error .control-label, -.control-group.error .help-block, -.control-group.error .help-inline { - color: #b94a48; -} - -.control-group.error .checkbox, -.control-group.error .radio, -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - color: #b94a48; -} - -.control-group.error input, -.control-group.error select, -.control-group.error textarea { - border-color: #b94a48; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.error input:focus, -.control-group.error select:focus, -.control-group.error textarea:focus { - border-color: #953b39; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; -} - -.control-group.error .input-prepend .add-on, -.control-group.error .input-append .add-on { - color: #b94a48; - background-color: #f2dede; - border-color: #b94a48; -} - -.control-group.success .control-label, -.control-group.success .help-block, -.control-group.success .help-inline { - color: #468847; -} - -.control-group.success .checkbox, -.control-group.success .radio, -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - color: #468847; -} - -.control-group.success input, -.control-group.success select, -.control-group.success textarea { - border-color: #468847; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.success input:focus, -.control-group.success select:focus, -.control-group.success textarea:focus { - border-color: #356635; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; -} - -.control-group.success .input-prepend .add-on, -.control-group.success .input-append .add-on { - color: #468847; - background-color: #dff0d8; - border-color: #468847; -} - -.control-group.info .control-label, -.control-group.info .help-block, -.control-group.info .help-inline { - color: #3a87ad; -} - -.control-group.info .checkbox, -.control-group.info .radio, -.control-group.info input, -.control-group.info select, -.control-group.info textarea { - color: #3a87ad; -} - -.control-group.info input, -.control-group.info select, -.control-group.info textarea { - border-color: #3a87ad; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.control-group.info input:focus, -.control-group.info select:focus, -.control-group.info textarea:focus { - border-color: #2d6987; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; -} - -.control-group.info .input-prepend .add-on, -.control-group.info .input-append .add-on { - color: #3a87ad; - background-color: #d9edf7; - border-color: #3a87ad; -} - -input:focus:invalid, -textarea:focus:invalid, -select:focus:invalid { - color: #b94a48; - border-color: #ee5f5b; -} - -input:focus:invalid:focus, -textarea:focus:invalid:focus, -select:focus:invalid:focus { - border-color: #e9322d; - -webkit-box-shadow: 0 0 6px #f8b9b7; - -moz-box-shadow: 0 0 6px #f8b9b7; - box-shadow: 0 0 6px #f8b9b7; -} - -.form-actions { - padding: 19px 20px 20px; - margin-top: 20px; - margin-bottom: 20px; - background-color: #f5f5f5; - border-top: 1px solid #e5e5e5; - *zoom: 1; -} - -.form-actions:before, -.form-actions:after { - display: table; - line-height: 0; - content: ""; -} - -.form-actions:after { - clear: both; -} - -.help-block, -.help-inline { - color: #595959; -} - -.help-block { - display: block; - margin-bottom: 10px; -} - -.help-inline { - display: inline-block; - *display: inline; - padding-left: 5px; - vertical-align: middle; - *zoom: 1; -} - -.input-append, -.input-prepend { - display: inline-block; - margin-bottom: 10px; - font-size: 0; - white-space: nowrap; - vertical-align: middle; -} - -.input-append input, -.input-prepend input, -.input-append select, -.input-prepend select, -.input-append .uneditable-input, -.input-prepend .uneditable-input, -.input-append .dropdown-menu, -.input-prepend .dropdown-menu, -.input-append .popover, -.input-prepend .popover { - font-size: 14px; -} - -.input-append input, -.input-prepend input, -.input-append select, -.input-prepend select, -.input-append .uneditable-input, -.input-prepend .uneditable-input { - position: relative; - margin-bottom: 0; - *margin-left: 0; - vertical-align: top; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-append input:focus, -.input-prepend input:focus, -.input-append select:focus, -.input-prepend select:focus, -.input-append .uneditable-input:focus, -.input-prepend .uneditable-input:focus { - z-index: 2; -} - -.input-append .add-on, -.input-prepend .add-on { - display: inline-block; - width: auto; - height: 20px; - min-width: 16px; - padding: 4px 5px; - font-size: 14px; - font-weight: normal; - line-height: 20px; - text-align: center; - text-shadow: 0 1px 0 #ffffff; - background-color: #eeeeee; - border: 1px solid #ccc; -} - -.input-append .add-on, -.input-prepend .add-on, -.input-append .btn, -.input-prepend .btn, -.input-append .btn-group > .dropdown-toggle, -.input-prepend .btn-group > .dropdown-toggle { - vertical-align: top; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.input-append .active, -.input-prepend .active { - background-color: #a9dba9; - border-color: #46a546; -} - -.input-prepend .add-on, -.input-prepend .btn { - margin-right: -1px; -} - -.input-prepend .add-on:first-child, -.input-prepend .btn:first-child { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-append input, -.input-append select, -.input-append .uneditable-input { - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-append input + .btn-group .btn:last-child, -.input-append select + .btn-group .btn:last-child, -.input-append .uneditable-input + .btn-group .btn:last-child { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-append .add-on, -.input-append .btn, -.input-append .btn-group { - margin-left: -1px; -} - -.input-append .add-on:last-child, -.input-append .btn:last-child, -.input-append .btn-group:last-child > .dropdown-toggle { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append input, -.input-prepend.input-append select, -.input-prepend.input-append .uneditable-input { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.input-prepend.input-append input + .btn-group .btn, -.input-prepend.input-append select + .btn-group .btn, -.input-prepend.input-append .uneditable-input + .btn-group .btn { - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append .add-on:first-child, -.input-prepend.input-append .btn:first-child { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.input-prepend.input-append .add-on:last-child, -.input-prepend.input-append .btn:last-child { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.input-prepend.input-append .btn-group:first-child { - margin-left: 0; -} - -input.search-query { - padding-right: 14px; - padding-right: 4px \9; - padding-left: 14px; - padding-left: 4px \9; - /* IE7-8 doesn't have border-radius, so don't indent the padding */ - - margin-bottom: 0; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -/* Allow for input prepend/append in search forms */ - -.form-search .input-append .search-query, -.form-search .input-prepend .search-query { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.form-search .input-append .search-query { - -webkit-border-radius: 14px 0 0 14px; - -moz-border-radius: 14px 0 0 14px; - border-radius: 14px 0 0 14px; -} - -.form-search .input-append .btn { - -webkit-border-radius: 0 14px 14px 0; - -moz-border-radius: 0 14px 14px 0; - border-radius: 0 14px 14px 0; -} - -.form-search .input-prepend .search-query { - -webkit-border-radius: 0 14px 14px 0; - -moz-border-radius: 0 14px 14px 0; - border-radius: 0 14px 14px 0; -} - -.form-search .input-prepend .btn { - -webkit-border-radius: 14px 0 0 14px; - -moz-border-radius: 14px 0 0 14px; - border-radius: 14px 0 0 14px; -} - -.form-search input, -.form-inline input, -.form-horizontal input, -.form-search textarea, -.form-inline textarea, -.form-horizontal textarea, -.form-search select, -.form-inline select, -.form-horizontal select, -.form-search .help-inline, -.form-inline .help-inline, -.form-horizontal .help-inline, -.form-search .uneditable-input, -.form-inline .uneditable-input, -.form-horizontal .uneditable-input, -.form-search .input-prepend, -.form-inline .input-prepend, -.form-horizontal .input-prepend, -.form-search .input-append, -.form-inline .input-append, -.form-horizontal .input-append { - display: inline-block; - *display: inline; - margin-bottom: 0; - vertical-align: middle; - *zoom: 1; -} - -.form-search .hide, -.form-inline .hide, -.form-horizontal .hide { - display: none; -} - -.form-search label, -.form-inline label, -.form-search .btn-group, -.form-inline .btn-group { - display: inline-block; -} - -.form-search .input-append, -.form-inline .input-append, -.form-search .input-prepend, -.form-inline .input-prepend { - margin-bottom: 0; -} - -.form-search .radio, -.form-search .checkbox, -.form-inline .radio, -.form-inline .checkbox { - padding-left: 0; - margin-bottom: 0; - vertical-align: middle; -} - -.form-search .radio input[type="radio"], -.form-search .checkbox input[type="checkbox"], -.form-inline .radio input[type="radio"], -.form-inline .checkbox input[type="checkbox"] { - float: left; - margin-right: 3px; - margin-left: 0; -} - -.control-group { - margin-bottom: 10px; -} - -legend + .control-group { - margin-top: 20px; - -webkit-margin-top-collapse: separate; -} - -.form-horizontal .control-group { - margin-bottom: 20px; - *zoom: 1; -} - -.form-horizontal .control-group:before, -.form-horizontal .control-group:after { - display: table; - line-height: 0; - content: ""; -} - -.form-horizontal .control-group:after { - clear: both; -} - -.form-horizontal .control-label { - float: left; - width: 160px; - padding-top: 5px; - text-align: right; -} - -.form-horizontal .controls { - *display: inline-block; - *padding-left: 20px; - margin-left: 180px; - *margin-left: 0; -} - -.form-horizontal .controls:first-child { - *padding-left: 180px; -} - -.form-horizontal .help-block { - margin-bottom: 0; -} - -.form-horizontal input + .help-block, -.form-horizontal select + .help-block, -.form-horizontal textarea + .help-block, -.form-horizontal .uneditable-input + .help-block, -.form-horizontal .input-prepend + .help-block, -.form-horizontal .input-append + .help-block { - margin-top: 10px; -} - -.form-horizontal .form-actions { - padding-left: 180px; -} - -table { - max-width: 100%; - background-color: transparent; - border-collapse: collapse; - border-spacing: 0; -} - -.table { - width: 100%; - margin-bottom: 20px; -} - -.table th, -.table td { - padding: 8px; - line-height: 20px; - text-align: left; - vertical-align: top; - border-top: 1px solid #dddddd; -} - -.table th { - font-weight: bold; -} - -.table thead th { - vertical-align: bottom; -} - -.table caption + thead tr:first-child th, -.table caption + thead tr:first-child td, -.table colgroup + thead tr:first-child th, -.table colgroup + thead tr:first-child td, -.table thead:first-child tr:first-child th, -.table thead:first-child tr:first-child td { - border-top: 0; -} - -.table tbody + tbody { - border-top: 2px solid #dddddd; -} - -.table .table { - background-color: #ffffff; -} - -.table-condensed th, -.table-condensed td { - padding: 4px 5px; -} - -.table-bordered { - border: 1px solid #dddddd; - border-collapse: separate; - *border-collapse: collapse; - border-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.table-bordered th, -.table-bordered td { - border-left: 1px solid #dddddd; -} - -.table-bordered caption + thead tr:first-child th, -.table-bordered caption + tbody tr:first-child th, -.table-bordered caption + tbody tr:first-child td, -.table-bordered colgroup + thead tr:first-child th, -.table-bordered colgroup + tbody tr:first-child th, -.table-bordered colgroup + tbody tr:first-child td, -.table-bordered thead:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child th, -.table-bordered tbody:first-child tr:first-child td { - border-top: 0; -} - -.table-bordered thead:first-child tr:first-child > th:first-child, -.table-bordered tbody:first-child tr:first-child > td:first-child, -.table-bordered tbody:first-child tr:first-child > th:first-child { - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; -} - -.table-bordered thead:first-child tr:first-child > th:last-child, -.table-bordered tbody:first-child tr:first-child > td:last-child, -.table-bordered tbody:first-child tr:first-child > th:last-child { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} - -.table-bordered thead:last-child tr:last-child > th:first-child, -.table-bordered tbody:last-child tr:last-child > td:first-child, -.table-bordered tbody:last-child tr:last-child > th:first-child, -.table-bordered tfoot:last-child tr:last-child > td:first-child, -.table-bordered tfoot:last-child tr:last-child > th:first-child { - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; -} - -.table-bordered thead:last-child tr:last-child > th:last-child, -.table-bordered tbody:last-child tr:last-child > td:last-child, -.table-bordered tbody:last-child tr:last-child > th:last-child, -.table-bordered tfoot:last-child tr:last-child > td:last-child, -.table-bordered tfoot:last-child tr:last-child > th:last-child { - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; -} - -.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { - -webkit-border-bottom-left-radius: 0; - border-bottom-left-radius: 0; - -moz-border-radius-bottomleft: 0; -} - -.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { - -webkit-border-bottom-right-radius: 0; - border-bottom-right-radius: 0; - -moz-border-radius-bottomright: 0; -} - -.table-bordered caption + thead tr:first-child th:first-child, -.table-bordered caption + tbody tr:first-child td:first-child, -.table-bordered colgroup + thead tr:first-child th:first-child, -.table-bordered colgroup + tbody tr:first-child td:first-child { - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; -} - -.table-bordered caption + thead tr:first-child th:last-child, -.table-bordered caption + tbody tr:first-child td:last-child, -.table-bordered colgroup + thead tr:first-child th:last-child, -.table-bordered colgroup + tbody tr:first-child td:last-child { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} - -.table-striped tbody > tr:nth-child(odd) > td, -.table-striped tbody > tr:nth-child(odd) > th { - background-color: #f9f9f9; -} - -.table-hover tbody tr:hover > td, -.table-hover tbody tr:hover > th { - background-color: #f5f5f5; -} - -table td[class*="span"], -table th[class*="span"], -.row-fluid table td[class*="span"], -.row-fluid table th[class*="span"] { - display: table-cell; - float: none; - margin-left: 0; -} - -.table td.span1, -.table th.span1 { - float: none; - width: 44px; - margin-left: 0; -} - -.table td.span2, -.table th.span2 { - float: none; - width: 124px; - margin-left: 0; -} - -.table td.span3, -.table th.span3 { - float: none; - width: 204px; - margin-left: 0; -} - -.table td.span4, -.table th.span4 { - float: none; - width: 284px; - margin-left: 0; -} - -.table td.span5, -.table th.span5 { - float: none; - width: 364px; - margin-left: 0; -} - -.table td.span6, -.table th.span6 { - float: none; - width: 444px; - margin-left: 0; -} - -.table td.span7, -.table th.span7 { - float: none; - width: 524px; - margin-left: 0; -} - -.table td.span8, -.table th.span8 { - float: none; - width: 604px; - margin-left: 0; -} - -.table td.span9, -.table th.span9 { - float: none; - width: 684px; - margin-left: 0; -} - -.table td.span10, -.table th.span10 { - float: none; - width: 764px; - margin-left: 0; -} - -.table td.span11, -.table th.span11 { - float: none; - width: 844px; - margin-left: 0; -} - -.table td.span12, -.table th.span12 { - float: none; - width: 924px; - margin-left: 0; -} - -.table tbody tr.success > td { - background-color: #dff0d8; -} - -.table tbody tr.error > td { - background-color: #f2dede; -} - -.table tbody tr.warning > td { - background-color: #fcf8e3; -} - -.table tbody tr.info > td { - background-color: #d9edf7; -} - -.table-hover tbody tr.success:hover > td { - background-color: #d0e9c6; -} - -.table-hover tbody tr.error:hover > td { - background-color: #ebcccc; -} - -.table-hover tbody tr.warning:hover > td { - background-color: #faf2cc; -} - -.table-hover tbody tr.info:hover > td { - background-color: #c4e3f3; -} - -[class^="icon-"], -[class*=" icon-"] { - display: inline-block; - width: 14px; - height: 14px; - margin-top: 1px; - *margin-right: .3em; - line-height: 14px; - vertical-align: text-top; - background-image: url("../img/glyphicons-halflings.png"); - background-position: 14px 14px; - background-repeat: no-repeat; -} - -/* White icons with optional class, or on hover/focus/active states of certain elements */ - -.icon-white, -.nav-pills > .active > a > [class^="icon-"], -.nav-pills > .active > a > [class*=" icon-"], -.nav-list > .active > a > [class^="icon-"], -.nav-list > .active > a > [class*=" icon-"], -.navbar-inverse .nav > .active > a > [class^="icon-"], -.navbar-inverse .nav > .active > a > [class*=" icon-"], -.dropdown-menu > li > a:hover > [class^="icon-"], -.dropdown-menu > li > a:focus > [class^="icon-"], -.dropdown-menu > li > a:hover > [class*=" icon-"], -.dropdown-menu > li > a:focus > [class*=" icon-"], -.dropdown-menu > .active > a > [class^="icon-"], -.dropdown-menu > .active > a > [class*=" icon-"], -.dropdown-submenu:hover > a > [class^="icon-"], -.dropdown-submenu:focus > a > [class^="icon-"], -.dropdown-submenu:hover > a > [class*=" icon-"], -.dropdown-submenu:focus > a > [class*=" icon-"] { - background-image: url("../img/glyphicons-halflings-white.png"); -} - -.icon-glass { - background-position: 0 0; -} - -.icon-music { - background-position: -24px 0; -} - -.icon-search { - background-position: -48px 0; -} - -.icon-envelope { - background-position: -72px 0; -} - -.icon-heart { - background-position: -96px 0; -} - -.icon-star { - background-position: -120px 0; -} - -.icon-star-empty { - background-position: -144px 0; -} - -.icon-user { - background-position: -168px 0; -} - -.icon-film { - background-position: -192px 0; -} - -.icon-th-large { - background-position: -216px 0; -} - -.icon-th { - background-position: -240px 0; -} - -.icon-th-list { - background-position: -264px 0; -} - -.icon-ok { - background-position: -288px 0; -} - -.icon-remove { - background-position: -312px 0; -} - -.icon-zoom-in { - background-position: -336px 0; -} - -.icon-zoom-out { - background-position: -360px 0; -} - -.icon-off { - background-position: -384px 0; -} - -.icon-signal { - background-position: -408px 0; -} - -.icon-cog { - background-position: -432px 0; -} - -.icon-trash { - background-position: -456px 0; -} - -.icon-home { - background-position: 0 -24px; -} - -.icon-file { - background-position: -24px -24px; -} - -.icon-time { - background-position: -48px -24px; -} - -.icon-road { - background-position: -72px -24px; -} - -.icon-download-alt { - background-position: -96px -24px; -} - -.icon-download { - background-position: -120px -24px; -} - -.icon-upload { - background-position: -144px -24px; -} - -.icon-inbox { - background-position: -168px -24px; -} - -.icon-play-circle { - background-position: -192px -24px; -} - -.icon-repeat { - background-position: -216px -24px; -} - -.icon-refresh { - background-position: -240px -24px; -} - -.icon-list-alt { - background-position: -264px -24px; -} - -.icon-lock { - background-position: -287px -24px; -} - -.icon-flag { - background-position: -312px -24px; -} - -.icon-headphones { - background-position: -336px -24px; -} - -.icon-volume-off { - background-position: -360px -24px; -} - -.icon-volume-down { - background-position: -384px -24px; -} - -.icon-volume-up { - background-position: -408px -24px; -} - -.icon-qrcode { - background-position: -432px -24px; -} - -.icon-barcode { - background-position: -456px -24px; -} - -.icon-tag { - background-position: 0 -48px; -} - -.icon-tags { - background-position: -25px -48px; -} - -.icon-book { - background-position: -48px -48px; -} - -.icon-bookmark { - background-position: -72px -48px; -} - -.icon-print { - background-position: -96px -48px; -} - -.icon-camera { - background-position: -120px -48px; -} - -.icon-font { - background-position: -144px -48px; -} - -.icon-bold { - background-position: -167px -48px; -} - -.icon-italic { - background-position: -192px -48px; -} - -.icon-text-height { - background-position: -216px -48px; -} - -.icon-text-width { - background-position: -240px -48px; -} - -.icon-align-left { - background-position: -264px -48px; -} - -.icon-align-center { - background-position: -288px -48px; -} - -.icon-align-right { - background-position: -312px -48px; -} - -.icon-align-justify { - background-position: -336px -48px; -} - -.icon-list { - background-position: -360px -48px; -} - -.icon-indent-left { - background-position: -384px -48px; -} - -.icon-indent-right { - background-position: -408px -48px; -} - -.icon-facetime-video { - background-position: -432px -48px; -} - -.icon-picture { - background-position: -456px -48px; -} - -.icon-pencil { - background-position: 0 -72px; -} - -.icon-map-marker { - background-position: -24px -72px; -} - -.icon-adjust { - background-position: -48px -72px; -} - -.icon-tint { - background-position: -72px -72px; -} - -.icon-edit { - background-position: -96px -72px; -} - -.icon-share { - background-position: -120px -72px; -} - -.icon-check { - background-position: -144px -72px; -} - -.icon-move { - background-position: -168px -72px; -} - -.icon-step-backward { - background-position: -192px -72px; -} - -.icon-fast-backward { - background-position: -216px -72px; -} - -.icon-backward { - background-position: -240px -72px; -} - -.icon-play { - background-position: -264px -72px; -} - -.icon-pause { - background-position: -288px -72px; -} - -.icon-stop { - background-position: -312px -72px; -} - -.icon-forward { - background-position: -336px -72px; -} - -.icon-fast-forward { - background-position: -360px -72px; -} - -.icon-step-forward { - background-position: -384px -72px; -} - -.icon-eject { - background-position: -408px -72px; -} - -.icon-chevron-left { - background-position: -432px -72px; -} - -.icon-chevron-right { - background-position: -456px -72px; -} - -.icon-plus-sign { - background-position: 0 -96px; -} - -.icon-minus-sign { - background-position: -24px -96px; -} - -.icon-remove-sign { - background-position: -48px -96px; -} - -.icon-ok-sign { - background-position: -72px -96px; -} - -.icon-question-sign { - background-position: -96px -96px; -} - -.icon-info-sign { - background-position: -120px -96px; -} - -.icon-screenshot { - background-position: -144px -96px; -} - -.icon-remove-circle { - background-position: -168px -96px; -} - -.icon-ok-circle { - background-position: -192px -96px; -} - -.icon-ban-circle { - background-position: -216px -96px; -} - -.icon-arrow-left { - background-position: -240px -96px; -} - -.icon-arrow-right { - background-position: -264px -96px; -} - -.icon-arrow-up { - background-position: -289px -96px; -} - -.icon-arrow-down { - background-position: -312px -96px; -} - -.icon-share-alt { - background-position: -336px -96px; -} - -.icon-resize-full { - background-position: -360px -96px; -} - -.icon-resize-small { - background-position: -384px -96px; -} - -.icon-plus { - background-position: -408px -96px; -} - -.icon-minus { - background-position: -433px -96px; -} - -.icon-asterisk { - background-position: -456px -96px; -} - -.icon-exclamation-sign { - background-position: 0 -120px; -} - -.icon-gift { - background-position: -24px -120px; -} - -.icon-leaf { - background-position: -48px -120px; -} - -.icon-fire { - background-position: -72px -120px; -} - -.icon-eye-open { - background-position: -96px -120px; -} - -.icon-eye-close { - background-position: -120px -120px; -} - -.icon-warning-sign { - background-position: -144px -120px; -} - -.icon-plane { - background-position: -168px -120px; -} - -.icon-calendar { - background-position: -192px -120px; -} - -.icon-random { - width: 16px; - background-position: -216px -120px; -} - -.icon-comment { - background-position: -240px -120px; -} - -.icon-magnet { - background-position: -264px -120px; -} - -.icon-chevron-up { - background-position: -288px -120px; -} - -.icon-chevron-down { - background-position: -313px -119px; -} - -.icon-retweet { - background-position: -336px -120px; -} - -.icon-shopping-cart { - background-position: -360px -120px; -} - -.icon-folder-close { - width: 16px; - background-position: -384px -120px; -} - -.icon-folder-open { - width: 16px; - background-position: -408px -120px; -} - -.icon-resize-vertical { - background-position: -432px -119px; -} - -.icon-resize-horizontal { - background-position: -456px -118px; -} - -.icon-hdd { - background-position: 0 -144px; -} - -.icon-bullhorn { - background-position: -24px -144px; -} - -.icon-bell { - background-position: -48px -144px; -} - -.icon-certificate { - background-position: -72px -144px; -} - -.icon-thumbs-up { - background-position: -96px -144px; -} - -.icon-thumbs-down { - background-position: -120px -144px; -} - -.icon-hand-right { - background-position: -144px -144px; -} - -.icon-hand-left { - background-position: -168px -144px; -} - -.icon-hand-up { - background-position: -192px -144px; -} - -.icon-hand-down { - background-position: -216px -144px; -} - -.icon-circle-arrow-right { - background-position: -240px -144px; -} - -.icon-circle-arrow-left { - background-position: -264px -144px; -} - -.icon-circle-arrow-up { - background-position: -288px -144px; -} - -.icon-circle-arrow-down { - background-position: -312px -144px; -} - -.icon-globe { - background-position: -336px -144px; -} - -.icon-wrench { - background-position: -360px -144px; -} - -.icon-tasks { - background-position: -384px -144px; -} - -.icon-filter { - background-position: -408px -144px; -} - -.icon-briefcase { - background-position: -432px -144px; -} - -.icon-fullscreen { - background-position: -456px -144px; -} - -.dropup, -.dropdown { - position: relative; -} - -.dropdown-toggle { - *margin-bottom: -3px; -} - -.dropdown-toggle:active, -.open .dropdown-toggle { - outline: 0; -} - -.caret { - display: inline-block; - width: 0; - height: 0; - vertical-align: top; - border-top: 4px solid #000000; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - content: ""; -} - -.dropdown .caret { - margin-top: 8px; - margin-left: 2px; -} - -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - list-style: none; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - *border-right-width: 2px; - *border-bottom-width: 2px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} - -.dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.dropdown-menu .divider { - *width: 100%; - height: 1px; - margin: 9px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} - -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 20px; - color: #333333; - white-space: nowrap; -} - -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus, -.dropdown-submenu:hover > a, -.dropdown-submenu:focus > a { - color: #ffffff; - text-decoration: none; - background-color: #0081c2; - background-image: -moz-linear-gradient(top, #0088cc, #0077b3); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); - background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); - background-image: -o-linear-gradient(top, #0088cc, #0077b3); - background-image: linear-gradient(to bottom, #0088cc, #0077b3); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); -} - -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #ffffff; - text-decoration: none; - background-color: #0081c2; - background-image: -moz-linear-gradient(top, #0088cc, #0077b3); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); - background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); - background-image: -o-linear-gradient(top, #0088cc, #0077b3); - background-image: linear-gradient(to bottom, #0088cc, #0077b3); - background-repeat: repeat-x; - outline: 0; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); -} - -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #999999; -} - -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: default; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.open { - *z-index: 1000; -} - -.open > .dropdown-menu { - display: block; -} - -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} - -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} - -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - border-top: 0; - border-bottom: 4px solid #000000; - content: ""; -} - -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} - -.dropdown-submenu { - position: relative; -} - -.dropdown-submenu > .dropdown-menu { - top: 0; - left: 100%; - margin-top: -6px; - margin-left: -1px; - -webkit-border-radius: 0 6px 6px 6px; - -moz-border-radius: 0 6px 6px 6px; - border-radius: 0 6px 6px 6px; -} - -.dropdown-submenu:hover > .dropdown-menu { - display: block; -} - -.dropup .dropdown-submenu > .dropdown-menu { - top: auto; - bottom: 0; - margin-top: 0; - margin-bottom: -2px; - -webkit-border-radius: 5px 5px 5px 0; - -moz-border-radius: 5px 5px 5px 0; - border-radius: 5px 5px 5px 0; -} - -.dropdown-submenu > a:after { - display: block; - float: right; - width: 0; - height: 0; - margin-top: 5px; - margin-right: -10px; - border-color: transparent; - border-left-color: #cccccc; - border-style: solid; - border-width: 5px 0 5px 5px; - content: " "; -} - -.dropdown-submenu:hover > a:after { - border-left-color: #ffffff; -} - -.dropdown-submenu.pull-left { - float: none; -} - -.dropdown-submenu.pull-left > .dropdown-menu { - left: -100%; - margin-left: 10px; - -webkit-border-radius: 6px 0 6px 6px; - -moz-border-radius: 6px 0 6px 6px; - border-radius: 6px 0 6px 6px; -} - -.dropdown .dropdown-menu .nav-header { - padding-right: 20px; - padding-left: 20px; -} - -.typeahead { - z-index: 1051; - margin-top: 2px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} - -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} - -.well-large { - padding: 24px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.well-small { - padding: 9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - -moz-transition: opacity 0.15s linear; - -o-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} - -.fade.in { - opacity: 1; -} - -.collapse { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height 0.35s ease; - -moz-transition: height 0.35s ease; - -o-transition: height 0.35s ease; - transition: height 0.35s ease; -} - -.collapse.in { - height: auto; -} - -.close { - float: right; - font-size: 20px; - font-weight: bold; - line-height: 20px; - color: #000000; - text-shadow: 0 1px 0 #ffffff; - opacity: 0.2; - filter: alpha(opacity=20); -} - -.close:hover, -.close:focus { - color: #000000; - text-decoration: none; - cursor: pointer; - opacity: 0.4; - filter: alpha(opacity=40); -} - -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} - -.btn { - display: inline-block; - *display: inline; - padding: 4px 12px; - margin-bottom: 0; - *margin-left: .3em; - font-size: 14px; - line-height: 20px; - color: #333333; - text-align: center; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - vertical-align: middle; - cursor: pointer; - background-color: #f5f5f5; - *background-color: #e6e6e6; - background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); - background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); - background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); - background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); - background-repeat: repeat-x; - border: 1px solid #cccccc; - *border: 0; - border-color: #e6e6e6 #e6e6e6 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-bottom-color: #b3b3b3; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn:hover, -.btn:focus, -.btn:active, -.btn.active, -.btn.disabled, -.btn[disabled] { - color: #333333; - background-color: #e6e6e6; - *background-color: #d9d9d9; -} - -.btn:active, -.btn.active { - background-color: #cccccc \9; -} - -.btn:first-child { - *margin-left: 0; -} - -.btn:hover, -.btn:focus { - color: #333333; - text-decoration: none; - background-position: 0 -15px; - -webkit-transition: background-position 0.1s linear; - -moz-transition: background-position 0.1s linear; - -o-transition: background-position 0.1s linear; - transition: background-position 0.1s linear; -} - -.btn:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.btn.active, -.btn:active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn.disabled, -.btn[disabled] { - cursor: default; - background-image: none; - opacity: 0.65; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} - -.btn-large { - padding: 11px 19px; - font-size: 17.5px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.btn-large [class^="icon-"], -.btn-large [class*=" icon-"] { - margin-top: 4px; -} - -.btn-small { - padding: 2px 10px; - font-size: 11.9px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.btn-small [class^="icon-"], -.btn-small [class*=" icon-"] { - margin-top: 0; -} - -.btn-mini [class^="icon-"], -.btn-mini [class*=" icon-"] { - margin-top: -1px; -} - -.btn-mini { - padding: 0 6px; - font-size: 10.5px; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.btn-block { - display: block; - width: 100%; - padding-right: 0; - padding-left: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -.btn-block + .btn-block { - margin-top: 5px; -} - -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} - -.btn-primary.active, -.btn-warning.active, -.btn-danger.active, -.btn-success.active, -.btn-info.active, -.btn-inverse.active { - color: rgba(255, 255, 255, 0.75); -} - -.btn-primary { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #006dcc; - *background-color: #0044cc; - background-image: -moz-linear-gradient(top, #0088cc, #0044cc); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); - background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); - background-image: -o-linear-gradient(top, #0088cc, #0044cc); - background-image: linear-gradient(to bottom, #0088cc, #0044cc); - background-repeat: repeat-x; - border-color: #0044cc #0044cc #002a80; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.btn-primary.disabled, -.btn-primary[disabled] { - color: #ffffff; - background-color: #0044cc; - *background-color: #003bb3; -} - -.btn-primary:active, -.btn-primary.active { - background-color: #003399 \9; -} - -.btn-warning { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #faa732; - *background-color: #f89406; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(to bottom, #fbb450, #f89406); - background-repeat: repeat-x; - border-color: #f89406 #f89406 #ad6704; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-warning:hover, -.btn-warning:focus, -.btn-warning:active, -.btn-warning.active, -.btn-warning.disabled, -.btn-warning[disabled] { - color: #ffffff; - background-color: #f89406; - *background-color: #df8505; -} - -.btn-warning:active, -.btn-warning.active { - background-color: #c67605 \9; -} - -.btn-danger { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #da4f49; - *background-color: #bd362f; - background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); - background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); - background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); - background-repeat: repeat-x; - border-color: #bd362f #bd362f #802420; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-danger:hover, -.btn-danger:focus, -.btn-danger:active, -.btn-danger.active, -.btn-danger.disabled, -.btn-danger[disabled] { - color: #ffffff; - background-color: #bd362f; - *background-color: #a9302a; -} - -.btn-danger:active, -.btn-danger.active { - background-color: #942a25 \9; -} - -.btn-success { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #5bb75b; - *background-color: #51a351; - background-image: -moz-linear-gradient(top, #62c462, #51a351); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); - background-image: -webkit-linear-gradient(top, #62c462, #51a351); - background-image: -o-linear-gradient(top, #62c462, #51a351); - background-image: linear-gradient(to bottom, #62c462, #51a351); - background-repeat: repeat-x; - border-color: #51a351 #51a351 #387038; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-success:hover, -.btn-success:focus, -.btn-success:active, -.btn-success.active, -.btn-success.disabled, -.btn-success[disabled] { - color: #ffffff; - background-color: #51a351; - *background-color: #499249; -} - -.btn-success:active, -.btn-success.active { - background-color: #408140 \9; -} - -.btn-info { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #49afcd; - *background-color: #2f96b4; - background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); - background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); - background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); - background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); - background-repeat: repeat-x; - border-color: #2f96b4 #2f96b4 #1f6377; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-info:hover, -.btn-info:focus, -.btn-info:active, -.btn-info.active, -.btn-info.disabled, -.btn-info[disabled] { - color: #ffffff; - background-color: #2f96b4; - *background-color: #2a85a0; -} - -.btn-info:active, -.btn-info.active { - background-color: #24748c \9; -} - -.btn-inverse { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #363636; - *background-color: #222222; - background-image: -moz-linear-gradient(top, #444444, #222222); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); - background-image: -webkit-linear-gradient(top, #444444, #222222); - background-image: -o-linear-gradient(top, #444444, #222222); - background-image: linear-gradient(to bottom, #444444, #222222); - background-repeat: repeat-x; - border-color: #222222 #222222 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.btn-inverse:hover, -.btn-inverse:focus, -.btn-inverse:active, -.btn-inverse.active, -.btn-inverse.disabled, -.btn-inverse[disabled] { - color: #ffffff; - background-color: #222222; - *background-color: #151515; -} - -.btn-inverse:active, -.btn-inverse.active { - background-color: #080808 \9; -} - -button.btn, -input[type="submit"].btn { - *padding-top: 3px; - *padding-bottom: 3px; -} - -button.btn::-moz-focus-inner, -input[type="submit"].btn::-moz-focus-inner { - padding: 0; - border: 0; -} - -button.btn.btn-large, -input[type="submit"].btn.btn-large { - *padding-top: 7px; - *padding-bottom: 7px; -} - -button.btn.btn-small, -input[type="submit"].btn.btn-small { - *padding-top: 3px; - *padding-bottom: 3px; -} - -button.btn.btn-mini, -input[type="submit"].btn.btn-mini { - *padding-top: 1px; - *padding-bottom: 1px; -} - -.btn-link, -.btn-link:active, -.btn-link[disabled] { - background-color: transparent; - background-image: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} - -.btn-link { - color: #0088cc; - cursor: pointer; - border-color: transparent; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-link:hover, -.btn-link:focus { - color: #005580; - text-decoration: underline; - background-color: transparent; -} - -.btn-link[disabled]:hover, -.btn-link[disabled]:focus { - color: #333333; - text-decoration: none; -} - -.btn-group { - position: relative; - display: inline-block; - *display: inline; - *margin-left: .3em; - font-size: 0; - white-space: nowrap; - vertical-align: middle; - *zoom: 1; -} - -.btn-group:first-child { - *margin-left: 0; -} - -.btn-group + .btn-group { - margin-left: 5px; -} - -.btn-toolbar { - margin-top: 10px; - margin-bottom: 10px; - font-size: 0; -} - -.btn-toolbar > .btn + .btn, -.btn-toolbar > .btn-group + .btn, -.btn-toolbar > .btn + .btn-group { - margin-left: 5px; -} - -.btn-group > .btn { - position: relative; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-group > .btn + .btn { - margin-left: -1px; -} - -.btn-group > .btn, -.btn-group > .dropdown-menu, -.btn-group > .popover { - font-size: 14px; -} - -.btn-group > .btn-mini { - font-size: 10.5px; -} - -.btn-group > .btn-small { - font-size: 11.9px; -} - -.btn-group > .btn-large { - font-size: 17.5px; -} - -.btn-group > .btn:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-topleft: 4px; -} - -.btn-group > .btn:last-child, -.btn-group > .dropdown-toggle { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; -} - -.btn-group > .btn.large:first-child { - margin-left: 0; - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; - -webkit-border-top-left-radius: 6px; - border-top-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-topleft: 6px; -} - -.btn-group > .btn.large:last-child, -.btn-group > .large.dropdown-toggle { - -webkit-border-top-right-radius: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-topright: 6px; - -moz-border-radius-bottomright: 6px; -} - -.btn-group > .btn:hover, -.btn-group > .btn:focus, -.btn-group > .btn:active, -.btn-group > .btn.active { - z-index: 2; -} - -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} - -.btn-group > .btn + .dropdown-toggle { - *padding-top: 5px; - padding-right: 8px; - *padding-bottom: 5px; - padding-left: 8px; - -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn-group > .btn-mini + .dropdown-toggle { - *padding-top: 2px; - padding-right: 5px; - *padding-bottom: 2px; - padding-left: 5px; -} - -.btn-group > .btn-small + .dropdown-toggle { - *padding-top: 5px; - *padding-bottom: 4px; -} - -.btn-group > .btn-large + .dropdown-toggle { - *padding-top: 7px; - padding-right: 12px; - *padding-bottom: 7px; - padding-left: 12px; -} - -.btn-group.open .dropdown-toggle { - background-image: none; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn-group.open .btn.dropdown-toggle { - background-color: #e6e6e6; -} - -.btn-group.open .btn-primary.dropdown-toggle { - background-color: #0044cc; -} - -.btn-group.open .btn-warning.dropdown-toggle { - background-color: #f89406; -} - -.btn-group.open .btn-danger.dropdown-toggle { - background-color: #bd362f; -} - -.btn-group.open .btn-success.dropdown-toggle { - background-color: #51a351; -} - -.btn-group.open .btn-info.dropdown-toggle { - background-color: #2f96b4; -} - -.btn-group.open .btn-inverse.dropdown-toggle { - background-color: #222222; -} - -.btn .caret { - margin-top: 8px; - margin-left: 0; -} - -.btn-large .caret { - margin-top: 6px; -} - -.btn-large .caret { - border-top-width: 5px; - border-right-width: 5px; - border-left-width: 5px; -} - -.btn-mini .caret, -.btn-small .caret { - margin-top: 8px; -} - -.dropup .btn-large .caret { - border-bottom-width: 5px; -} - -.btn-primary .caret, -.btn-warning .caret, -.btn-danger .caret, -.btn-info .caret, -.btn-success .caret, -.btn-inverse .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.btn-group-vertical { - display: inline-block; - *display: inline; - /* IE7 inline-block hack */ - - *zoom: 1; -} - -.btn-group-vertical > .btn { - display: block; - float: none; - max-width: 100%; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.btn-group-vertical > .btn + .btn { - margin-top: -1px; - margin-left: 0; -} - -.btn-group-vertical > .btn:first-child { - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} - -.btn-group-vertical > .btn:last-child { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} - -.btn-group-vertical > .btn-large:first-child { - -webkit-border-radius: 6px 6px 0 0; - -moz-border-radius: 6px 6px 0 0; - border-radius: 6px 6px 0 0; -} - -.btn-group-vertical > .btn-large:last-child { - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; -} - -.alert { - padding: 8px 35px 8px 14px; - margin-bottom: 20px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - background-color: #fcf8e3; - border: 1px solid #fbeed5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.alert, -.alert h4 { - color: #c09853; -} - -.alert h4 { - margin: 0; -} - -.alert .close { - position: relative; - top: -2px; - right: -21px; - line-height: 20px; -} - -.alert-success { - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; -} - -.alert-success h4 { - color: #468847; -} - -.alert-danger, -.alert-error { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; -} - -.alert-danger h4, -.alert-error h4 { - color: #b94a48; -} - -.alert-info { - color: #3a87ad; - background-color: #d9edf7; - border-color: #bce8f1; -} - -.alert-info h4 { - color: #3a87ad; -} - -.alert-block { - padding-top: 14px; - padding-bottom: 14px; -} - -.alert-block > p, -.alert-block > ul { - margin-bottom: 0; -} - -.alert-block p + p { - margin-top: 5px; -} - -.nav { - margin-bottom: 20px; - margin-left: 0; - list-style: none; -} - -.nav > li > a { - display: block; -} - -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} - -.nav > li > a > img { - max-width: none; -} - -.nav > .pull-right { - float: right; -} - -.nav-header { - display: block; - padding: 3px 15px; - font-size: 11px; - font-weight: bold; - line-height: 20px; - color: #999999; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - text-transform: uppercase; -} - -.nav li + .nav-header { - margin-top: 9px; -} - -.nav-list { - padding-right: 15px; - padding-left: 15px; - margin-bottom: 0; -} - -.nav-list > li > a, -.nav-list .nav-header { - margin-right: -15px; - margin-left: -15px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -} - -.nav-list > li > a { - padding: 3px 15px; -} - -.nav-list > .active > a, -.nav-list > .active > a:hover, -.nav-list > .active > a:focus { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); - background-color: #0088cc; -} - -.nav-list [class^="icon-"], -.nav-list [class*=" icon-"] { - margin-right: 2px; -} - -.nav-list .divider { - *width: 100%; - height: 1px; - margin: 9px 1px; - *margin: -5px 0 5px; - overflow: hidden; - background-color: #e5e5e5; - border-bottom: 1px solid #ffffff; -} - -.nav-tabs, -.nav-pills { - *zoom: 1; -} - -.nav-tabs:before, -.nav-pills:before, -.nav-tabs:after, -.nav-pills:after { - display: table; - line-height: 0; - content: ""; -} - -.nav-tabs:after, -.nav-pills:after { - clear: both; -} - -.nav-tabs > li, -.nav-pills > li { - float: left; -} - -.nav-tabs > li > a, -.nav-pills > li > a { - padding-right: 12px; - padding-left: 12px; - margin-right: 2px; - line-height: 14px; -} - -.nav-tabs { - border-bottom: 1px solid #ddd; -} - -.nav-tabs > li { - margin-bottom: -1px; -} - -.nav-tabs > li > a { - padding-top: 8px; - padding-bottom: 8px; - line-height: 20px; - border: 1px solid transparent; - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; - border-radius: 4px 4px 0 0; -} - -.nav-tabs > li > a:hover, -.nav-tabs > li > a:focus { - border-color: #eeeeee #eeeeee #dddddd; -} - -.nav-tabs > .active > a, -.nav-tabs > .active > a:hover, -.nav-tabs > .active > a:focus { - color: #555555; - cursor: default; - background-color: #ffffff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} - -.nav-pills > li > a { - padding-top: 8px; - padding-bottom: 8px; - margin-top: 2px; - margin-bottom: 2px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} - -.nav-pills > .active > a, -.nav-pills > .active > a:hover, -.nav-pills > .active > a:focus { - color: #ffffff; - background-color: #0088cc; -} - -.nav-stacked > li { - float: none; -} - -.nav-stacked > li > a { - margin-right: 0; -} - -.nav-tabs.nav-stacked { - border-bottom: 0; -} - -.nav-tabs.nav-stacked > li > a { - border: 1px solid #ddd; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.nav-tabs.nav-stacked > li:first-child > a { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-topleft: 4px; -} - -.nav-tabs.nav-stacked > li:last-child > a { - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -moz-border-radius-bottomright: 4px; - -moz-border-radius-bottomleft: 4px; -} - -.nav-tabs.nav-stacked > li > a:hover, -.nav-tabs.nav-stacked > li > a:focus { - z-index: 2; - border-color: #ddd; -} - -.nav-pills.nav-stacked > li > a { - margin-bottom: 3px; -} - -.nav-pills.nav-stacked > li:last-child > a { - margin-bottom: 1px; -} - -.nav-tabs .dropdown-menu { - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; -} - -.nav-pills .dropdown-menu { - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.nav .dropdown-toggle .caret { - margin-top: 6px; - border-top-color: #0088cc; - border-bottom-color: #0088cc; -} - -.nav .dropdown-toggle:hover .caret, -.nav .dropdown-toggle:focus .caret { - border-top-color: #005580; - border-bottom-color: #005580; -} - -/* move down carets for tabs */ - -.nav-tabs .dropdown-toggle .caret { - margin-top: 8px; -} - -.nav .active .dropdown-toggle .caret { - border-top-color: #fff; - border-bottom-color: #fff; -} - -.nav-tabs .active .dropdown-toggle .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} - -.nav > .dropdown.active > a:hover, -.nav > .dropdown.active > a:focus { - cursor: pointer; -} - -.nav-tabs .open .dropdown-toggle, -.nav-pills .open .dropdown-toggle, -.nav > li.dropdown.open.active > a:hover, -.nav > li.dropdown.open.active > a:focus { - color: #ffffff; - background-color: #999999; - border-color: #999999; -} - -.nav li.dropdown.open .caret, -.nav li.dropdown.open.active .caret, -.nav li.dropdown.open a:hover .caret, -.nav li.dropdown.open a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; - opacity: 1; - filter: alpha(opacity=100); -} - -.tabs-stacked .open > a:hover, -.tabs-stacked .open > a:focus { - border-color: #999999; -} - -.tabbable { - *zoom: 1; -} - -.tabbable:before, -.tabbable:after { - display: table; - line-height: 0; - content: ""; -} - -.tabbable:after { - clear: both; -} - -.tab-content { - overflow: auto; -} - -.tabs-below > .nav-tabs, -.tabs-right > .nav-tabs, -.tabs-left > .nav-tabs { - border-bottom: 0; -} - -.tab-content > .tab-pane, -.pill-content > .pill-pane { - display: none; -} - -.tab-content > .active, -.pill-content > .active { - display: block; -} - -.tabs-below > .nav-tabs { - border-top: 1px solid #ddd; -} - -.tabs-below > .nav-tabs > li { - margin-top: -1px; - margin-bottom: 0; -} - -.tabs-below > .nav-tabs > li > a { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius: 0 0 4px 4px; - border-radius: 0 0 4px 4px; -} - -.tabs-below > .nav-tabs > li > a:hover, -.tabs-below > .nav-tabs > li > a:focus { - border-top-color: #ddd; - border-bottom-color: transparent; -} - -.tabs-below > .nav-tabs > .active > a, -.tabs-below > .nav-tabs > .active > a:hover, -.tabs-below > .nav-tabs > .active > a:focus { - border-color: transparent #ddd #ddd #ddd; -} - -.tabs-left > .nav-tabs > li, -.tabs-right > .nav-tabs > li { - float: none; -} - -.tabs-left > .nav-tabs > li > a, -.tabs-right > .nav-tabs > li > a { - min-width: 74px; - margin-right: 0; - margin-bottom: 3px; -} - -.tabs-left > .nav-tabs { - float: left; - margin-right: 19px; - border-right: 1px solid #ddd; -} - -.tabs-left > .nav-tabs > li > a { - margin-right: -1px; - -webkit-border-radius: 4px 0 0 4px; - -moz-border-radius: 4px 0 0 4px; - border-radius: 4px 0 0 4px; -} - -.tabs-left > .nav-tabs > li > a:hover, -.tabs-left > .nav-tabs > li > a:focus { - border-color: #eeeeee #dddddd #eeeeee #eeeeee; -} - -.tabs-left > .nav-tabs .active > a, -.tabs-left > .nav-tabs .active > a:hover, -.tabs-left > .nav-tabs .active > a:focus { - border-color: #ddd transparent #ddd #ddd; - *border-right-color: #ffffff; -} - -.tabs-right > .nav-tabs { - float: right; - margin-left: 19px; - border-left: 1px solid #ddd; -} - -.tabs-right > .nav-tabs > li > a { - margin-left: -1px; - -webkit-border-radius: 0 4px 4px 0; - -moz-border-radius: 0 4px 4px 0; - border-radius: 0 4px 4px 0; -} - -.tabs-right > .nav-tabs > li > a:hover, -.tabs-right > .nav-tabs > li > a:focus { - border-color: #eeeeee #eeeeee #eeeeee #dddddd; -} - -.tabs-right > .nav-tabs .active > a, -.tabs-right > .nav-tabs .active > a:hover, -.tabs-right > .nav-tabs .active > a:focus { - border-color: #ddd #ddd #ddd transparent; - *border-left-color: #ffffff; -} - -.nav > .disabled > a { - color: #999999; -} - -.nav > .disabled > a:hover, -.nav > .disabled > a:focus { - text-decoration: none; - cursor: default; - background-color: transparent; -} - -.navbar { - *position: relative; - *z-index: 2; - margin-bottom: 20px; - overflow: visible; -} - -.navbar-inner { - min-height: 40px; - padding-right: 20px; - padding-left: 20px; - background-color: #fafafa; - background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); - background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); - background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); - background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); - background-repeat: repeat-x; - border: 1px solid #d4d4d4; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); - *zoom: 1; - -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); -} - -.navbar-inner:before, -.navbar-inner:after { - display: table; - line-height: 0; - content: ""; -} - -.navbar-inner:after { - clear: both; -} - -.navbar .container { - width: auto; -} - -.nav-collapse.collapse { - height: auto; - overflow: visible; -} - -.navbar .brand { - display: block; - float: left; - padding: 10px 20px 10px; - margin-left: -20px; - font-size: 20px; - font-weight: 200; - color: #777777; - text-shadow: 0 1px 0 #ffffff; -} - -.navbar .brand:hover, -.navbar .brand:focus { - text-decoration: none; -} - -.navbar-text { - margin-bottom: 0; - line-height: 40px; - color: #777777; -} - -.navbar-link { - color: #777777; -} - -.navbar-link:hover, -.navbar-link:focus { - color: #333333; -} - -.navbar .divider-vertical { - height: 40px; - margin: 0 9px; - border-right: 1px solid #ffffff; - border-left: 1px solid #f2f2f2; -} - -.navbar .btn, -.navbar .btn-group { - margin-top: 5px; -} - -.navbar .btn-group .btn, -.navbar .input-prepend .btn, -.navbar .input-append .btn, -.navbar .input-prepend .btn-group, -.navbar .input-append .btn-group { - margin-top: 0; -} - -.navbar-form { - margin-bottom: 0; - *zoom: 1; -} - -.navbar-form:before, -.navbar-form:after { - display: table; - line-height: 0; - content: ""; -} - -.navbar-form:after { - clear: both; -} - -.navbar-form input, -.navbar-form select, -.navbar-form .radio, -.navbar-form .checkbox { - margin-top: 5px; -} - -.navbar-form input, -.navbar-form select, -.navbar-form .btn { - display: inline-block; - margin-bottom: 0; -} - -.navbar-form input[type="image"], -.navbar-form input[type="checkbox"], -.navbar-form input[type="radio"] { - margin-top: 3px; -} - -.navbar-form .input-append, -.navbar-form .input-prepend { - margin-top: 5px; - white-space: nowrap; -} - -.navbar-form .input-append input, -.navbar-form .input-prepend input { - margin-top: 0; -} - -.navbar-search { - position: relative; - float: left; - margin-top: 5px; - margin-bottom: 0; -} - -.navbar-search .search-query { - padding: 4px 14px; - margin-bottom: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 13px; - font-weight: normal; - line-height: 1; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -.navbar-static-top { - position: static; - margin-bottom: 0; -} - -.navbar-static-top .navbar-inner { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; - margin-bottom: 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-static-top .navbar-inner { - border-width: 0 0 1px; -} - -.navbar-fixed-bottom .navbar-inner { - border-width: 1px 0 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-fixed-bottom .navbar-inner { - padding-right: 0; - padding-left: 0; - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; -} - -.navbar-static-top .container, -.navbar-fixed-top .container, -.navbar-fixed-bottom .container { - width: 940px; -} - -.navbar-fixed-top { - top: 0; -} - -.navbar-fixed-top .navbar-inner, -.navbar-static-top .navbar-inner { - -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); -} - -.navbar-fixed-bottom { - bottom: 0; -} - -.navbar-fixed-bottom .navbar-inner { - -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); - box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); -} - -.navbar .nav { - position: relative; - left: 0; - display: block; - float: left; - margin: 0 10px 0 0; -} - -.navbar .nav.pull-right { - float: right; - margin-right: 0; -} - -.navbar .nav > li { - float: left; -} - -.navbar .nav > li > a { - float: none; - padding: 10px 15px 10px; - color: #777777; - text-decoration: none; - text-shadow: 0 1px 0 #ffffff; -} - -.navbar .nav .dropdown-toggle .caret { - margin-top: 8px; -} - -.navbar .nav > li > a:focus, -.navbar .nav > li > a:hover { - color: #333333; - text-decoration: none; - background-color: transparent; -} - -.navbar .nav > .active > a, -.navbar .nav > .active > a:hover, -.navbar .nav > .active > a:focus { - color: #555555; - text-decoration: none; - background-color: #e5e5e5; - -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); -} - -.navbar .btn-navbar { - display: none; - float: right; - padding: 7px 10px; - margin-right: 5px; - margin-left: 5px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #ededed; - *background-color: #e5e5e5; - background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); - background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); - background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); - background-repeat: repeat-x; - border-color: #e5e5e5 #e5e5e5 #bfbfbf; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); -} - -.navbar .btn-navbar:hover, -.navbar .btn-navbar:focus, -.navbar .btn-navbar:active, -.navbar .btn-navbar.active, -.navbar .btn-navbar.disabled, -.navbar .btn-navbar[disabled] { - color: #ffffff; - background-color: #e5e5e5; - *background-color: #d9d9d9; -} - -.navbar .btn-navbar:active, -.navbar .btn-navbar.active { - background-color: #cccccc \9; -} - -.navbar .btn-navbar .icon-bar { - display: block; - width: 18px; - height: 2px; - background-color: #f5f5f5; - -webkit-border-radius: 1px; - -moz-border-radius: 1px; - border-radius: 1px; - -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); -} - -.btn-navbar .icon-bar + .icon-bar { - margin-top: 3px; -} - -.navbar .nav > li > .dropdown-menu:before { - position: absolute; - top: -7px; - left: 9px; - display: inline-block; - border-right: 7px solid transparent; - border-bottom: 7px solid #ccc; - border-left: 7px solid transparent; - border-bottom-color: rgba(0, 0, 0, 0.2); - content: ''; -} - -.navbar .nav > li > .dropdown-menu:after { - position: absolute; - top: -6px; - left: 10px; - display: inline-block; - border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; - border-left: 6px solid transparent; - content: ''; -} - -.navbar-fixed-bottom .nav > li > .dropdown-menu:before { - top: auto; - bottom: -7px; - border-top: 7px solid #ccc; - border-bottom: 0; - border-top-color: rgba(0, 0, 0, 0.2); -} - -.navbar-fixed-bottom .nav > li > .dropdown-menu:after { - top: auto; - bottom: -6px; - border-top: 6px solid #ffffff; - border-bottom: 0; -} - -.navbar .nav li.dropdown > a:hover .caret, -.navbar .nav li.dropdown > a:focus .caret { - border-top-color: #333333; - border-bottom-color: #333333; -} - -.navbar .nav li.dropdown.open > .dropdown-toggle, -.navbar .nav li.dropdown.active > .dropdown-toggle, -.navbar .nav li.dropdown.open.active > .dropdown-toggle { - color: #555555; - background-color: #e5e5e5; -} - -.navbar .nav li.dropdown > .dropdown-toggle .caret { - border-top-color: #777777; - border-bottom-color: #777777; -} - -.navbar .nav li.dropdown.open > .dropdown-toggle .caret, -.navbar .nav li.dropdown.active > .dropdown-toggle .caret, -.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} - -.navbar .pull-right > li > .dropdown-menu, -.navbar .nav > li > .dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu:before, -.navbar .nav > li > .dropdown-menu.pull-right:before { - right: 12px; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu:after, -.navbar .nav > li > .dropdown-menu.pull-right:after { - right: 13px; - left: auto; -} - -.navbar .pull-right > li > .dropdown-menu .dropdown-menu, -.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { - right: 100%; - left: auto; - margin-right: -1px; - margin-left: 0; - -webkit-border-radius: 6px 0 6px 6px; - -moz-border-radius: 6px 0 6px 6px; - border-radius: 6px 0 6px 6px; -} - -.navbar-inverse .navbar-inner { - background-color: #1b1b1b; - background-image: -moz-linear-gradient(top, #222222, #111111); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); - background-image: -webkit-linear-gradient(top, #222222, #111111); - background-image: -o-linear-gradient(top, #222222, #111111); - background-image: linear-gradient(to bottom, #222222, #111111); - background-repeat: repeat-x; - border-color: #252525; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); -} - -.navbar-inverse .brand, -.navbar-inverse .nav > li > a { - color: #999999; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); -} - -.navbar-inverse .brand:hover, -.navbar-inverse .nav > li > a:hover, -.navbar-inverse .brand:focus, -.navbar-inverse .nav > li > a:focus { - color: #ffffff; -} - -.navbar-inverse .brand { - color: #999999; -} - -.navbar-inverse .navbar-text { - color: #999999; -} - -.navbar-inverse .nav > li > a:focus, -.navbar-inverse .nav > li > a:hover { - color: #ffffff; - background-color: transparent; -} - -.navbar-inverse .nav .active > a, -.navbar-inverse .nav .active > a:hover, -.navbar-inverse .nav .active > a:focus { - color: #ffffff; - background-color: #111111; -} - -.navbar-inverse .navbar-link { - color: #999999; -} - -.navbar-inverse .navbar-link:hover, -.navbar-inverse .navbar-link:focus { - color: #ffffff; -} - -.navbar-inverse .divider-vertical { - border-right-color: #222222; - border-left-color: #111111; -} - -.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, -.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, -.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { - color: #ffffff; - background-color: #111111; -} - -.navbar-inverse .nav li.dropdown > a:hover .caret, -.navbar-inverse .nav li.dropdown > a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { - border-top-color: #999999; - border-bottom-color: #999999; -} - -.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, -.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, -.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} - -.navbar-inverse .navbar-search .search-query { - color: #ffffff; - background-color: #515151; - border-color: #111111; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); - -webkit-transition: none; - -moz-transition: none; - -o-transition: none; - transition: none; -} - -.navbar-inverse .navbar-search .search-query:-moz-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { - color: #cccccc; -} - -.navbar-inverse .navbar-search .search-query:focus, -.navbar-inverse .navbar-search .search-query.focused { - padding: 5px 15px; - color: #333333; - text-shadow: 0 1px 0 #ffffff; - background-color: #ffffff; - border: 0; - outline: 0; - -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); - box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -} - -.navbar-inverse .btn-navbar { - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e0e0e; - *background-color: #040404; - background-image: -moz-linear-gradient(top, #151515, #040404); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); - background-image: -webkit-linear-gradient(top, #151515, #040404); - background-image: -o-linear-gradient(top, #151515, #040404); - background-image: linear-gradient(to bottom, #151515, #040404); - background-repeat: repeat-x; - border-color: #040404 #040404 #000000; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.navbar-inverse .btn-navbar:hover, -.navbar-inverse .btn-navbar:focus, -.navbar-inverse .btn-navbar:active, -.navbar-inverse .btn-navbar.active, -.navbar-inverse .btn-navbar.disabled, -.navbar-inverse .btn-navbar[disabled] { - color: #ffffff; - background-color: #040404; - *background-color: #000000; -} - -.navbar-inverse .btn-navbar:active, -.navbar-inverse .btn-navbar.active { - background-color: #000000 \9; -} - -.breadcrumb { - padding: 8px 15px; - margin: 0 0 20px; - list-style: none; - background-color: #f5f5f5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.breadcrumb > li { - display: inline-block; - *display: inline; - text-shadow: 0 1px 0 #ffffff; - *zoom: 1; -} - -.breadcrumb > li > .divider { - padding: 0 5px; - color: #ccc; -} - -.breadcrumb > .active { - color: #999999; -} - -.pagination { - margin: 20px 0; -} - -.pagination ul { - display: inline-block; - *display: inline; - margin-bottom: 0; - margin-left: 0; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - *zoom: 1; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.pagination ul > li { - display: inline; -} - -.pagination ul > li > a, -.pagination ul > li > span { - float: left; - padding: 4px 12px; - line-height: 20px; - text-decoration: none; - background-color: #ffffff; - border: 1px solid #dddddd; - border-left-width: 0; -} - -.pagination ul > li > a:hover, -.pagination ul > li > a:focus, -.pagination ul > .active > a, -.pagination ul > .active > span { - background-color: #f5f5f5; -} - -.pagination ul > .active > a, -.pagination ul > .active > span { - color: #999999; - cursor: default; -} - -.pagination ul > .disabled > span, -.pagination ul > .disabled > a, -.pagination ul > .disabled > a:hover, -.pagination ul > .disabled > a:focus { - color: #999999; - cursor: default; - background-color: transparent; -} - -.pagination ul > li:first-child > a, -.pagination ul > li:first-child > span { - border-left-width: 1px; - -webkit-border-bottom-left-radius: 4px; - border-bottom-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - border-top-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - -moz-border-radius-topleft: 4px; -} - -.pagination ul > li:last-child > a, -.pagination ul > li:last-child > span { - -webkit-border-top-right-radius: 4px; - border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; -} - -.pagination-centered { - text-align: center; -} - -.pagination-right { - text-align: right; -} - -.pagination-large ul > li > a, -.pagination-large ul > li > span { - padding: 11px 19px; - font-size: 17.5px; -} - -.pagination-large ul > li:first-child > a, -.pagination-large ul > li:first-child > span { - -webkit-border-bottom-left-radius: 6px; - border-bottom-left-radius: 6px; - -webkit-border-top-left-radius: 6px; - border-top-left-radius: 6px; - -moz-border-radius-bottomleft: 6px; - -moz-border-radius-topleft: 6px; -} - -.pagination-large ul > li:last-child > a, -.pagination-large ul > li:last-child > span { - -webkit-border-top-right-radius: 6px; - border-top-right-radius: 6px; - -webkit-border-bottom-right-radius: 6px; - border-bottom-right-radius: 6px; - -moz-border-radius-topright: 6px; - -moz-border-radius-bottomright: 6px; -} - -.pagination-mini ul > li:first-child > a, -.pagination-small ul > li:first-child > a, -.pagination-mini ul > li:first-child > span, -.pagination-small ul > li:first-child > span { - -webkit-border-bottom-left-radius: 3px; - border-bottom-left-radius: 3px; - -webkit-border-top-left-radius: 3px; - border-top-left-radius: 3px; - -moz-border-radius-bottomleft: 3px; - -moz-border-radius-topleft: 3px; -} - -.pagination-mini ul > li:last-child > a, -.pagination-small ul > li:last-child > a, -.pagination-mini ul > li:last-child > span, -.pagination-small ul > li:last-child > span { - -webkit-border-top-right-radius: 3px; - border-top-right-radius: 3px; - -webkit-border-bottom-right-radius: 3px; - border-bottom-right-radius: 3px; - -moz-border-radius-topright: 3px; - -moz-border-radius-bottomright: 3px; -} - -.pagination-small ul > li > a, -.pagination-small ul > li > span { - padding: 2px 10px; - font-size: 11.9px; -} - -.pagination-mini ul > li > a, -.pagination-mini ul > li > span { - padding: 0 6px; - font-size: 10.5px; -} - -.pager { - margin: 20px 0; - text-align: center; - list-style: none; - *zoom: 1; -} - -.pager:before, -.pager:after { - display: table; - line-height: 0; - content: ""; -} - -.pager:after { - clear: both; -} - -.pager li { - display: inline; -} - -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - -webkit-border-radius: 15px; - -moz-border-radius: 15px; - border-radius: 15px; -} - -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #f5f5f5; -} - -.pager .next > a, -.pager .next > span { - float: right; -} - -.pager .previous > a, -.pager .previous > span { - float: left; -} - -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #999999; - cursor: default; - background-color: #fff; -} - -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000000; -} - -.modal-backdrop.fade { - opacity: 0; -} - -.modal-backdrop, -.modal-backdrop.fade.in { - opacity: 0.8; - filter: alpha(opacity=80); -} - -.modal { - position: fixed; - top: 10%; - left: 50%; - z-index: 1050; - width: 560px; - margin-left: -280px; - background-color: #ffffff; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, 0.3); - *border: 1px solid #999; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - outline: none; - -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); - -webkit-background-clip: padding-box; - -moz-background-clip: padding-box; - background-clip: padding-box; -} - -.modal.fade { - top: -25%; - -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; - -moz-transition: opacity 0.3s linear, top 0.3s ease-out; - -o-transition: opacity 0.3s linear, top 0.3s ease-out; - transition: opacity 0.3s linear, top 0.3s ease-out; -} - -.modal.fade.in { - top: 10%; -} - -.modal-header { - padding: 9px 15px; - border-bottom: 1px solid #eee; -} - -.modal-header .close { - margin-top: 2px; -} - -.modal-header h3 { - margin: 0; - line-height: 30px; -} - -.modal-body { - position: relative; - max-height: 400px; - padding: 15px; - overflow-y: auto; -} - -.modal-form { - margin-bottom: 0; -} - -.modal-footer { - padding: 14px 15px 15px; - margin-bottom: 0; - text-align: right; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - -webkit-border-radius: 0 0 6px 6px; - -moz-border-radius: 0 0 6px 6px; - border-radius: 0 0 6px 6px; - *zoom: 1; - -webkit-box-shadow: inset 0 1px 0 #ffffff; - -moz-box-shadow: inset 0 1px 0 #ffffff; - box-shadow: inset 0 1px 0 #ffffff; -} - -.modal-footer:before, -.modal-footer:after { - display: table; - line-height: 0; - content: ""; -} - -.modal-footer:after { - clear: both; -} - -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} - -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} - -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} - -.tooltip { - position: absolute; - z-index: 1030; - display: block; - font-size: 11px; - line-height: 1.4; - opacity: 0; - filter: alpha(opacity=0); - visibility: visible; -} - -.tooltip.in { - opacity: 0.8; - filter: alpha(opacity=80); -} - -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} - -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} - -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} - -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} - -.tooltip-inner { - max-width: 200px; - padding: 8px; - color: #ffffff; - text-align: center; - text-decoration: none; - background-color: #000000; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top-color: #000000; - border-width: 5px 5px 0; -} - -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-right-color: #000000; - border-width: 5px 5px 5px 0; -} - -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-left-color: #000000; - border-width: 5px 0 5px 5px; -} - -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-bottom-color: #000000; - border-width: 0 5px 5px; -} - -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - max-width: 276px; - padding: 1px; - text-align: left; - white-space: normal; - background-color: #ffffff; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} - -.popover.top { - margin-top: -10px; -} - -.popover.right { - margin-left: 10px; -} - -.popover.bottom { - margin-top: 10px; -} - -.popover.left { - margin-left: -10px; -} - -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - font-weight: normal; - line-height: 18px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - -webkit-border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - border-radius: 5px 5px 0 0; -} - -.popover-title:empty { - display: none; -} - -.popover-content { - padding: 9px 14px; -} - -.popover .arrow, -.popover .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.popover .arrow { - border-width: 11px; -} - -.popover .arrow:after { - border-width: 10px; - content: ""; -} - -.popover.top .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, 0.25); - border-bottom-width: 0; -} - -.popover.top .arrow:after { - bottom: 1px; - margin-left: -10px; - border-top-color: #ffffff; - border-bottom-width: 0; -} - -.popover.right .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, 0.25); - border-left-width: 0; -} - -.popover.right .arrow:after { - bottom: -10px; - left: 1px; - border-right-color: #ffffff; - border-left-width: 0; -} - -.popover.bottom .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, 0.25); - border-top-width: 0; -} - -.popover.bottom .arrow:after { - top: 1px; - margin-left: -10px; - border-bottom-color: #ffffff; - border-top-width: 0; -} - -.popover.left .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, 0.25); - border-right-width: 0; -} - -.popover.left .arrow:after { - right: 1px; - bottom: -10px; - border-left-color: #ffffff; - border-right-width: 0; -} - -.thumbnails { - margin-left: -20px; - list-style: none; - *zoom: 1; -} - -.thumbnails:before, -.thumbnails:after { - display: table; - line-height: 0; - content: ""; -} - -.thumbnails:after { - clear: both; -} - -.row-fluid .thumbnails { - margin-left: 0; -} - -.thumbnails > li { - float: left; - margin-bottom: 20px; - margin-left: 20px; -} - -.thumbnail { - display: block; - padding: 4px; - line-height: 20px; - border: 1px solid #ddd; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} - -a.thumbnail:hover, -a.thumbnail:focus { - border-color: #0088cc; - -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); - box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); -} - -.thumbnail > img { - display: block; - max-width: 100%; - margin-right: auto; - margin-left: auto; -} - -.thumbnail .caption { - padding: 9px; - color: #555555; -} - -.media, -.media-body { - overflow: hidden; - *overflow: visible; - zoom: 1; -} - -.media, -.media .media { - margin-top: 15px; -} - -.media:first-child { - margin-top: 0; -} - -.media-object { - display: block; -} - -.media-heading { - margin: 0 0 5px; -} - -.media > .pull-left { - margin-right: 10px; -} - -.media > .pull-right { - margin-left: 10px; -} - -.media-list { - margin-left: 0; - list-style: none; -} - -.label, -.badge { - display: inline-block; - padding: 2px 4px; - font-size: 11.844px; - font-weight: bold; - line-height: 14px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - white-space: nowrap; - vertical-align: baseline; - background-color: #999999; -} - -.label { - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} - -.badge { - padding-right: 9px; - padding-left: 9px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; - border-radius: 9px; -} - -.label:empty, -.badge:empty { - display: none; -} - -a.label:hover, -a.label:focus, -a.badge:hover, -a.badge:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} - -.label-important, -.badge-important { - background-color: #b94a48; -} - -.label-important[href], -.badge-important[href] { - background-color: #953b39; -} - -.label-warning, -.badge-warning { - background-color: #f89406; -} - -.label-warning[href], -.badge-warning[href] { - background-color: #c67605; -} - -.label-success, -.badge-success { - background-color: #468847; -} - -.label-success[href], -.badge-success[href] { - background-color: #356635; -} - -.label-info, -.badge-info { - background-color: #3a87ad; -} - -.label-info[href], -.badge-info[href] { - background-color: #2d6987; -} - -.label-inverse, -.badge-inverse { - background-color: #333333; -} - -.label-inverse[href], -.badge-inverse[href] { - background-color: #1a1a1a; -} - -.btn .label, -.btn .badge { - position: relative; - top: -1px; -} - -.btn-mini .label, -.btn-mini .badge { - top: 0; -} - -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-moz-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-ms-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} - -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f7f7f7; - background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); - background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); - background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); - background-repeat: repeat-x; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -} - -.progress .bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - color: #ffffff; - text-align: center; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - background-color: #0e90d2; - background-image: -moz-linear-gradient(top, #149bdf, #0480be); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); - background-image: -webkit-linear-gradient(top, #149bdf, #0480be); - background-image: -o-linear-gradient(top, #149bdf, #0480be); - background-image: linear-gradient(to bottom, #149bdf, #0480be); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - -webkit-transition: width 0.6s ease; - -moz-transition: width 0.6s ease; - -o-transition: width 0.6s ease; - transition: width 0.6s ease; -} - -.progress .bar + .bar { - -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); -} - -.progress-striped .bar { - background-color: #149bdf; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - -moz-background-size: 40px 40px; - -o-background-size: 40px 40px; - background-size: 40px 40px; -} - -.progress.active .bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -ms-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} - -.progress-danger .bar, -.progress .bar-danger { - background-color: #dd514c; - background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); - background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); - background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); - background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); -} - -.progress-danger.progress-striped .bar, -.progress-striped .bar-danger { - background-color: #ee5f5b; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-success .bar, -.progress .bar-success { - background-color: #5eb95e; - background-image: -moz-linear-gradient(top, #62c462, #57a957); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); - background-image: -webkit-linear-gradient(top, #62c462, #57a957); - background-image: -o-linear-gradient(top, #62c462, #57a957); - background-image: linear-gradient(to bottom, #62c462, #57a957); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); -} - -.progress-success.progress-striped .bar, -.progress-striped .bar-success { - background-color: #62c462; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-info .bar, -.progress .bar-info { - background-color: #4bb1cf; - background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); - background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); - background-image: -o-linear-gradient(top, #5bc0de, #339bb9); - background-image: linear-gradient(to bottom, #5bc0de, #339bb9); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); -} - -.progress-info.progress-striped .bar, -.progress-striped .bar-info { - background-color: #5bc0de; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-warning .bar, -.progress .bar-warning { - background-color: #faa732; - background-image: -moz-linear-gradient(top, #fbb450, #f89406); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); - background-image: -webkit-linear-gradient(top, #fbb450, #f89406); - background-image: -o-linear-gradient(top, #fbb450, #f89406); - background-image: linear-gradient(to bottom, #fbb450, #f89406); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); -} - -.progress-warning.progress-striped .bar, -.progress-striped .bar-warning { - background-color: #fbb450; - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.accordion { - margin-bottom: 20px; -} - -.accordion-group { - margin-bottom: 2px; - border: 1px solid #e5e5e5; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} - -.accordion-heading { - border-bottom: 0; -} - -.accordion-heading .accordion-toggle { - display: block; - padding: 8px 15px; -} - -.accordion-toggle { - cursor: pointer; -} - -.accordion-inner { - padding: 9px 15px; - border-top: 1px solid #e5e5e5; -} - -.carousel { - position: relative; - margin-bottom: 20px; - line-height: 1; -} - -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} - -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: 0.6s ease-in-out left; - -moz-transition: 0.6s ease-in-out left; - -o-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} - -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - line-height: 1; -} - -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} - -.carousel-inner > .active { - left: 0; -} - -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} - -.carousel-inner > .next { - left: 100%; -} - -.carousel-inner > .prev { - left: -100%; -} - -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} - -.carousel-inner > .active.left { - left: -100%; -} - -.carousel-inner > .active.right { - left: 100%; -} - -.carousel-control { - position: absolute; - top: 40%; - left: 15px; - width: 40px; - height: 40px; - margin-top: -20px; - font-size: 60px; - font-weight: 100; - line-height: 30px; - color: #ffffff; - text-align: center; - background: #222222; - border: 3px solid #ffffff; - -webkit-border-radius: 23px; - -moz-border-radius: 23px; - border-radius: 23px; - opacity: 0.5; - filter: alpha(opacity=50); -} - -.carousel-control.right { - right: 15px; - left: auto; -} - -.carousel-control:hover, -.carousel-control:focus { - color: #ffffff; - text-decoration: none; - opacity: 0.9; - filter: alpha(opacity=90); -} - -.carousel-indicators { - position: absolute; - top: 15px; - right: 15px; - z-index: 5; - margin: 0; - list-style: none; -} - -.carousel-indicators li { - display: block; - float: left; - width: 10px; - height: 10px; - margin-left: 5px; - text-indent: -999px; - background-color: #ccc; - background-color: rgba(255, 255, 255, 0.25); - border-radius: 5px; -} - -.carousel-indicators .active { - background-color: #fff; -} - -.carousel-caption { - position: absolute; - right: 0; - bottom: 0; - left: 0; - padding: 15px; - background: #333333; - background: rgba(0, 0, 0, 0.75); -} - -.carousel-caption h4, -.carousel-caption p { - line-height: 20px; - color: #ffffff; -} - -.carousel-caption h4 { - margin: 0 0 5px; -} - -.carousel-caption p { - margin-bottom: 0; -} - -.hero-unit { - padding: 60px; - margin-bottom: 30px; - font-size: 18px; - font-weight: 200; - line-height: 30px; - color: inherit; - background-color: #eeeeee; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} - -.hero-unit h1 { - margin-bottom: 0; - font-size: 60px; - line-height: 1; - letter-spacing: -1px; - color: inherit; -} - -.hero-unit li { - line-height: 30px; -} - -.pull-right { - float: right; -} - -.pull-left { - float: left; -} - -.hide { - display: none; -} - -.show { - display: block; -} - -.invisible { - visibility: hidden; -} - -.affix { - position: fixed; -} diff --git a/wicket/README.md b/wicket/README.md new file mode 100644 index 0000000000..614446e7ba --- /dev/null +++ b/wicket/README.md @@ -0,0 +1,4 @@ + +From the same directory where pom.xml is, execute the following command to run the project: + +mvn jetty:run diff --git a/wicket/pom.xml b/wicket/pom.xml new file mode 100644 index 0000000000..929f723c2c --- /dev/null +++ b/wicket/pom.xml @@ -0,0 +1,106 @@ + + + + 4.0.0 + com.baeldung.wicket.examples + wicket-intro + war + 1.0-SNAPSHOT + WicketIntro + + 7.4.0 + 9.2.13.v20150730 + 2.5 + 4.12 + 3.5.1 + 2.6 + UTF-8 + + + + + org.apache.wicket + wicket-core + ${wicket.version} + + + + + junit + junit + ${junit.version} + test + + + + + org.eclipse.jetty.aggregate + jetty-all + ${jetty9.version} + test + + + + + + false + src/main/resources + + + false + src/main/java + + ** + + + **/*.java + + + + + + false + src/test/resources + + + false + src/test/java + + ** + + + **/*.java + + + + + + true + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + UTF-8 + true + true + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + false + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty9.version} + + + + diff --git a/wicket/src/main/java/com/baeldung/wicket/examples/Examples.html b/wicket/src/main/java/com/baeldung/wicket/examples/Examples.html new file mode 100644 index 0000000000..497e98e01a --- /dev/null +++ b/wicket/src/main/java/com/baeldung/wicket/examples/Examples.html @@ -0,0 +1,52 @@ + + + + +Wicket Intro Examples + + + +
      +
      +
      +

      Wicket Introduction Examples:

      + + Hello World! +
      +
      + Cafes +
      +
      +
      +
      + + diff --git a/wicket/src/main/java/com/baeldung/wicket/examples/Examples.java b/wicket/src/main/java/com/baeldung/wicket/examples/Examples.java new file mode 100644 index 0000000000..358e4f7b19 --- /dev/null +++ b/wicket/src/main/java/com/baeldung/wicket/examples/Examples.java @@ -0,0 +1,9 @@ +package com.baeldung.wicket.examples; + +import org.apache.wicket.markup.html.WebPage; + +public class Examples extends WebPage { + + private static final long serialVersionUID = 1L; + +} diff --git a/wicket/src/main/java/com/baeldung/wicket/examples/ExamplesApplication.java b/wicket/src/main/java/com/baeldung/wicket/examples/ExamplesApplication.java new file mode 100644 index 0000000000..711e8f01fd --- /dev/null +++ b/wicket/src/main/java/com/baeldung/wicket/examples/ExamplesApplication.java @@ -0,0 +1,27 @@ +package com.baeldung.wicket.examples; + +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.protocol.http.WebApplication; + +import com.baeldung.wicket.examples.cafeaddress.CafeAddress; +import com.baeldung.wicket.examples.helloworld.HelloWorld; + +public class ExamplesApplication extends WebApplication { + /** + * @see org.apache.wicket.Application#getHomePage() + */ + @Override + public Class getHomePage() { + return Examples.class; + } + + /** + * @see org.apache.wicket.Application#init() + */ + @Override + public void init() { + super.init(); + mountPage("/examples/helloworld", HelloWorld.class); + mountPage("/examples/cafes", CafeAddress.class); + } +} diff --git a/wicket/src/main/java/com/baeldung/wicket/examples/cafeaddress/CafeAddress.html b/wicket/src/main/java/com/baeldung/wicket/examples/cafeaddress/CafeAddress.html new file mode 100644 index 0000000000..c5ada2323d --- /dev/null +++ b/wicket/src/main/java/com/baeldung/wicket/examples/cafeaddress/CafeAddress.html @@ -0,0 +1,15 @@ + + + + +Cafes + + +
      + +

      + Address: address +

      +
      + + diff --git a/wicket/src/main/java/com/baeldung/wicket/examples/cafeaddress/CafeAddress.java b/wicket/src/main/java/com/baeldung/wicket/examples/cafeaddress/CafeAddress.java new file mode 100644 index 0000000000..ce26c5a1ad --- /dev/null +++ b/wicket/src/main/java/com/baeldung/wicket/examples/cafeaddress/CafeAddress.java @@ -0,0 +1,72 @@ +package com.baeldung.wicket.examples.cafeaddress; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.DropDownChoice; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.request.mapper.parameter.PageParameters; + +public class CafeAddress extends WebPage { + + private static final long serialVersionUID = 1L; + + String selectedCafe; + Address address; + Map cafeNamesAndAddresses = new HashMap<>(); + + public CafeAddress(final PageParameters parameters) { + super(parameters); + initCafes(); + + ArrayList cafeNames = new ArrayList<>(this.cafeNamesAndAddresses.keySet()); + this.selectedCafe = cafeNames.get(0); + this.address = new Address(this.cafeNamesAndAddresses.get(this.selectedCafe).getAddress()); + + final Label addressLabel = new Label("address", new PropertyModel(this.address, "address")); + addressLabel.setOutputMarkupId(true); + + final DropDownChoice cafeDropdown = new DropDownChoice<>("cafes", new PropertyModel(this, "selectedCafe"), cafeNames); + cafeDropdown.add(new AjaxFormComponentUpdatingBehavior("onchange") { + private static final long serialVersionUID = 1L; + + @Override + protected void onUpdate(AjaxRequestTarget target) { + String name = (String) cafeDropdown.getDefaultModel().getObject(); + address.setAddress(cafeNamesAndAddresses.get(name).getAddress()); + target.add(addressLabel); + } + }); + + add(addressLabel); + add(cafeDropdown); + + } + + private void initCafes() { + this.cafeNamesAndAddresses.put("Linda's Cafe", new Address("35 Bower St.")); + this.cafeNamesAndAddresses.put("Old Tree", new Address("2 Edgware Rd.")); + } + + class Address implements Serializable { + private String sAddress = ""; + + public Address(String address) { + this.sAddress = address; + } + + public String getAddress() { + return this.sAddress; + } + + public void setAddress(String address) { + this.sAddress = address; + } + } +} diff --git a/wicket/src/main/java/com/baeldung/wicket/examples/helloworld/HelloWorld.html b/wicket/src/main/java/com/baeldung/wicket/examples/helloworld/HelloWorld.html new file mode 100644 index 0000000000..c56d07fc10 --- /dev/null +++ b/wicket/src/main/java/com/baeldung/wicket/examples/helloworld/HelloWorld.html @@ -0,0 +1,5 @@ + + + + + diff --git a/wicket/src/main/java/com/baeldung/wicket/examples/helloworld/HelloWorld.java b/wicket/src/main/java/com/baeldung/wicket/examples/helloworld/HelloWorld.java new file mode 100644 index 0000000000..f819e05be6 --- /dev/null +++ b/wicket/src/main/java/com/baeldung/wicket/examples/helloworld/HelloWorld.java @@ -0,0 +1,13 @@ +package com.baeldung.wicket.examples.helloworld; + +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; + +public class HelloWorld extends WebPage { + + private static final long serialVersionUID = 1L; + + public HelloWorld() { + add(new Label("hello", "Hello World!")); + } +} diff --git a/wicket/src/main/test/java/com/baeldung/wicket/examples/TestHomePage.java b/wicket/src/main/test/java/com/baeldung/wicket/examples/TestHomePage.java new file mode 100644 index 0000000000..a393f1d178 --- /dev/null +++ b/wicket/src/main/test/java/com/baeldung/wicket/examples/TestHomePage.java @@ -0,0 +1,23 @@ +package com.baeldung.wicket.examples; + +import org.apache.wicket.util.tester.WicketTester; +import org.junit.Before; +import org.junit.Test; + +public class TestHomePage { + private WicketTester tester; + + @Before + public void setUp() { + tester = new WicketTester(new ExamplesApplication()); + } + + @Test + public void whenPageInvoked_thanRenderedOK() { + //start and render the test page + tester.startPage(Examples.class); + + //assert rendered page class + tester.assertRenderedPage(Examples.class); + } +} diff --git a/wicket/src/main/webapp/WEB-INF/web.xml b/wicket/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..8a4451c80e --- /dev/null +++ b/wicket/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,32 @@ + + + + CafeAddress + + + + + wicket.examples + org.apache.wicket.protocol.http.WicketFilter + + applicationClassName + com.baeldung.wicket.examples.ExamplesApplication + + + + + wicket.examples + /* + + \ No newline at end of file diff --git a/xml/pom.xml b/xml/pom.xml new file mode 100644 index 0000000000..d204eea45f --- /dev/null +++ b/xml/pom.xml @@ -0,0 +1,111 @@ + + 4.0.0 + com.baeldung + xml + 0.1-SNAPSHOT + + xml + + + + + dom4j + dom4j + 1.6.1 + + + jaxen + jaxen + 1.1.6 + + + + + org.jdom + jdom2 + 2.0.6 + + + + + commons-io + commons-io + 2.4 + + + + org.apache.commons + commons-collections4 + 4.0 + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + + + junit + junit + ${junit.version} + test + + + + + + xml + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + + + + + + + + 19.0 + 3.4 + + + 4.12 + + + 3.5.1 + 2.6 + 2.19.1 + 2.7 + 1.4.18 + + + + + diff --git a/xml/src/main/java/com/baeldung/xml/DefaultParser.java b/xml/src/main/java/com/baeldung/xml/DefaultParser.java new file mode 100644 index 0000000000..1f2a7418fb --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/DefaultParser.java @@ -0,0 +1,193 @@ +package com.baeldung.xml; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Iterator; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +public class DefaultParser { + + private File file; + + public DefaultParser(File file) { + this.file = file; + } + + public NodeList getFirstLevelNodeList() { + NodeList nodeList = null; + try { + FileInputStream fileIS = new FileInputStream(this.getFile()); + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + + Document xmlDocument = builder.parse(fileIS); + + XPath xPath = XPathFactory.newInstance().newXPath(); + + String expression = "/tutorials/tutorial"; + + nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET); + + } catch (SAXException | IOException | ParserConfigurationException | XPathExpressionException e) { + e.printStackTrace(); + } + return nodeList; + } + + public Node getNodeById(String id) { + Node node = null; + try { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + + Document xmlDocument = builder.parse(this.getFile()); + + XPath xPath = XPathFactory.newInstance().newXPath(); + + String expression = "/tutorials/tutorial[@tutId=" + "'" + id + "'" + "]"; + + node = (Node) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODE); + + } catch (SAXException | IOException | ParserConfigurationException | XPathExpressionException e) { + e.printStackTrace(); + } + return node; + } + + public NodeList getNodeListByTitle(String name) { + NodeList nodeList = null; + try { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + + Document xmlDocument = builder.parse(this.getFile()); + + this.clean(xmlDocument); + + XPath xPath = XPathFactory.newInstance().newXPath(); + + String expression = "//tutorial[descendant::title[text()=" + "'" + name + "'" + "]]"; + + nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET); + + } catch (SAXException | IOException | ParserConfigurationException | XPathExpressionException e) { + e.printStackTrace(); + } + return nodeList; + } + + public NodeList getElementsByDate(String date) { + NodeList nodeList = null; + + try { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + + Document xmlDocument = builder.parse(this.getFile()); + + this.clean(xmlDocument); + + XPath xPath = XPathFactory.newInstance().newXPath(); + + String expression = "//tutorial[number(translate(date, '/', '')) > " + date + "]"; + + nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET); + + } catch (SAXException | IOException | ParserConfigurationException | XPathExpressionException e) { + e.printStackTrace(); + } + return nodeList; + } + + public NodeList getAllTutorials() { + NodeList nodeList = null; + try { + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + builderFactory.setNamespaceAware(true); + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + + Document xmlDocument = builder.parse(this.getFile()); + + this.clean(xmlDocument); + + XPath xPath = XPathFactory.newInstance().newXPath(); + + xPath.setNamespaceContext(new NamespaceContext() { + + @Override + public Iterator getPrefixes(String arg0) { + return null; + } + + @Override + public String getPrefix(String arg0) { + return null; + } + + @Override + public String getNamespaceURI(String arg0) { + if ("bdn".equals(arg0)) { + return "http://www.baeldung.com/full_archive"; + } + return null; + } + }); + + String expression = "/bdn:tutorials/bdn:tutorial"; + + nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET); + + } catch (SAXException | IOException | ParserConfigurationException | XPathExpressionException e) { + e.printStackTrace(); + } + return nodeList; + } + + private void clean(Node node) { + + NodeList childs = node.getChildNodes(); + + for (int n = childs.getLength() - 1; n >= 0; n--) { + Node child = childs.item(n); + short nodeType = child.getNodeType(); + + if (nodeType == Node.ELEMENT_NODE) + clean(child); + else if (nodeType == Node.TEXT_NODE) { + String trimmedNodeVal = child.getNodeValue().trim(); + if (trimmedNodeVal.length() == 0) + node.removeChild(child); + else + child.setNodeValue(trimmedNodeVal); + } else if (nodeType == Node.COMMENT_NODE) + node.removeChild(child); + } + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + +} diff --git a/xml/src/main/java/com/baeldung/xml/Dom4JParser.java b/xml/src/main/java/com/baeldung/xml/Dom4JParser.java new file mode 100644 index 0000000000..d9058ba236 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/Dom4JParser.java @@ -0,0 +1,131 @@ +package com.baeldung.xml; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Iterator; +import java.util.List; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.Node; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.SAXReader; +import org.dom4j.io.XMLWriter; + +public class Dom4JParser { + + private File file; + + public Dom4JParser(File file) { + this.file = file; + } + + public Element getRootElement() { + try { + SAXReader reader = new SAXReader(); + Document document = reader.read(file); + return document.getRootElement(); + } catch (DocumentException e) { + e.printStackTrace(); + return null; + } + } + + public List getFirstElementList() { + try { + SAXReader reader = new SAXReader(); + Document document = reader.read(file); + return document.getRootElement().elements(); + } catch (DocumentException e) { + e.printStackTrace(); + return null; + } + } + + public Node getNodeById(String id) { + try { + SAXReader reader = new SAXReader(); + Document document = reader.read(file); + List elements = document.selectNodes("//*[@tutId='" + id + "']"); + return elements.get(0); + } catch (DocumentException e) { + e.printStackTrace(); + return null; + } + } + + public Node getElementsListByTitle(String name) { + try { + SAXReader reader = new SAXReader(); + Document document = reader.read(file); + List elements = document + .selectNodes("//tutorial[descendant::title[text()=" + "'" + name + "'" + "]]"); + return elements.get(0); + } catch (DocumentException e) { + e.printStackTrace(); + return null; + } + } + + public void generateModifiedDocument() { + try { + SAXReader reader = new SAXReader(); + Document document = reader.read(file); + List nodes = document.selectNodes("/tutorials/tutorial"); + for (Node node : nodes) { + Element element = (Element) node; + Iterator iterator = element.elementIterator("title"); + while (iterator.hasNext()) { + Element title = (Element) iterator.next(); + title.setText(title.getText() + " updated"); + } + } + XMLWriter writer = new XMLWriter(new FileWriter(new File("src/test/resources/example_updated.xml"))); + writer.write(document); + writer.close(); + } catch (DocumentException e) { + e.printStackTrace(); + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public void generateNewDocument() { + try { + Document document = DocumentHelper.createDocument(); + Element root = document.addElement("XMLTutorials"); + Element tutorialElement = root.addElement("tutorial").addAttribute("tutId", "01"); + tutorialElement.addAttribute("type", "xml"); + + tutorialElement.addElement("title").addText("XML with Dom4J"); + + tutorialElement.addElement("description").addText("XML handling with Dom4J"); + + tutorialElement.addElement("date").addText("14/06/2016"); + + tutorialElement.addElement("author").addText("Dom4J tech writer"); + + OutputFormat format = OutputFormat.createPrettyPrint(); + XMLWriter writer = new XMLWriter(new FileWriter(new File("src/test/resources/example_new.xml")), format); + writer.write(document); + writer.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + +} diff --git a/xml/src/main/java/com/baeldung/xml/JDomParser.java b/xml/src/main/java/com/baeldung/xml/JDomParser.java new file mode 100644 index 0000000000..08676b44f8 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/JDomParser.java @@ -0,0 +1,62 @@ +package com.baeldung.xml; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.JDOMException; +import org.jdom2.filter.Filters; +import org.jdom2.input.SAXBuilder; +import org.jdom2.xpath.XPathExpression; +import org.jdom2.xpath.XPathFactory; + + +public class JDomParser { + + private File file; + + public JDomParser(File file) { + this.file = file; + } + + public List getAllTitles() { + try { + SAXBuilder builder = new SAXBuilder(); + Document doc = builder.build(this.getFile()); + Element tutorials = doc.getRootElement(); + List titles = tutorials.getChildren("tutorial"); + return titles; + } catch (JDOMException | IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } + + public Element getNodeById(String id) { + try { + SAXBuilder builder = new SAXBuilder(); + Document document = (Document) builder.build(file); + String filter = "//*[@tutId='" + id + "']"; + XPathFactory xFactory = XPathFactory.instance(); + XPathExpression expr = xFactory.compile(filter, Filters.element()); + List node = expr.evaluate(document); + + return node.get(0); + } catch (JDOMException | IOException e ) { + e.printStackTrace(); + return null; + } + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + +} diff --git a/xml/src/main/java/com/baeldung/xml/JaxbParser.java b/xml/src/main/java/com/baeldung/xml/JaxbParser.java new file mode 100644 index 0000000000..758ebb969c --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/JaxbParser.java @@ -0,0 +1,68 @@ +package com.baeldung.xml; + +import java.io.File; +import java.util.ArrayList; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + +import com.baeldung.xml.binding.Tutorial; +import com.baeldung.xml.binding.Tutorials; + +public class JaxbParser { + + private File file; + + public JaxbParser(File file) { + this.file = file; + } + + public Tutorials getFullDocument() { + try { + JAXBContext jaxbContext = JAXBContext.newInstance(Tutorials.class); + Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); + Tutorials tutorials = (Tutorials) jaxbUnmarshaller.unmarshal(this.getFile()); + return tutorials; + } catch (JAXBException e) { + e.printStackTrace(); + return null; + } + } + + public void createNewDocument() { + Tutorials tutorials = new Tutorials(); + tutorials.setTutorial(new ArrayList()); + Tutorial tut = new Tutorial(); + tut.setTutId("01"); + tut.setType("XML"); + tut.setTitle("XML with Jaxb"); + tut.setDescription("XML Binding with Jaxb"); + tut.setDate("04/02/2015"); + tut.setAuthor("Jaxb author"); + tutorials.getTutorial().add(tut); + + try { + JAXBContext jaxbContext = JAXBContext.newInstance(Tutorials.class); + Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); + + jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + + jaxbMarshaller.marshal(tutorials, file); + + } catch (JAXBException e) { + e.printStackTrace(); + } + + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + +} diff --git a/xml/src/main/java/com/baeldung/xml/JaxenDemo.java b/xml/src/main/java/com/baeldung/xml/JaxenDemo.java new file mode 100644 index 0000000000..0c2dca0573 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/JaxenDemo.java @@ -0,0 +1,57 @@ +package com.baeldung.xml; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.jaxen.JaxenException; +import org.jaxen.XPath; +import org.jaxen.dom.DOMXPath; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +public class JaxenDemo { + + private File file; + + public JaxenDemo(File file) { + this.file = file; + } + + public List getAllTutorial(){ + try { + FileInputStream fileIS = new FileInputStream(this.getFile()); + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + + DocumentBuilder builder = builderFactory.newDocumentBuilder(); + + Document xmlDocument = builder.parse(fileIS); + + String expression = "/tutorials/tutorial"; + + XPath path = new DOMXPath(expression); + List result = path.selectNodes(xmlDocument); + return result; + + } catch (SAXException | IOException | ParserConfigurationException | JaxenException e) { + e.printStackTrace(); + return null; + } + + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + + +} diff --git a/xml/src/main/java/com/baeldung/xml/StaxParser.java b/xml/src/main/java/com/baeldung/xml/StaxParser.java new file mode 100644 index 0000000000..e14d872831 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/StaxParser.java @@ -0,0 +1,120 @@ +package com.baeldung.xml; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import com.baeldung.xml.binding.Tutorial; + +public class StaxParser { + + private File file; + + public StaxParser(File file) { + this.file = file; + } + + public List getAllTutorial() { + boolean bTitle = false; + boolean bDescription = false; + boolean bDate = false; + boolean bAuthor = false; + List tutorials = new ArrayList(); + try { + XMLInputFactory factory = XMLInputFactory.newInstance(); + XMLEventReader eventReader = factory.createXMLEventReader(new FileReader(this.getFile())); + Tutorial current = null; + while (eventReader.hasNext()) { + XMLEvent event = eventReader.nextEvent(); + switch (event.getEventType()) { + case XMLStreamConstants.START_ELEMENT: + StartElement startElement = event.asStartElement(); + String qName = startElement.getName().getLocalPart(); + if (qName.equalsIgnoreCase("tutorial")) { + current = new Tutorial(); + Iterator attributes = startElement.getAttributes(); + while (attributes.hasNext()) { + Attribute currentAt = attributes.next(); + if (currentAt.getName().toString().equalsIgnoreCase("tutId")) { + current.setTutId(currentAt.getValue()); + } else if (currentAt.getName().toString().equalsIgnoreCase("type")) { + current.setType(currentAt.getValue()); + } + } + } else if (qName.equalsIgnoreCase("title")) { + bTitle = true; + } else if (qName.equalsIgnoreCase("description")) { + bDescription = true; + } else if (qName.equalsIgnoreCase("date")) { + bDate = true; + } else if (qName.equalsIgnoreCase("author")) { + bAuthor = true; + } + break; + case XMLStreamConstants.CHARACTERS: + Characters characters = event.asCharacters(); + if (bTitle) { + if (current != null) { + current.setTitle(characters.getData()); + } + bTitle = false; + } + if (bDescription) { + if (current != null) { + current.setDescription(characters.getData()); + } + bDescription = false; + } + if (bDate) { + if (current != null) { + current.setDate(characters.getData()); + } + bDate = false; + } + if (bAuthor) { + if (current != null) { + current.setAuthor(characters.getData()); + } + bAuthor = false; + } + break; + case XMLStreamConstants.END_ELEMENT: + EndElement endElement = event.asEndElement(); + if (endElement.getName().getLocalPart().equalsIgnoreCase("tutorial")) { + if(current != null){ + tutorials.add(current); + } + } + break; + } + } + + } catch (FileNotFoundException | XMLStreamException e) { + e.printStackTrace(); + } + + return tutorials; + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + +} diff --git a/xml/src/main/java/com/baeldung/xml/binding/Tutorial.java b/xml/src/main/java/com/baeldung/xml/binding/Tutorial.java new file mode 100644 index 0000000000..7201d499d0 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/binding/Tutorial.java @@ -0,0 +1,59 @@ +package com.baeldung.xml.binding; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; + +public class Tutorial { + + private String tutId; + private String type; + private String title; + private String description; + private String date; + private String author; + + + public String getTutId() { + return tutId; + } + + @XmlAttribute + public void setTutId(String tutId) { + this.tutId = tutId; + } + public String getType() { + return type; + } + @XmlAttribute + public void setType(String type) { + this.type = type; + } + public String getTitle() { + return title; + } + @XmlElement + public void setTitle(String title) { + this.title = title; + } + public String getDescription() { + return description; + } + @XmlElement + public void setDescription(String description) { + this.description = description; + } + public String getDate() { + return date; + } + @XmlElement + public void setDate(String date) { + this.date = date; + } + public String getAuthor() { + return author; + } + @XmlElement + public void setAuthor(String author) { + this.author = author; + } +} diff --git a/xml/src/main/java/com/baeldung/xml/binding/Tutorials.java b/xml/src/main/java/com/baeldung/xml/binding/Tutorials.java new file mode 100644 index 0000000000..ab6669c0ad --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/binding/Tutorials.java @@ -0,0 +1,23 @@ +package com.baeldung.xml.binding; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class Tutorials { + + private List tutorial; + + public List getTutorial() { + return tutorial; + } + + @XmlElement + public void setTutorial(List tutorial) { + this.tutorial = tutorial; + } + + +} diff --git a/xml/src/test/java/com/baeldung/xml/DefaultParserTest.java b/xml/src/test/java/com/baeldung/xml/DefaultParserTest.java new file mode 100644 index 0000000000..734e7a93cb --- /dev/null +++ b/xml/src/test/java/com/baeldung/xml/DefaultParserTest.java @@ -0,0 +1,80 @@ +package com.baeldung.xml; + +import static org.junit.Assert.*; + +import java.io.File; + +import org.junit.Test; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class DefaultParserTest { + + final String fileName = "src/test/resources/example.xml"; + + final String fileNameSpace = "src/test/resources/example_namespace.xml"; + + DefaultParser parser; + + @Test + public void getFirstLevelNodeListTest() { + parser = new DefaultParser(new File(fileName)); + NodeList list = parser.getFirstLevelNodeList(); + + assertNotNull(list); + assertTrue(list.getLength() == 4); + } + + @Test + public void getNodeListByTitleTest() { + parser = new DefaultParser(new File(fileName)); + NodeList list = parser.getNodeListByTitle("XML"); + + for (int i = 0; null != list && i < list.getLength(); i++) { + Node nod = list.item(i); + assertEquals("java", nod.getAttributes().getNamedItem("type").getTextContent()); + assertEquals("02", nod.getAttributes().getNamedItem("tutId").getTextContent()); + assertEquals("XML", nod.getFirstChild().getTextContent()); + assertEquals("title", nod.getFirstChild().getNodeName()); + assertEquals("description", nod.getChildNodes().item(1).getNodeName()); + assertEquals("Introduction to XPath", nod.getChildNodes().item(1).getTextContent()); + assertEquals("author", nod.getLastChild().getNodeName()); + assertEquals("XMLAuthor", nod.getLastChild().getTextContent()); + } + } + + @Test + public void getNodeByIdTest() { + parser = new DefaultParser(new File(fileName)); + Node node = parser.getNodeById("03"); + + String type = node.getAttributes().getNamedItem("type").getNodeValue(); + assertEquals("android", type); + } + + @Test + public void getNodeListByDateTest(){ + parser = new DefaultParser(new File(fileName)); + NodeList list = parser.getNodeListByTitle("04022016"); + for (int i = 0; null != list && i < list.getLength(); i++) { + Node nod = list.item(i); + assertEquals("java", nod.getAttributes().getNamedItem("type").getTextContent()); + assertEquals("04", nod.getAttributes().getNamedItem("tutId").getTextContent()); + assertEquals("Spring", nod.getFirstChild().getTextContent()); + assertEquals("title", nod.getFirstChild().getNodeName()); + assertEquals("description", nod.getChildNodes().item(1).getNodeName()); + assertEquals("Introduction to Spring", nod.getChildNodes().item(1).getTextContent()); + assertEquals("author", nod.getLastChild().getNodeName()); + assertEquals("SpringAuthor", nod.getLastChild().getTextContent()); + } + } + + @Test + public void getNodeListWithNamespaceTest(){ + parser = new DefaultParser(new File(fileNameSpace)); + NodeList list = parser.getAllTutorials(); + assertNotNull(list); + assertTrue(list.getLength() == 4); + } + +} diff --git a/xml/src/test/java/com/baeldung/xml/Dom4JParserTest.java b/xml/src/test/java/com/baeldung/xml/Dom4JParserTest.java new file mode 100644 index 0000000000..277eca8355 --- /dev/null +++ b/xml/src/test/java/com/baeldung/xml/Dom4JParserTest.java @@ -0,0 +1,88 @@ +package com.baeldung.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.List; + +import org.dom4j.Element; +import org.dom4j.Node; +import org.junit.Test; + +public class Dom4JParserTest { + + final String fileName = "src/test/resources/example.xml"; + + Dom4JParser parser; + + @Test + public void getRootElementTest() { + parser = new Dom4JParser(new File(fileName)); + Element root = parser.getRootElement(); + + assertNotNull(root); + assertTrue(root.elements().size() == 4); + } + + @Test + public void getFirstElementListTest() { + parser = new Dom4JParser(new File(fileName)); + List firstList = parser.getFirstElementList(); + + assertNotNull(firstList); + assertTrue(firstList.size() == 4); + assertTrue(firstList.get(0).attributeValue("type").equals("java")); + } + + @Test + public void getElementByIdTest() { + parser = new Dom4JParser(new File(fileName)); + Node element = parser.getNodeById("03"); + + String type = element.valueOf("@type"); + assertEquals("android", type); + } + + @Test + public void getElementsListByTitleTest() { + parser = new Dom4JParser(new File(fileName)); + Node element = parser.getElementsListByTitle("XML"); + + assertEquals("java", element.valueOf("@type")); + assertEquals("02", element.valueOf("@tutId")); + assertEquals("XML", element.selectSingleNode("title").getText()); + assertEquals("title", element.selectSingleNode("title").getName()); + } + + @Test + public void generateModifiedDocumentTest() { + parser = new Dom4JParser(new File(fileName)); + parser.generateModifiedDocument(); + + File generatedFile = new File("src/test/resources/example_updated.xml"); + assertTrue(generatedFile.exists()); + + parser.setFile(generatedFile); + Node element = parser.getNodeById("02"); + + assertEquals("XML updated", element.selectSingleNode("title").getText()); + + } + + @Test + public void generateNewDocumentTest() { + parser = new Dom4JParser(new File(fileName)); + parser.generateNewDocument(); + + File newFile = new File("src/test/resources/example_new.xml"); + assertTrue(newFile.exists()); + + parser.setFile(newFile); + Node element = parser.getNodeById("01"); + + assertEquals("XML with Dom4J", element.selectSingleNode("title").getText()); + + } +} diff --git a/xml/src/test/java/com/baeldung/xml/JDomParserTest.java b/xml/src/test/java/com/baeldung/xml/JDomParserTest.java new file mode 100644 index 0000000000..981458469f --- /dev/null +++ b/xml/src/test/java/com/baeldung/xml/JDomParserTest.java @@ -0,0 +1,38 @@ +package com.baeldung.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.List; + +import org.jdom2.Element; +import org.junit.Test; + +public class JDomParserTest { + + final String fileName = "src/test/resources/example.xml"; + + JDomParser parser; + + @Test + public void getFirstElementListTest() { + parser = new JDomParser(new File(fileName)); + List firstList = parser.getAllTitles(); + + assertNotNull(firstList); + assertTrue(firstList.size() == 4); + assertTrue(firstList.get(0).getAttributeValue("type").equals("java")); + } + + @Test + public void getElementByIdTest() { + parser = new JDomParser(new File(fileName)); + Element el = parser.getNodeById("03"); + + String type = el.getAttributeValue("type"); + assertEquals("android", type); + } + +} diff --git a/xml/src/test/java/com/baeldung/xml/JaxbParserTest.java b/xml/src/test/java/com/baeldung/xml/JaxbParserTest.java new file mode 100644 index 0000000000..6c31a7bfdd --- /dev/null +++ b/xml/src/test/java/com/baeldung/xml/JaxbParserTest.java @@ -0,0 +1,44 @@ +package com.baeldung.xml; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.junit.Test; + +import com.baeldung.xml.binding.Tutorials; + +public class JaxbParserTest { + + + final String fileName = "src/test/resources/example.xml"; + + JaxbParser parser; + + @Test + public void getFullDocumentTest(){ + parser = new JaxbParser(new File(fileName)); + Tutorials tutorials = parser.getFullDocument(); + + assertNotNull(tutorials); + assertTrue(tutorials.getTutorial().size() == 4); + assertTrue(tutorials.getTutorial().get(0).getType().equalsIgnoreCase("java")); + } + + @Test + public void createNewDocumentTest(){ + File newFile = new File("src/test/resources/example_new.xml"); + parser = new JaxbParser(newFile); + parser.createNewDocument(); + + + assertTrue(newFile.exists()); + + Tutorials tutorials = parser.getFullDocument(); + + assertNotNull(tutorials); + assertTrue(tutorials.getTutorial().size() == 1); + assertTrue(tutorials.getTutorial().get(0).getTitle().equalsIgnoreCase("XML with Jaxb")); + } +} diff --git a/xml/src/test/java/com/baeldung/xml/JaxenDemoTest.java b/xml/src/test/java/com/baeldung/xml/JaxenDemoTest.java new file mode 100644 index 0000000000..2521fcaf8a --- /dev/null +++ b/xml/src/test/java/com/baeldung/xml/JaxenDemoTest.java @@ -0,0 +1,25 @@ +package com.baeldung.xml; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.List; + +import org.junit.Test; + +public class JaxenDemoTest { + + final String fileName = "src/test/resources/example.xml"; + + JaxenDemo jaxenDemo; + + @Test + public void getFirstLevelNodeListTest() { + jaxenDemo = new JaxenDemo(new File(fileName)); + List list = jaxenDemo.getAllTutorial(); + + assertNotNull(list); + assertTrue(list.size() == 4); + } +} diff --git a/xml/src/test/java/com/baeldung/xml/StaxParserTest.java b/xml/src/test/java/com/baeldung/xml/StaxParserTest.java new file mode 100644 index 0000000000..cf7ee1ee75 --- /dev/null +++ b/xml/src/test/java/com/baeldung/xml/StaxParserTest.java @@ -0,0 +1,28 @@ +package com.baeldung.xml; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.List; + +import org.junit.Test; + +import com.baeldung.xml.binding.Tutorial; + +public class StaxParserTest { + + final String fileName = "src/test/resources/example.xml"; + + StaxParser parser; + + @Test + public void getAllTutorialsTest(){ + parser = new StaxParser(new File(fileName)); + List tutorials = parser.getAllTutorial(); + + assertNotNull(tutorials); + assertTrue(tutorials.size() == 4); + assertTrue(tutorials.get(0).getType().equalsIgnoreCase("java")); + } +} diff --git a/xml/src/test/resources/example.xml b/xml/src/test/resources/example.xml new file mode 100644 index 0000000000..0993b6240a --- /dev/null +++ b/xml/src/test/resources/example.xml @@ -0,0 +1,32 @@ + + + + Guava + Introduction to Guava + 04/04/2016 + GuavaAuthor + + + XML + Introduction to XPath + 04/05/2016 + XMLAuthor + + + Android + Introduction to Android + 04/03/2016 + AndroidAuthor + + + Spring + Introduction to Spring + 04/02/2016 + SpringAuthor + +
      Spring Core
      +
      Spring MVC
      +
      Spring Batch
      +
      +
      +
      \ No newline at end of file diff --git a/xml/src/test/resources/example_namespace.xml b/xml/src/test/resources/example_namespace.xml new file mode 100644 index 0000000000..f1a880951a --- /dev/null +++ b/xml/src/test/resources/example_namespace.xml @@ -0,0 +1,32 @@ + + + + Guava + Introduction to Guava + 04/04/2016 + GuavaAuthor + + + XML + Introduction to XPath + 04/05/2016 + XMLAuthor + + + Android + Introduction to Android + 04/03/2016 + AndroidAuthor + + + Spring + Introduction to Spring + 04/02/2016 + SpringAuthor + +
      Spring Core
      +
      Spring MVC
      +
      Spring Batch
      +
      +
      +
      \ No newline at end of file diff --git a/xml/src/test/resources/example_new.xml b/xml/src/test/resources/example_new.xml new file mode 100644 index 0000000000..646d938869 --- /dev/null +++ b/xml/src/test/resources/example_new.xml @@ -0,0 +1,9 @@ + + + + Jaxb author + 04/02/2015 + XML Binding with Jaxb + XML with Jaxb + + diff --git a/xml/src/test/resources/example_updated.xml b/xml/src/test/resources/example_updated.xml new file mode 100644 index 0000000000..962ca0c889 --- /dev/null +++ b/xml/src/test/resources/example_updated.xml @@ -0,0 +1,32 @@ + + + + Guava updated + Introduction to Guava + 04/04/2016 + GuavaAuthor + + + XML updated + Introduction to XPath + 04/05/2016 + XMLAuthor + + + Android updated + Introduction to Android + 04/03/2016 + AndroidAuthor + + + Spring updated + Introduction to Spring + 04/02/2016 + SpringAuthor + +
      Spring Core
      +
      Spring MVC
      +
      Spring Batch
      +
      +
      +
      \ No newline at end of file diff --git a/xmlunit2-tutorial/README.md b/xmlunit2-tutorial/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xmlunit2-tutorial/pom.xml b/xmlunit2-tutorial/pom.xml new file mode 100644 index 0000000000..b4cb684f65 --- /dev/null +++ b/xmlunit2-tutorial/pom.xml @@ -0,0 +1,46 @@ + + 4.0.0 + com.baeldung + xmlunit2-tutorial + 1.0 + XMLUnit-2 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 7 + 7 + + + + + + + junit + junit + 4.3 + test + + + org.hamcrest + hamcrest-all + 1.3 + + + org.xmlunit + xmlunit-matchers + 2.2.1 + + + + org.xmlunit + xmlunit-core + 2.2.1 + + + + diff --git a/xmlunit2-tutorial/src/main/java/com/baeldung/xmlunit/IgnoreAttributeDifferenceEvaluator.java b/xmlunit2-tutorial/src/main/java/com/baeldung/xmlunit/IgnoreAttributeDifferenceEvaluator.java new file mode 100644 index 0000000000..2f644e0114 --- /dev/null +++ b/xmlunit2-tutorial/src/main/java/com/baeldung/xmlunit/IgnoreAttributeDifferenceEvaluator.java @@ -0,0 +1,31 @@ +package com.baeldung.xmlunit; + +import org.w3c.dom.Attr; +import org.w3c.dom.Node; +import org.xmlunit.diff.Comparison; +import org.xmlunit.diff.ComparisonResult; +import org.xmlunit.diff.DifferenceEvaluator; + +public class IgnoreAttributeDifferenceEvaluator implements DifferenceEvaluator { + + private String attributeName; + + public IgnoreAttributeDifferenceEvaluator(String attributeName) { + this.attributeName = attributeName; + } + + @Override + public ComparisonResult evaluate(Comparison comparison, + ComparisonResult outcome) { + if (outcome == ComparisonResult.EQUAL) + return outcome; + final Node controlNode = comparison.getControlDetails().getTarget(); + if (controlNode instanceof Attr) { + Attr attr = (Attr) controlNode; + if (attr.getName().equals(attributeName)) { + return ComparisonResult.SIMILAR; + } + } + return outcome; + } +} diff --git a/xmlunit2-tutorial/src/test/java/com/baeldung/xmlunit/XMLUnitTest.java b/xmlunit2-tutorial/src/test/java/com/baeldung/xmlunit/XMLUnitTest.java new file mode 100644 index 0000000000..175250f47b --- /dev/null +++ b/xmlunit2-tutorial/src/test/java/com/baeldung/xmlunit/XMLUnitTest.java @@ -0,0 +1,302 @@ +package com.baeldung.xmlunit; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.xmlunit.matchers.CompareMatcher.isIdenticalTo; +import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; +import static org.xmlunit.matchers.HasXPathMatcher.hasXPath; + +import java.io.File; +import java.util.Iterator; + +import org.junit.Ignore; +import org.junit.Test; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.xmlunit.builder.DiffBuilder; +import org.xmlunit.builder.Input; +import org.xmlunit.diff.ComparisonControllers; +import org.xmlunit.diff.DefaultNodeMatcher; +import org.xmlunit.diff.Diff; +import org.xmlunit.diff.Difference; +import org.xmlunit.diff.ElementSelectors; +import org.xmlunit.validation.Languages; +import org.xmlunit.validation.ValidationProblem; +import org.xmlunit.validation.ValidationResult; +import org.xmlunit.validation.Validator; +import org.xmlunit.xpath.JAXPXPathEngine; + +public class XMLUnitTest { + @Test + public void givenWrongXml_whenValidateFailsAgainstXsd_thenCorrect() { + Validator v = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI); + v.setSchemaSource(Input.fromStream( + XMLUnitTest.class.getResourceAsStream( + "/students.xsd")).build()); + ValidationResult r = v.validateInstance(Input.fromStream( + XMLUnitTest.class.getResourceAsStream( + "/students_with_error.xml")).build()); + assertFalse(r.isValid()); + } + + @Test + public void givenXmlWithErrors_whenReturnsValidationProblems_thenCorrect() { + Validator v = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI); + v.setSchemaSource(Input.fromStream( + XMLUnitTest.class.getResourceAsStream( + "/students.xsd")).build()); + ValidationResult r = v.validateInstance(Input.fromStream( + XMLUnitTest.class.getResourceAsStream( + "/students_with_error.xml")).build()); + Iterator probs = r.getProblems().iterator(); + int count = 0; + while (probs.hasNext()) { + count++; + probs.next().toString(); + } + assertTrue(count > 0); + } + + @Test + public void givenXml_whenValidatesAgainstXsd_thenCorrect() { + Validator v = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI); + v.setSchemaSource(Input.fromStream( + XMLUnitTest.class.getResourceAsStream( + "/students.xsd")).build()); + ValidationResult r = v.validateInstance(Input.fromStream( + XMLUnitTest.class.getResourceAsStream( + "/students.xml")).build()); + Iterator probs = r.getProblems().iterator(); + while (probs.hasNext()) { + System.out.println(probs.next().toString()); + } + assertTrue(r.isValid()); + } + + @Test + public void givenXPath_whenAbleToRetrieveNodes_thenCorrect() { + ClassLoader classLoader = getClass().getClassLoader(); + + Iterable i = new JAXPXPathEngine().selectNodes( + "//teacher", + Input.fromFile( + new File(classLoader.getResource("teachers.xml") + .getFile())).build()); + assertNotNull(i); + int count = 0; + for (Iterator it = i.iterator(); it.hasNext();) { + count++; + Node node = it.next(); + assertEquals("teacher", node.getNodeName()); + NamedNodeMap map = node.getAttributes(); + assertEquals("department", map.item(0).getNodeName()); + assertEquals("id", map.item(1).getNodeName()); + assertEquals("teacher", node.getNodeName()); + } + assertEquals(2, count); + } + + @Test + public void givenXmlSource_whenAbleToValidateExistingXPath_thenCorrect() { + ClassLoader classLoader = getClass().getClassLoader(); + assertThat(Input.fromFile(new File(classLoader.getResource( + "teachers.xml").getFile())), hasXPath("//teachers")); + assertThat(Input.fromFile(new File(classLoader.getResource( + "teachers.xml").getFile())), hasXPath("//teacher")); + assertThat(Input.fromFile(new File(classLoader.getResource( + "teachers.xml").getFile())), hasXPath("//subject")); + assertThat(Input.fromFile(new File(classLoader.getResource( + "teachers.xml").getFile())), hasXPath("//@department")); + } + + @Test + public void givenXmlSource_whenFailsToValidateInExistentXPath_thenCorrect() { + ClassLoader classLoader = getClass().getClassLoader(); + assertThat(Input.fromFile(new File(classLoader.getResource( + "teachers.xml").getFile())), not(hasXPath("//sujet"))); + } + + // NOTE: ignore as this test demonstrates that two XMLs that contain the same data + // will fail the isSimilarTo test. + @Test @Ignore + public void given2XMLS_whenSimilar_thenCorrect_fails() { + String controlXml = "3false"; + String testXml = "false3"; + assertThat(testXml, isSimilarTo(controlXml)); + } + + @Test + public void given2XMLS_whenSimilar_thenCorrect() { + String controlXml = "3false"; + String testXml = "false3"; + assertThat(testXml,isSimilarTo(controlXml).withNodeMatcher( + new DefaultNodeMatcher(ElementSelectors.byName))); + } + + @Test + public void given2XMLs_whenSimilarWithDiff_thenCorrect() throws Exception { + String myControlXML = "3false"; + String myTestXML = "false3"; + + Diff myDiffSimilar = DiffBuilder + .compare(myControlXML) + .withTest(myTestXML) + .withNodeMatcher( + new DefaultNodeMatcher(ElementSelectors.byName)) + .checkForSimilar().build(); + assertFalse("XML similar " + myDiffSimilar.toString(), + myDiffSimilar.hasDifferences()); + + } + + @Test + public void given2XMLsWithDifferences_whenTestsSimilarWithDifferenceEvaluator_thenCorrect() { + final String control = ""; + final String test = ""; + Diff myDiff = DiffBuilder + .compare(control) + .withTest(test) + .withDifferenceEvaluator( + new IgnoreAttributeDifferenceEvaluator("attr")) + .checkForSimilar().build(); + + assertFalse(myDiff.toString(), myDiff.hasDifferences()); + } + + @Test + public void given2XMLsWithDifferences_whenTestsDifferentWithoutDifferenceEvaluator_thenCorrect() { + final String control = ""; + final String test = ""; + + Diff myDiff = DiffBuilder.compare(control).withTest(test) + .checkForSimilar().build(); + + // assertFalse(myDiff.toString(), myDiff.hasDifferences()); + assertTrue(myDiff.toString(), myDiff.hasDifferences()); + } + + @Test + public void given2XMLS_whenSimilarWithCustomElementSelector_thenCorrect() { + String controlXml = "3false"; + String testXml = "false3"; + assertThat( + testXml, + isSimilarTo(controlXml).withNodeMatcher( + new DefaultNodeMatcher(ElementSelectors.byName))); + + } + + @Test + public void givenFileSourceAsObject_whenAbleToInput_thenCorrect() { + ClassLoader classLoader = getClass().getClassLoader(); + assertThat(Input.from(new File(classLoader.getResource("test.xml").getFile())), + isSimilarTo(Input.from(new File(classLoader.getResource("control.xml").getFile())))); + } + + @Test + public void givenStreamAsSource_whenAbleToInput_thenCorrect() { + assertThat(Input.fromStream(XMLUnitTest.class + .getResourceAsStream("/test.xml")), + isSimilarTo(Input.fromStream(XMLUnitTest.class + .getResourceAsStream("/control.xml")))); + + } + + @Test + public void givenStreamAsObject_whenAbleToInput_thenCorrect() { + assertThat(Input.from(XMLUnitTest.class.getResourceAsStream("/test.xml")), + isSimilarTo(Input.from(XMLUnitTest.class.getResourceAsStream("/control.xml")))); + } + + @Test + public void givenStringSourceAsObject_whenAbleToInput_thenCorrect() { + assertThat( + Input.from("3false"), + isSimilarTo(Input + .from("3false"))); + } + + @Test + public void givenFileSource_whenAbleToInput_thenCorrect() { + ClassLoader classLoader = getClass().getClassLoader(); + String testPath = classLoader.getResource("test.xml").getPath(); + String controlPath = classLoader.getResource("control.xml").getPath(); + assertThat(Input.fromFile(testPath), + isSimilarTo(Input.fromFile(controlPath))); + } + + @Test + public void givenStringSource_whenAbleToInput_thenCorrect() { + String controlXml = "3false"; + String testXml = "3false"; + assertThat(Input.fromString(testXml), + isSimilarTo(Input.fromString(controlXml))); + + } + + @Test + public void givenSource_whenAbleToInput_thenCorrect() { + String controlXml = "3false"; + String testXml = "3false"; + assertThat(Input.fromString(testXml), + isSimilarTo(Input.fromString(controlXml))); + + } + + @Test + public void given2XMLS_whenIdentical_thenCorrect() { + String controlXml = "3false"; + String testXml = "3false"; + assertThat(testXml, isIdenticalTo(controlXml)); + + } + + @Test + public void given2XMLSWithSimilarNodesButDifferentSequence_whenNotIdentical_thenCorrect() { + String controlXml = "3false"; + String testXml = "false3"; + assertThat(testXml, not(isIdenticalTo(controlXml))); + + } + + @Test + public void given2XMLS_whenGeneratesDifferences_thenCorrect() + throws Exception { + String controlXml = "3false"; + String testXml = "false3"; + Diff myDiff = DiffBuilder.compare(controlXml).withTest(testXml).build(); + Iterator iter = myDiff.getDifferences().iterator(); + int size = 0; + while (iter.hasNext()) { + iter.next().toString(); + size++; + } + assertThat(size, greaterThan(1)); + } + + @Test + public void given2XMLS_whenGeneratesOneDifference_thenCorrect() + throws Exception { + String myControlXML = "3false"; + String myTestXML = "false3"; + Diff myDiff = DiffBuilder + .compare(myControlXML) + .withTest(myTestXML) + .withComparisonController( + ComparisonControllers.StopWhenDifferent).build(); + Iterator iter = myDiff.getDifferences().iterator(); + int size = 0; + while (iter.hasNext()) { + iter.next().toString(); + size++; + } + assertThat(size, equalTo(1)); + } + +} diff --git a/xmlunit2-tutorial/src/test/resources/control.xml b/xmlunit2-tutorial/src/test/resources/control.xml new file mode 100644 index 0000000000..afc0f53f91 --- /dev/null +++ b/xmlunit2-tutorial/src/test/resources/control.xml @@ -0,0 +1,4 @@ + + 3 + false + \ No newline at end of file diff --git a/xmlunit2-tutorial/src/test/resources/students.xml b/xmlunit2-tutorial/src/test/resources/students.xml new file mode 100644 index 0000000000..413e73fd07 --- /dev/null +++ b/xmlunit2-tutorial/src/test/resources/students.xml @@ -0,0 +1,11 @@ + + + + Rajiv + 18 + + + Candie + 19 + + \ No newline at end of file diff --git a/xmlunit2-tutorial/src/test/resources/students.xsd b/xmlunit2-tutorial/src/test/resources/students.xsd new file mode 100644 index 0000000000..15b10279f9 --- /dev/null +++ b/xmlunit2-tutorial/src/test/resources/students.xsd @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xmlunit2-tutorial/src/test/resources/students_with_error.xml b/xmlunit2-tutorial/src/test/resources/students_with_error.xml new file mode 100644 index 0000000000..e9ce77faf0 --- /dev/null +++ b/xmlunit2-tutorial/src/test/resources/students_with_error.xml @@ -0,0 +1,12 @@ + + + + Rajiv + 18 +
      + + + Candie + 19 +
      + \ No newline at end of file diff --git a/xmlunit2-tutorial/src/test/resources/teachers.xml b/xmlunit2-tutorial/src/test/resources/teachers.xml new file mode 100644 index 0000000000..9c073d5a38 --- /dev/null +++ b/xmlunit2-tutorial/src/test/resources/teachers.xml @@ -0,0 +1,10 @@ + + + math + physics + + + political education + english + + \ No newline at end of file diff --git a/xmlunit2-tutorial/src/test/resources/test.xml b/xmlunit2-tutorial/src/test/resources/test.xml new file mode 100644 index 0000000000..afc0f53f91 --- /dev/null +++ b/xmlunit2-tutorial/src/test/resources/test.xml @@ -0,0 +1,4 @@ + + 3 + false + \ No newline at end of file diff --git a/xstream/pom.xml b/xstream/pom.xml new file mode 100644 index 0000000000..f505019d71 --- /dev/null +++ b/xstream/pom.xml @@ -0,0 +1,50 @@ + + 4.0.0 + org.baeldung + xstream-introduction + 0.0.1-SNAPSHOT + xstream-introduction + An Introduction To XStream + + + + com.thoughtworks.xstream + xstream + 1.4.5 + + + + org.codehaus.jettison + jettison + 1.3.7 + + + + junit + junit + 4.12 + + + + log4j + log4j + 1.2.17 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + + \ No newline at end of file diff --git a/xstream/src/main/java/com/baeldung/annotation/pojo/Customer.java b/xstream/src/main/java/com/baeldung/annotation/pojo/Customer.java new file mode 100644 index 0000000000..2cdb0f56c9 --- /dev/null +++ b/xstream/src/main/java/com/baeldung/annotation/pojo/Customer.java @@ -0,0 +1,46 @@ +package com.baeldung.annotation.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +import java.util.Date; + +@XStreamAlias("customer") +public class Customer { + + @XStreamAlias("fn") + private String firstName; + + private String lastName; + + private Date dob; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Date getDob() { + return dob; + } + + public void setDob(Date dob) { + this.dob = dob; + } + + @Override + public String toString() { + return "Customer [firstName=" + firstName + ", lastName=" + lastName + + ", dob=" + dob + "]"; + } +} diff --git a/xstream/src/main/java/com/baeldung/annotation/pojo/CustomerOmitField.java b/xstream/src/main/java/com/baeldung/annotation/pojo/CustomerOmitField.java new file mode 100644 index 0000000000..f5b98c9c1b --- /dev/null +++ b/xstream/src/main/java/com/baeldung/annotation/pojo/CustomerOmitField.java @@ -0,0 +1,50 @@ +package com.baeldung.annotation.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamOmitField; + +import java.util.Date; + + +@XStreamAlias("customer") +public class CustomerOmitField { + + @XStreamOmitField + private String firstName; + + private String lastName; + + private Date dob; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Date getDob() { + return dob; + } + + public void setDob(Date dob) { + this.dob = dob; + } + + @Override + public String toString() { + return "CustomerOmitAnnotation [firstName=" + firstName + ", lastName=" + + lastName + ", dob=" + dob + "]"; + } + + +} diff --git a/xstream/src/main/java/com/baeldung/complex/pojo/ContactDetails.java b/xstream/src/main/java/com/baeldung/complex/pojo/ContactDetails.java new file mode 100644 index 0000000000..e091492a1a --- /dev/null +++ b/xstream/src/main/java/com/baeldung/complex/pojo/ContactDetails.java @@ -0,0 +1,46 @@ +package com.baeldung.complex.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamAsAttribute; + +@XStreamAlias("ContactDetails") +public class ContactDetails { + + private String mobile; + + private String landline; + + @XStreamAsAttribute + private String contactType; + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getLandline() { + return landline; + } + + public void setLandline(String landline) { + this.landline = landline; + } + + public String getContactType() { + return contactType; + } + + public void setContactType(String contactType) { + this.contactType = contactType; + } + + @Override + public String toString() { + return "ContactDetails [mobile=" + mobile + ", landline=" + landline + + ", contactType=" + contactType + "]"; + } + +} diff --git a/xstream/src/main/java/com/baeldung/complex/pojo/Customer.java b/xstream/src/main/java/com/baeldung/complex/pojo/Customer.java new file mode 100644 index 0000000000..c6f98982f0 --- /dev/null +++ b/xstream/src/main/java/com/baeldung/complex/pojo/Customer.java @@ -0,0 +1,57 @@ +package com.baeldung.complex.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +import java.util.Date; +import java.util.List; + +@XStreamAlias("customer") +public class Customer { + + private String firstName; + + private String lastName; + + private Date dob; + + private List contactDetailsList; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Date getDob() { + return dob; + } + + public void setDob(Date dob) { + this.dob = dob; + } + + public List getContactDetailsList() { + return contactDetailsList; + } + + public void setContactDetailsList(List contactDetailsList) { + this.contactDetailsList = contactDetailsList; + } + + @Override + public String toString() { + return "Customer [firstName=" + firstName + ", lastName=" + lastName + + ", dob=" + dob + ", contactDetailsList=" + contactDetailsList + + "]"; + } +} diff --git a/xstream/src/main/java/com/baeldung/implicit/collection/pojo/ContactDetails.java b/xstream/src/main/java/com/baeldung/implicit/collection/pojo/ContactDetails.java new file mode 100644 index 0000000000..38ec7ff077 --- /dev/null +++ b/xstream/src/main/java/com/baeldung/implicit/collection/pojo/ContactDetails.java @@ -0,0 +1,46 @@ +package com.baeldung.implicit.collection.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamAsAttribute; + +@XStreamAlias("ContactDetails") +public class ContactDetails { + + private String mobile; + + private String landline; + + @XStreamAsAttribute + private String contactType; + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getLandline() { + return landline; + } + + public void setLandline(String landline) { + this.landline = landline; + } + + public String getContactType() { + return contactType; + } + + public void setContactType(String contactType) { + this.contactType = contactType; + } + + @Override + public String toString() { + return "ContactDetails [mobile=" + mobile + ", landline=" + landline + + ", contactType=" + contactType + "]"; + } + +} diff --git a/xstream/src/main/java/com/baeldung/implicit/collection/pojo/Customer.java b/xstream/src/main/java/com/baeldung/implicit/collection/pojo/Customer.java new file mode 100644 index 0000000000..a50ac850dd --- /dev/null +++ b/xstream/src/main/java/com/baeldung/implicit/collection/pojo/Customer.java @@ -0,0 +1,59 @@ +package com.baeldung.implicit.collection.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamImplicit; + +import java.util.Date; +import java.util.List; + +@XStreamAlias("customer") +public class Customer { + + private String firstName; + + private String lastName; + + private Date dob; + + @XStreamImplicit + private List contactDetailsList; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Date getDob() { + return dob; + } + + public void setDob(Date dob) { + this.dob = dob; + } + + public List getContactDetailsList() { + return contactDetailsList; + } + + public void setContactDetailsList(List contactDetailsList) { + this.contactDetailsList = contactDetailsList; + } + + @Override + public String toString() { + return "Customer [firstName=" + firstName + ", lastName=" + lastName + + ", dob=" + dob + ", contactDetailsList=" + contactDetailsList + + "]"; + } +} diff --git a/xstream/src/main/java/com/baeldung/initializer/SimpleXstreamInitializer.java b/xstream/src/main/java/com/baeldung/initializer/SimpleXstreamInitializer.java new file mode 100644 index 0000000000..a15bea5481 --- /dev/null +++ b/xstream/src/main/java/com/baeldung/initializer/SimpleXstreamInitializer.java @@ -0,0 +1,23 @@ +package com.baeldung.initializer; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; +import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver; + +public class SimpleXstreamInitializer { + + public XStream getXstreamInstance() { + XStream xtreamInstance = new XStream(); + return xtreamInstance; + } + + public XStream getXstreamJettisonMappedInstance() { + XStream xstreamInstance = new XStream(new JettisonMappedXmlDriver()); + return xstreamInstance; + } + + public XStream getXstreamJsonHierarchicalInstance() { + XStream xstreamInstance = new XStream(new JsonHierarchicalStreamDriver()); + return xstreamInstance; + } +} \ No newline at end of file diff --git a/xstream/src/main/java/com/baeldung/pojo/AddressDetails.java b/xstream/src/main/java/com/baeldung/pojo/AddressDetails.java new file mode 100644 index 0000000000..53ba7e9a85 --- /dev/null +++ b/xstream/src/main/java/com/baeldung/pojo/AddressDetails.java @@ -0,0 +1,40 @@ +package com.baeldung.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +import java.util.List; + +@XStreamAlias("AddressDetails") +public class AddressDetails { + + private String address; + + private String zipcode; + + private List contactDetails; + + public String getZipcode() { + return zipcode; + } + + public void setZipcode(String zipcode) { + this.zipcode = zipcode; + } + + public List getContactDetails() { + return contactDetails; + } + + public void setContactDetails(List contactDetails) { + this.contactDetails = contactDetails; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + +} diff --git a/xstream/src/main/java/com/baeldung/pojo/ContactDetails.java b/xstream/src/main/java/com/baeldung/pojo/ContactDetails.java new file mode 100644 index 0000000000..75408bdba8 --- /dev/null +++ b/xstream/src/main/java/com/baeldung/pojo/ContactDetails.java @@ -0,0 +1,28 @@ +package com.baeldung.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("ContactDetails") +public class ContactDetails { + + private String mobile; + + private String landline; + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getLandline() { + return landline; + } + + public void setLandline(String landline) { + this.landline = landline; + } + +} diff --git a/xstream/src/main/java/com/baeldung/pojo/Customer.java b/xstream/src/main/java/com/baeldung/pojo/Customer.java new file mode 100644 index 0000000000..728939c356 --- /dev/null +++ b/xstream/src/main/java/com/baeldung/pojo/Customer.java @@ -0,0 +1,57 @@ +package com.baeldung.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamImplicit; + +import java.util.Date; +import java.util.List; + +@XStreamAlias("customer") +public class Customer { + + private String firstName; + + private String lastName; + + private Date dob; + + @XStreamImplicit + private List contactDetailsList; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Date getDob() { + return dob; + } + + public void setDob(Date dob) { + this.dob = dob; + } + + public List getContactDetailsList() { + return contactDetailsList; + } + + public void setContactDetailsList(List contactDetailsList) { + this.contactDetailsList = contactDetailsList; + } + + @Override + public String toString() { + return "Customer [firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + "]"; + } +} diff --git a/xstream/src/main/java/com/baeldung/pojo/CustomerAddressDetails.java b/xstream/src/main/java/com/baeldung/pojo/CustomerAddressDetails.java new file mode 100644 index 0000000000..f203c9cce9 --- /dev/null +++ b/xstream/src/main/java/com/baeldung/pojo/CustomerAddressDetails.java @@ -0,0 +1,50 @@ +package com.baeldung.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +import java.util.List; + +@XStreamAlias("CustomerAddressDetails") +public class CustomerAddressDetails { + + private List addressDetails; + + private String firstName; + + private String lastName; + + private int age; + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + + public List getAddressDetails() { + return addressDetails; + } + + public void setAddressDetails(List addressDetails) { + this.addressDetails = addressDetails; + } +} diff --git a/xstream/src/main/java/com/baeldung/pojo/CustomerPortfolio.java b/xstream/src/main/java/com/baeldung/pojo/CustomerPortfolio.java new file mode 100644 index 0000000000..90722feb71 --- /dev/null +++ b/xstream/src/main/java/com/baeldung/pojo/CustomerPortfolio.java @@ -0,0 +1,20 @@ +package com.baeldung.pojo; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +import java.util.List; + +@XStreamAlias("CustomerPortfolio") +public class CustomerPortfolio { + + private List customerAddressDetailsList; + + public List getCustomerAddressDetailsList() { + return customerAddressDetailsList; + } + + public void setCustomerAddressDetailsList(List customerAddressDetailsList) { + this.customerAddressDetailsList = customerAddressDetailsList; + } + +} diff --git a/xstream/src/main/java/com/baeldung/utility/MyDateConverter.java b/xstream/src/main/java/com/baeldung/utility/MyDateConverter.java new file mode 100644 index 0000000000..af7ca19aac --- /dev/null +++ b/xstream/src/main/java/com/baeldung/utility/MyDateConverter.java @@ -0,0 +1,40 @@ +package com.baeldung.utility; + +import com.thoughtworks.xstream.converters.ConversionException; +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.GregorianCalendar; + +public class MyDateConverter implements Converter { + + private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy"); + + @Override + public boolean canConvert(Class clazz) { + return Date.class.isAssignableFrom(clazz); + } + + @Override + public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext arg2) { + Date date = (Date) value; + writer.setValue(formatter.format(date)); + } + + @Override + public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext arg1) { + GregorianCalendar calendar = new GregorianCalendar(); + try { + calendar.setTime(formatter.parse(reader.getValue())); + } catch (ParseException e) { + throw new ConversionException(e.getMessage(), e); + } + return calendar; + } +} diff --git a/xstream/src/main/java/com/baeldung/utility/MySingleValueConverter.java b/xstream/src/main/java/com/baeldung/utility/MySingleValueConverter.java new file mode 100644 index 0000000000..9b242f1c7c --- /dev/null +++ b/xstream/src/main/java/com/baeldung/utility/MySingleValueConverter.java @@ -0,0 +1,28 @@ +package com.baeldung.utility; + +import com.baeldung.pojo.Customer; +import com.thoughtworks.xstream.converters.SingleValueConverter; + +import java.text.SimpleDateFormat; +import java.util.Date; + +public class MySingleValueConverter implements SingleValueConverter { + + @Override + public boolean canConvert(Class clazz) { + return Customer.class.isAssignableFrom(clazz); + } + + @Override + public Object fromString(String arg0) { + return null; + } + + @Override + public String toString(Object obj) { + SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy"); + Date date = ((Customer) obj).getDob(); + return ((Customer) obj).getFirstName() + "," + ((Customer) obj).getLastName() + "," + formatter.format(date); + } + +} diff --git a/xstream/src/main/java/com/baeldung/utility/SimpleDataGeneration.java b/xstream/src/main/java/com/baeldung/utility/SimpleDataGeneration.java new file mode 100644 index 0000000000..cf038bfd1b --- /dev/null +++ b/xstream/src/main/java/com/baeldung/utility/SimpleDataGeneration.java @@ -0,0 +1,37 @@ +package com.baeldung.utility; + +import com.baeldung.pojo.ContactDetails; +import com.baeldung.pojo.Customer; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +public class SimpleDataGeneration { + + public static Customer generateData() { + Customer customer = new Customer(); + Calendar cal = Calendar.getInstance(); + cal.set(1986, 01, 14); + customer.setDob(cal.getTime()); + customer.setFirstName("XStream"); + customer.setLastName("Java"); + + List contactDetailsList = new ArrayList(); + + ContactDetails contactDetails1 = new ContactDetails(); + contactDetails1.setLandline("0124-2460311"); + contactDetails1.setMobile("6673543265"); + + ContactDetails contactDetails2 = new ContactDetails(); + contactDetails2.setLandline("0120-223312"); + contactDetails2.setMobile("4676543565"); + + contactDetailsList.add(contactDetails1); + contactDetailsList.add(contactDetails2); + + customer.setContactDetailsList(contactDetailsList); + return customer; + } + +} diff --git a/xstream/src/main/resources/log4j.properties b/xstream/src/main/resources/log4j.properties new file mode 100644 index 0000000000..03d8c51aa0 --- /dev/null +++ b/xstream/src/main/resources/log4j.properties @@ -0,0 +1,14 @@ +# Root logger option +log4j.rootLogger=DEBUG, file +# Redirect log messages to console +# log4j.appender.stdout=org.apache.log4j.ConsoleAppender +# log4j.appender.stdout.Target=System.out +# log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +# log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n +# Redirect log messages to a log file, support file rolling. +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.File=D:\\Test\\xstream-application.log +log4j.appender.file.MaxFileSize=5MB +log4j.appender.file.MaxBackupIndex=10 +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/xstream/src/test/java/com/baeldung/pojo/test/ComplexXmlToObjectAnnotationTest.java b/xstream/src/test/java/com/baeldung/pojo/test/ComplexXmlToObjectAnnotationTest.java new file mode 100644 index 0000000000..479500c4a0 --- /dev/null +++ b/xstream/src/test/java/com/baeldung/pojo/test/ComplexXmlToObjectAnnotationTest.java @@ -0,0 +1,38 @@ +package com.baeldung.pojo.test; + +import com.baeldung.complex.pojo.Customer; +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileReader; +import java.io.IOException; + +public class ComplexXmlToObjectAnnotationTest { + + private XStream xstream = null; + + @Before + public void dataSetup() { + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamInstance(); + xstream.processAnnotations(Customer.class); + } + + @Test + public void convertXmlToObjectFromFile() { + try { + ClassLoader classLoader = getClass().getClassLoader(); + FileReader reader = new FileReader(classLoader.getResource("data-file-alias-field-complex.xml").getFile()); + Customer customer = (Customer) xstream.fromXML(reader); + Assert.assertNotNull(customer); + Assert.assertNotNull(customer.getContactDetailsList()); + + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/xstream/src/test/java/com/baeldung/pojo/test/ComplexXmlToObjectAttributeCollectionTest.java b/xstream/src/test/java/com/baeldung/pojo/test/ComplexXmlToObjectAttributeCollectionTest.java new file mode 100644 index 0000000000..8c569aa11e --- /dev/null +++ b/xstream/src/test/java/com/baeldung/pojo/test/ComplexXmlToObjectAttributeCollectionTest.java @@ -0,0 +1,42 @@ +package com.baeldung.pojo.test; + +import com.baeldung.complex.pojo.ContactDetails; +import com.baeldung.complex.pojo.Customer; +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileReader; +import java.io.IOException; + +public class ComplexXmlToObjectAttributeCollectionTest { + + private XStream xstream = null; + + @Before + public void dataSetup() { + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamInstance(); + xstream.processAnnotations(Customer.class); + } + + @Test + public void convertXmlToObjectFromFile() { + try { + ClassLoader classLoader = getClass().getClassLoader(); + FileReader reader = new FileReader(classLoader.getResource("data-file-alias-field-complex.xml").getFile()); + Customer customer = (Customer) xstream.fromXML(reader); + Assert.assertNotNull(customer); + Assert.assertNotNull(customer.getContactDetailsList()); + for (ContactDetails contactDetails : customer.getContactDetailsList()) { + Assert.assertNotNull(contactDetails.getContactType()); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/xstream/src/test/java/com/baeldung/pojo/test/ComplexXmlToObjectCollectionTest.java b/xstream/src/test/java/com/baeldung/pojo/test/ComplexXmlToObjectCollectionTest.java new file mode 100644 index 0000000000..29ef7a5d64 --- /dev/null +++ b/xstream/src/test/java/com/baeldung/pojo/test/ComplexXmlToObjectCollectionTest.java @@ -0,0 +1,39 @@ +package com.baeldung.pojo.test; + +import com.baeldung.implicit.collection.pojo.Customer; +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileReader; +import java.io.IOException; + +public class ComplexXmlToObjectCollectionTest { + + private XStream xstream = null; + + @Before + public void dataSetup() { + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamInstance(); + xstream.processAnnotations(Customer.class); + } + + @Test + public void convertXmlToObjectFromFile() { + try { + ClassLoader classLoader = getClass().getClassLoader(); + FileReader reader = new FileReader(classLoader.getResource("data-file-alias-implicit-collection.xml").getFile()); + Customer customer = (Customer) xstream.fromXML(reader); + Assert.assertNotNull(customer); + Assert.assertNotNull(customer.getContactDetailsList()); + //System.out.println(customer); + + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectAliasTest.java b/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectAliasTest.java new file mode 100644 index 0000000000..8a4de3b70a --- /dev/null +++ b/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectAliasTest.java @@ -0,0 +1,37 @@ +package com.baeldung.pojo.test; + +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.baeldung.pojo.Customer; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileReader; +import java.io.IOException; + +public class XmlToObjectAliasTest { + + private XStream xstream = null; + + @Before + public void dataSetup() { + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamInstance(); + xstream.alias("customer", Customer.class); + } + + @Test + public void convertXmlToObjectFromFile() { + try { + ClassLoader classLoader = getClass().getClassLoader(); + FileReader reader = new FileReader(classLoader.getResource("data-file-alias.xml").getFile()); + Customer customer = (Customer) xstream.fromXML(reader); + Assert.assertNotNull(customer); + + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectAnnotationTest.java b/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectAnnotationTest.java new file mode 100644 index 0000000000..4a7ff2f74a --- /dev/null +++ b/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectAnnotationTest.java @@ -0,0 +1,38 @@ +package com.baeldung.pojo.test; + +import com.baeldung.annotation.pojo.Customer; +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileReader; +import java.io.IOException; + +public class XmlToObjectAnnotationTest { + + private XStream xstream = null; + + @Before + public void dataSetup() { + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamInstance(); + xstream.processAnnotations(Customer.class); + } + + @Test + public void convertXmlToObjectFromFile() { + try { + ClassLoader classLoader = getClass().getClassLoader(); + FileReader reader = new FileReader(classLoader.getResource("data-file-alias-field.xml").getFile()); + Customer customer = (Customer) xstream.fromXML(reader); + Assert.assertNotNull(customer); + Assert.assertNotNull(customer.getFirstName()); + + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectFieldAliasTest.java b/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectFieldAliasTest.java new file mode 100644 index 0000000000..3b1b8326ab --- /dev/null +++ b/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectFieldAliasTest.java @@ -0,0 +1,39 @@ +package com.baeldung.pojo.test; + +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.baeldung.pojo.Customer; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileReader; +import java.io.IOException; + +public class XmlToObjectFieldAliasTest { + + private XStream xstream = null; + + @Before + public void dataSetup() { + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamInstance(); + xstream.alias("customer", Customer.class); + xstream.aliasField("fn", Customer.class, "firstName"); + } + + @Test + public void convertXmlToObjectFromFile() { + try { + ClassLoader classLoader = getClass().getClassLoader(); + FileReader reader = new FileReader(classLoader.getResource("data-file-alias-field.xml").getFile()); + Customer customer = (Customer) xstream.fromXML(reader); + Assert.assertNotNull(customer); + Assert.assertNotNull(customer.getFirstName()); + + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectIgnoreFieldsTest.java b/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectIgnoreFieldsTest.java new file mode 100644 index 0000000000..95a034b3e7 --- /dev/null +++ b/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectIgnoreFieldsTest.java @@ -0,0 +1,38 @@ +package com.baeldung.pojo.test; + +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.baeldung.pojo.Customer; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileReader; +import java.io.IOException; + +public class XmlToObjectIgnoreFieldsTest { + + private XStream xstream = null; + + @Before + public void dataSetup() { + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamInstance(); + xstream.alias("customer", Customer.class); + xstream.ignoreUnknownElements(); + } + + @Test + public void convertXmlToObjectFromFile() { + try { + ClassLoader classLoader = getClass().getClassLoader(); + FileReader reader = new FileReader(classLoader.getResource("data-file-ignore-field.xml").getFile()); + Customer customer = (Customer) xstream.fromXML(reader); + Assert.assertNotNull(customer); + //System.out.println(customer); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectTest.java b/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectTest.java new file mode 100644 index 0000000000..b6b64ce8da --- /dev/null +++ b/xstream/src/test/java/com/baeldung/pojo/test/XmlToObjectTest.java @@ -0,0 +1,46 @@ +package com.baeldung.pojo.test; + +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.baeldung.pojo.Customer; +import com.baeldung.utility.SimpleDataGeneration; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.FileReader; +import java.io.IOException; + +public class XmlToObjectTest { + + private XStream xstream = null; + + @Before + public void dataSetup() { + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamInstance(); + } + + @Test + public void convertXmlToObjectFromFile() { + try { + ClassLoader classLoader = getClass().getClassLoader(); + FileReader reader = new FileReader(classLoader.getResource("data-file.xml").getFile()); + Customer customer = (Customer) xstream.fromXML(reader); + Assert.assertNotNull(customer); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Test + public void convertXmlToObjectFromString() { + Customer customer = SimpleDataGeneration.generateData(); + String dataXml = xstream.toXML(customer); + Customer convertedCustomer = (Customer) xstream.fromXML(dataXml); + Assert.assertNotNull(convertedCustomer); + } + + +} diff --git a/xstream/src/test/java/com/baeldung/test/XStreamJettisonTest.java b/xstream/src/test/java/com/baeldung/test/XStreamJettisonTest.java new file mode 100644 index 0000000000..f37605cc98 --- /dev/null +++ b/xstream/src/test/java/com/baeldung/test/XStreamJettisonTest.java @@ -0,0 +1,47 @@ +package com.baeldung.test; + +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.baeldung.pojo.ContactDetails; +import com.baeldung.pojo.Customer; +import com.baeldung.utility.SimpleDataGeneration; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class XStreamJettisonTest { + + private Customer customer = null; + + private String dataJson = null; + + private XStream xstream = null; + + @Before + public void dataSetup() { + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamJettisonMappedInstance(); + xstream.processAnnotations(Customer.class); + } + + @Test + public void convertObjectToJson() { + customer = SimpleDataGeneration.generateData(); + xstream.alias("customer", Customer.class); + xstream.alias("contactDetails", ContactDetails.class); + xstream.aliasField("fn", Customer.class, "firstName"); + dataJson = xstream.toXML(customer); + System.out.println(dataJson); + Assert.assertNotNull(dataJson); + } + + @Test + public void convertJsonToObject() { + customer = SimpleDataGeneration.generateData(); + dataJson = xstream.toXML(customer); + customer = (Customer) xstream.fromXML(dataJson); + System.out.println(customer); + Assert.assertNotNull(customer); + } + +} diff --git a/xstream/src/test/java/com/baeldung/test/XStreamJsonHierarchicalTest.java b/xstream/src/test/java/com/baeldung/test/XStreamJsonHierarchicalTest.java new file mode 100644 index 0000000000..1e71cb7066 --- /dev/null +++ b/xstream/src/test/java/com/baeldung/test/XStreamJsonHierarchicalTest.java @@ -0,0 +1,44 @@ +package com.baeldung.test; + +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.baeldung.pojo.ContactDetails; +import com.baeldung.pojo.Customer; +import com.baeldung.utility.SimpleDataGeneration; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class XStreamJsonHierarchicalTest { + + private Customer customer = null; + private String dataJson = null; + private XStream xstream = null; + + @Before + public void dataSetup() { + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamJsonHierarchicalInstance(); + xstream.processAnnotations(Customer.class); + } + + @Test + public void convertObjectToJson() { + customer = SimpleDataGeneration.generateData(); + xstream.alias("customer", Customer.class); + xstream.alias("contactDetails", ContactDetails.class); + xstream.aliasField("fn", Customer.class, "firstName"); + dataJson = xstream.toXML(customer); + System.out.println(dataJson); + Assert.assertNotNull(dataJson); + } + + @Test(expected = UnsupportedOperationException.class) + public void convertJsonToObject() { + customer = SimpleDataGeneration.generateData(); + dataJson = xstream.toXML(customer); + customer = (Customer) xstream.fromXML(dataJson); + Assert.assertNotNull(customer); + } + +} diff --git a/xstream/src/test/java/com/baeldung/utility/XStreamSimpleXmlTest.java b/xstream/src/test/java/com/baeldung/utility/XStreamSimpleXmlTest.java new file mode 100644 index 0000000000..83a965ce1b --- /dev/null +++ b/xstream/src/test/java/com/baeldung/utility/XStreamSimpleXmlTest.java @@ -0,0 +1,57 @@ +package com.baeldung.utility; + +import com.baeldung.initializer.SimpleXstreamInitializer; +import com.baeldung.pojo.AddressDetails; +import com.baeldung.pojo.ContactDetails; +import com.baeldung.pojo.Customer; +import com.thoughtworks.xstream.XStream; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class XStreamSimpleXmlTest { + + private Customer customer; + private String dataXml; + private XStream xstream; + + @Before + public void dataSetup() { + customer = SimpleDataGeneration.generateData(); + SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer(); + xstream = simpleXstreamInitializer.getXstreamInstance(); + xstream.processAnnotations(Customer.class); + xstream.processAnnotations(AddressDetails.class); + xstream.processAnnotations(ContactDetails.class); + xstream.omitField(Customer.class, "lastName"); + xstream.registerConverter(new MyDateConverter()); + // xstream.registerConverter(new MySingleValueConverter()); + xstream.aliasField("fn", Customer.class, "firstName"); + dataXml = xstream.toXML(customer); + } + + @Test + public void testClassAliasedAnnotation() { + Assert.assertNotEquals(-1, dataXml.indexOf("")); + } + + @Test + public void testFieldAliasedAnnotation() { + Assert.assertNotEquals(-1, dataXml.indexOf("")); + } + + @Test + public void testImplicitCollection() { + Assert.assertEquals(-1, dataXml.indexOf("contactDetailsList")); + } + + @Test + public void testDateFieldFormating() { + Assert.assertEquals("14-02-1986", dataXml.substring(dataXml.indexOf("") + 5, dataXml.indexOf(""))); + } + + @Test + public void testOmitField() { + Assert.assertEquals(-1, dataXml.indexOf("lastName")); + } +} diff --git a/xstream/src/test/resources/data-file-alias-field-complex.xml b/xstream/src/test/resources/data-file-alias-field-complex.xml new file mode 100644 index 0000000000..06050cd1ed --- /dev/null +++ b/xstream/src/test/resources/data-file-alias-field-complex.xml @@ -0,0 +1,15 @@ + + XStream + Java + 1986-02-14 04:14:05.874 UTC + + + 6673543265 + 0124-2460311 + + + 4676543565 + 0120-223312 + + + \ No newline at end of file diff --git a/xstream/src/test/resources/data-file-alias-field.xml b/xstream/src/test/resources/data-file-alias-field.xml new file mode 100644 index 0000000000..7e71d721ca --- /dev/null +++ b/xstream/src/test/resources/data-file-alias-field.xml @@ -0,0 +1,5 @@ + + XStream + Java + 1986-02-14 03:46:16.381 UTC + \ No newline at end of file diff --git a/xstream/src/test/resources/data-file-alias-implicit-collection.xml b/xstream/src/test/resources/data-file-alias-implicit-collection.xml new file mode 100644 index 0000000000..0cb852fc04 --- /dev/null +++ b/xstream/src/test/resources/data-file-alias-implicit-collection.xml @@ -0,0 +1,13 @@ + + XStream + Java + 1986-02-14 04:14:20.541 UTC + + 6673543265 + 0124-2460311 + + + 4676543565 + 0120-223312 + + \ No newline at end of file diff --git a/xstream/src/test/resources/data-file-alias.xml b/xstream/src/test/resources/data-file-alias.xml new file mode 100644 index 0000000000..61ee9f1ac3 --- /dev/null +++ b/xstream/src/test/resources/data-file-alias.xml @@ -0,0 +1,5 @@ + + XStream + Java + 1986-02-14 03:46:16.381 UTC + \ No newline at end of file diff --git a/xstream/src/test/resources/data-file-ignore-field.xml b/xstream/src/test/resources/data-file-ignore-field.xml new file mode 100644 index 0000000000..7dc8023b96 --- /dev/null +++ b/xstream/src/test/resources/data-file-ignore-field.xml @@ -0,0 +1,6 @@ + + XStream + Java + 1986-02-14 04:14:20.541 UTC + XStream Java + \ No newline at end of file diff --git a/xstream/src/test/resources/data-file.xml b/xstream/src/test/resources/data-file.xml new file mode 100644 index 0000000000..b8dbce32c0 --- /dev/null +++ b/xstream/src/test/resources/data-file.xml @@ -0,0 +1,5 @@ + + XStream + Java + 1986-02-14 03:46:16.381 UTC + \ No newline at end of file