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/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/jsf/pom.xml b/jsf/pom.xml
index 2f5d315e41..c4801996de 100644
--- a/jsf/pom.xml
+++ b/jsf/pom.xml
@@ -90,12 +90,21 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.5.1
+ ${maven-compiler-plugin.version}
1.8
1.8
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ ${maven-war-plugin.version}
+
+ false
+
+
@@ -112,5 +121,10 @@
3.1.0
+
+
+ 3.5.1
+ 2.6
+
\ 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/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/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/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-data-couchbase-2/README.md b/spring-data-couchbase-2/README.md
index e58e37e090..3ed226fb33 100644
--- a/spring-data-couchbase-2/README.md
+++ b/spring-data-couchbase-2/README.md
@@ -2,11 +2,12 @@
### 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)
### Overview
This Maven project contains the Java code for Spring Data Couchbase
entities, repositories, and template-based services
-as described in the tutorial, as well as a unit test
+as described in the tutorials, as well as a unit/integration test
for each service implementation.
### Working with the Code
@@ -22,13 +23,16 @@ mvn clean install
```
### Running the tests
-There are three test classes in src/test/java in the package
+The following test classes 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 latter two may be run as JUnit tests from your IDE
+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
index 93b3dbddb4..d24ef4aeaa 100644
--- a/spring-data-couchbase-2/pom.xml
+++ b/spring-data-couchbase-2/pom.xml
@@ -93,7 +93,7 @@
1.7
UTF-8
4.2.4.RELEASE
- 2.0.0.RELEASE
+ 2.1.1.RELEASE
5.2.4.Final
2.9.2
1.1.3
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
index bedae26e00..3fabf7a11e 100644
--- 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
@@ -27,28 +27,20 @@ public abstract class PersonServiceTest extends IntegrationTest {
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 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());
-
+ 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() {
- Cluster cluster = CouchbaseCluster.create(MyCouchbaseConfig.NODE_LIST);
- Bucket bucket = cluster.openBucket(MyCouchbaseConfig.BUCKET_NAME, MyCouchbaseConfig.BUCKET_PASSWORD);
+ 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();
@@ -57,7 +49,7 @@ public abstract class PersonServiceTest extends IntegrationTest {
@Test
public void whenFindingPersonByJohnSmithId_thenReturnsJohnSmith() {
- Person actualPerson = personService.findOne(johnSmithId);
+ final Person actualPerson = personService.findOne(johnSmithId);
assertNotNull(actualPerson);
assertNotNull(actualPerson.getCreated());
assertEquals(johnSmith, actualPerson);
@@ -65,7 +57,7 @@ public abstract class PersonServiceTest extends IntegrationTest {
@Test
public void whenFindingAllPersons_thenReturnsTwoOrMorePersonsIncludingJohnSmithAndFooBar() {
- List resultList = personService.findAll();
+ final List resultList = personService.findAll();
assertNotNull(resultList);
assertFalse(resultList.isEmpty());
assertTrue(resultContains(resultList, johnSmith));
@@ -75,8 +67,8 @@ public abstract class PersonServiceTest extends IntegrationTest {
@Test
public void whenFindingByFirstNameJohn_thenReturnsOnlyPersonsNamedJohn() {
- String expectedFirstName = john;
- List resultList = personService.findByFirstName(expectedFirstName);
+ final String expectedFirstName = john;
+ final List resultList = personService.findByFirstName(expectedFirstName);
assertNotNull(resultList);
assertFalse(resultList.isEmpty());
assertTrue(allResultsContainExpectedFirstName(resultList, expectedFirstName));
@@ -84,17 +76,24 @@ public abstract class PersonServiceTest extends IntegrationTest {
@Test
public void whenFindingByLastNameSmith_thenReturnsOnlyPersonsNamedSmith() {
- String expectedLastName = smith;
- List resultList = personService.findByLastName(expectedLastName);
+ final String expectedLastName = smith;
+ final List resultList = personService.findByLastName(expectedLastName);
assertNotNull(resultList);
assertFalse(resultList.isEmpty());
assertTrue(allResultsContainExpectedLastName(resultList, expectedLastName));
}
-
+
+ @Test
+ public void whenFindingByFirstNameJohn_thenReturnsOnePersonNamedJohn() {
+ final String expectedFirstName = john;
+ final List resultList = personService.findByFirstName(expectedFirstName);
+ assertTrue(resultList.size() == 1);
+ }
+
private boolean resultContains(List resultList, Person person) {
boolean found = false;
- for(Person p : resultList) {
- if(p.equals(person)) {
+ for (final Person p : resultList) {
+ if (p.equals(person)) {
found = true;
break;
}
@@ -104,8 +103,8 @@ public abstract class PersonServiceTest extends IntegrationTest {
private boolean allResultsContainExpectedFirstName(List resultList, String firstName) {
boolean found = false;
- for(Person p : resultList) {
- if(p.getFirstName().equals(firstName)) {
+ for (final Person p : resultList) {
+ if (p.getFirstName().equals(firstName)) {
found = true;
break;
}
@@ -115,8 +114,8 @@ public abstract class PersonServiceTest extends IntegrationTest {
private boolean allResultsContainExpectedLastName(List resultList, String lastName) {
boolean found = false;
- for(Person p : resultList) {
- if(p.getLastName().equals(lastName)) {
+ for (final Person p : resultList) {
+ if (p.getLastName().equals(lastName)) {
found = true;
break;
}
diff --git a/spring-data-couchbase-2b/.classpath b/spring-data-couchbase-2b/.classpath
new file mode 100644
index 0000000000..450036fc00
--- /dev/null
+++ b/spring-data-couchbase-2b/.classpath
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-data-couchbase-2b/.project b/spring-data-couchbase-2b/.project
new file mode 100644
index 0000000000..1690ad8ce2
--- /dev/null
+++ b/spring-data-couchbase-2b/.project
@@ -0,0 +1,30 @@
+
+
+ spring-data-couchbase-2
+ This project is a simple template for a jar utility using Spring.
+
+
+
+
+
+ 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-couchbase-2b/.springBeans b/spring-data-couchbase-2b/.springBeans
new file mode 100644
index 0000000000..0c014a97b6
--- /dev/null
+++ b/spring-data-couchbase-2b/.springBeans
@@ -0,0 +1,20 @@
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
diff --git a/spring-data-couchbase-2b/README.md b/spring-data-couchbase-2b/README.md
new file mode 100644
index 0000000000..262962f58a
--- /dev/null
+++ b/spring-data-couchbase-2b/README.md
@@ -0,0 +1,36 @@
+## 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)
+
+### Overview
+This Maven project contains the Java code for Spring Data Couchbase
+entities, repositories, and repository-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
+```
+
+### Running the tests
+The following test classes are in src/test/java in the package
+org.baeldung.spring.data.couchbase.service:
+- CampusRepositoryServiceTest
+- PersonRepositoryServiceTest
+- StudentRepositoryServiceTest
+
+These may be run as JUnit tests from your IDE
+or using the Maven command line:
+```
+mvn test
+```
diff --git a/spring-data-couchbase-2b/pom.xml b/spring-data-couchbase-2b/pom.xml
new file mode 100644
index 0000000000..7d58f78ce5
--- /dev/null
+++ b/spring-data-couchbase-2b/pom.xml
@@ -0,0 +1,105 @@
+
+ 4.0.0
+ org.baeldung
+ spring-data-couchbase-2b
+ 0.1-SNAPSHOT
+ spring-data-couchbase-2b
+ 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-2b/src/main/java/org/baeldung/spring/data/couchbase/MyCouchbaseConfig.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/MyCouchbaseConfig.java
new file mode 100644
index 0000000000..8eeda08455
--- /dev/null
+++ b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/MyCouchbaseConfig.java
@@ -0,0 +1,79 @@
+package org.baeldung.spring.data.couchbase;
+
+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.couchbase"})
+public class MyCouchbaseConfig 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
+ 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-2b/src/main/java/org/baeldung/spring/data/couchbase/model/Campus.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/model/Campus.java
new file mode 100644
index 0000000000..201b14cf0b
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/main/java/org/baeldung/spring/data/couchbase/model/Person.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/model/Person.java
new file mode 100644
index 0000000000..9220e157ed
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/main/java/org/baeldung/spring/data/couchbase/model/Student.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/model/Student.java
new file mode 100644
index 0000000000..9c266c2c62
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/main/java/org/baeldung/spring/data/couchbase/repos/CampusRepository.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/repos/CampusRepository.java
new file mode 100644
index 0000000000..22b2fb2735
--- /dev/null
+++ b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/repos/CampusRepository.java
@@ -0,0 +1,19 @@
+package org.baeldung.spring.data.couchbase.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-2b/src/main/java/org/baeldung/spring/data/couchbase/repos/PersonRepository.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/repos/PersonRepository.java
new file mode 100644
index 0000000000..14b77759e3
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/main/java/org/baeldung/spring/data/couchbase/repos/StudentRepository.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/repos/StudentRepository.java
new file mode 100644
index 0000000000..433964c872
--- /dev/null
+++ b/spring-data-couchbase-2b/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 {
+ List findByFirstName(String firstName);
+ List findByLastName(String lastName);
+}
diff --git a/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/service/CampusRepositoryService.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/service/CampusRepositoryService.java
new file mode 100644
index 0000000000..d12e59ba1f
--- /dev/null
+++ b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/service/CampusRepositoryService.java
@@ -0,0 +1,54 @@
+package org.baeldung.spring.data.couchbase.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.couchbase.repos.CampusRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.geo.Distance;
+import org.springframework.data.geo.Point;
+import org.springframework.stereotype.Service;
+
+@Service
+@Qualifier("CampusRepositoryService")
+public class CampusRepositoryService 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-2b/src/main/java/org/baeldung/spring/data/couchbase/service/CampusService.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/service/CampusService.java
new file mode 100644
index 0000000000..e82c14cb87
--- /dev/null
+++ b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/service/CampusService.java
@@ -0,0 +1,20 @@
+package org.baeldung.spring.data.couchbase.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-2b/src/main/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryService.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryService.java
new file mode 100644
index 0000000000..90cc36780a
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/main/java/org/baeldung/spring/data/couchbase/service/PersonService.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/service/PersonService.java
new file mode 100644
index 0000000000..a823908b01
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/main/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryService.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryService.java
new file mode 100644
index 0000000000..58304afc1c
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/main/java/org/baeldung/spring/data/couchbase/service/StudentService.java b/spring-data-couchbase-2b/src/main/java/org/baeldung/spring/data/couchbase/service/StudentService.java
new file mode 100644
index 0000000000..f483ef0fb6
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/main/resources/logback.xml b/spring-data-couchbase-2b/src/main/resources/logback.xml
new file mode 100644
index 0000000000..d9067fd1da
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/site/site.xml b/spring-data-couchbase-2b/src/site/site.xml
new file mode 100644
index 0000000000..dda96feecd
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/test/java/org/baeldung/spring/data/couchbase/IntegrationTest.java b/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/IntegrationTest.java
new file mode 100644
index 0000000000..ce2daa92cd
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/test/java/org/baeldung/spring/data/couchbase/IntegrationTestConfig.java b/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/IntegrationTestConfig.java
new file mode 100644
index 0000000000..6f040c34db
--- /dev/null
+++ b/spring-data-couchbase-2b/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-2b/src/test/java/org/baeldung/spring/data/couchbase/TestCouchbaseConfig.java b/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/TestCouchbaseConfig.java
new file mode 100644
index 0000000000..c298ef0a61
--- /dev/null
+++ b/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/TestCouchbaseConfig.java
@@ -0,0 +1,17 @@
+package org.baeldung.spring.data.couchbase;
+
+import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
+import org.springframework.data.couchbase.core.query.Consistency;
+
+public class TestCouchbaseConfig extends MyCouchbaseConfig {
+
+ @Override
+ public String typeKey() {
+ return MappingCouchbaseConverter.TYPEKEY_SYNCGATEWAY_COMPATIBLE;
+ }
+
+ @Override
+ public Consistency getDefaultConsistency() {
+ return Consistency.READ_YOUR_OWN_WRITES;
+ }
+}
diff --git a/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/service/CampusRepositoryServiceTest.java b/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/service/CampusRepositoryServiceTest.java
new file mode 100644
index 0000000000..5a718f0807
--- /dev/null
+++ b/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/service/CampusRepositoryServiceTest.java
@@ -0,0 +1,135 @@
+package org.baeldung.spring.data.couchbase.service;
+
+import static org.junit.Assert.*;
+
+import java.util.Set;
+
+import javax.annotation.PostConstruct;
+
+import org.baeldung.spring.data.couchbase.IntegrationTest;
+import org.baeldung.spring.data.couchbase.model.Campus;
+import org.baeldung.spring.data.couchbase.repos.CampusRepository;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.geo.Distance;
+import org.springframework.data.geo.Metrics;
+import org.springframework.data.geo.Point;
+
+public class CampusRepositoryServiceTest extends IntegrationTest {
+
+ @Autowired
+ @Qualifier("CampusRepositoryService")
+ private CampusRepositoryService 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-2b/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceTest.java b/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceTest.java
new file mode 100644
index 0000000000..84b6f75d56
--- /dev/null
+++ b/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceTest.java
@@ -0,0 +1,130 @@
+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 org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+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 PersonRepositoryServiceTest extends IntegrationTest {
+
+ private static final String typeField = "_class";
+ private static final String john = "John";
+ private static final String smith = "Smith";
+ private static final String johnSmithId = "person:" + john + ":" + smith;
+ private static final Person johnSmith = new Person(johnSmithId, john, smith);
+ private static final JsonObject jsonJohnSmith = JsonObject.empty()
+ .put(typeField, Person.class.getName())
+ .put("firstName", john)
+ .put("lastName", smith)
+ .put("created", DateTime.now().getMillis());
+
+ private static final String foo = "Foo";
+ private static final String bar = "Bar";
+ private static final String foobarId = "person:" + foo + ":" + bar;
+ private static final Person foobar = new Person(foobarId, foo, bar);
+ private static final JsonObject jsonFooBar = JsonObject.empty()
+ .put(typeField, Person.class.getName())
+ .put("firstName", foo)
+ .put("lastName", bar)
+ .put("created", DateTime.now().getMillis());
+
+ @Autowired
+ @Qualifier("PersonRepositoryService")
+ private PersonService personService;
+
+ @BeforeClass
+ public static void setupBeforeClass() {
+ Cluster cluster = CouchbaseCluster.create(MyCouchbaseConfig.NODE_LIST);
+ Bucket bucket = cluster.openBucket(MyCouchbaseConfig.DEFAULT_BUCKET_NAME, MyCouchbaseConfig.DEFAULT_BUCKET_PASSWORD);
+ bucket.upsert(JsonDocument.create(johnSmithId, jsonJohnSmith));
+ bucket.upsert(JsonDocument.create(foobarId, jsonFooBar));
+ bucket.close();
+ cluster.disconnect();
+ }
+
+ @Test
+ public void whenFindingPersonByJohnSmithId_thenReturnsJohnSmith() {
+ Person actualPerson = personService.findOne(johnSmithId);
+ assertNotNull(actualPerson);
+ assertNotNull(actualPerson.getCreated());
+ assertEquals(johnSmith, actualPerson);
+ }
+
+ @Test
+ public void whenFindingAllPersons_thenReturnsTwoOrMorePersonsIncludingJohnSmithAndFooBar() {
+ 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() {
+ String expectedFirstName = john;
+ List resultList = personService.findByFirstName(expectedFirstName);
+ assertNotNull(resultList);
+ assertFalse(resultList.isEmpty());
+ assertTrue(allResultsContainExpectedFirstName(resultList, expectedFirstName));
+ }
+
+ @Test
+ public void whenFindingByLastNameSmith_thenReturnsOnlyPersonsNamedSmith() {
+ String expectedLastName = smith;
+ 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(Person p : resultList) {
+ if(p.equals(person)) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+ }
+
+ private boolean allResultsContainExpectedFirstName(List resultList, String firstName) {
+ boolean found = false;
+ for(Person p : resultList) {
+ if(p.getFirstName().equals(firstName)) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+ }
+
+ private boolean allResultsContainExpectedLastName(List resultList, String lastName) {
+ boolean found = false;
+ for(Person p : resultList) {
+ if(p.getLastName().equals(lastName)) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+ }
+}
diff --git a/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceTest.java b/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceTest.java
new file mode 100644
index 0000000000..166f01d754
--- /dev/null
+++ b/spring-data-couchbase-2b/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceTest.java
@@ -0,0 +1,170 @@
+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 org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+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 StudentRepositoryServiceTest extends IntegrationTest {
+
+ private static final String typeField = "_class";
+ private static final String joe = "Joe";
+ private static final String college = "College";
+ private static final String joeCollegeId = "student:" + joe + ":" + college;
+ private static final DateTime joeCollegeDob = DateTime.now().minusYears(21);
+ private static final Student joeCollege = new Student(joeCollegeId, joe, college, joeCollegeDob);
+ private 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);
+
+ private static final String judy = "Judy";
+ private static final String jetson = "Jetson";
+ private static final String judyJetsonId = "student:" + judy + ":" + jetson;
+ private static final DateTime judyJetsonDob = DateTime.now().minusYears(19).minusMonths(5).minusDays(3);
+ private static final Student judyJetson = new Student(judyJetsonId, judy, jetson, judyJetsonDob);
+ private 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
+ @Qualifier("StudentRepositoryService")
+ private StudentService studentService;
+
+ @BeforeClass
+ public static void setupBeforeClass() {
+ Cluster cluster = CouchbaseCluster.create(MyCouchbaseConfig.NODE_LIST);
+ Bucket bucket = cluster.openBucket(MyCouchbaseConfig.DEFAULT_BUCKET_NAME, MyCouchbaseConfig.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-2b/src/test/resources/logback.xml b/spring-data-couchbase-2b/src/test/resources/logback.xml
new file mode 100644
index 0000000000..d9067fd1da
--- /dev/null
+++ b/spring-data-couchbase-2b/src/test/resources/logback.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ web - %date [%thread] %-5level %logger{36} - %message%n
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file