From 8880d96d3a0c6c5dcdc0f188756d89543fec7481 Mon Sep 17 00:00:00 2001 From: codehunter34 Date: Sun, 23 Dec 2018 16:41:11 -0500 Subject: [PATCH 001/190] BAEL-2399: Guice vs Spring - Dependency Injection --- .../com/baeldung/examples/common/Account.java | 27 +++++++ .../examples/common/AccountService.java | 8 +++ .../examples/common/AccountServiceImpl.java | 15 ++++ .../com/baeldung/examples/common/Address.java | 35 +++++++++ .../baeldung/examples/common/BookService.java | 9 +++ .../examples/common/BookServiceImpl.java | 12 ++++ .../com/baeldung/examples/guice/Employee.java | 32 +++++++++ .../java/com/baeldung/examples/guice/Foo.java | 5 ++ .../baeldung/examples/guice/FooGenerator.java | 11 +++ .../baeldung/examples/guice/GuiceUser.java | 32 +++++++++ .../examples/guice/GuiceUserService.java | 19 +++++ .../com/baeldung/examples/guice/Person.java | 39 ++++++++++ .../examples/guice/modules/GuiceModule.java | 47 ++++++++++++ .../baeldung/examples/spring/AppConfig.java | 19 +++++ .../baeldung/examples/spring/SpringUser.java | 35 +++++++++ .../com/baeldung/examples/spring/Student.java | 34 +++++++++ .../baeldung/examples/spring/UserService.java | 22 ++++++ .../com/baeldung/examples/GuiceTests.java | 72 +++++++++++++++++++ .../com/baeldung/examples/SpringTests.java | 58 +++++++++++++++ 19 files changed, 531 insertions(+) create mode 100644 guice/src/main/java/com/baeldung/examples/common/Account.java create mode 100644 guice/src/main/java/com/baeldung/examples/common/AccountService.java create mode 100644 guice/src/main/java/com/baeldung/examples/common/AccountServiceImpl.java create mode 100644 guice/src/main/java/com/baeldung/examples/common/Address.java create mode 100644 guice/src/main/java/com/baeldung/examples/common/BookService.java create mode 100644 guice/src/main/java/com/baeldung/examples/common/BookServiceImpl.java create mode 100644 guice/src/main/java/com/baeldung/examples/guice/Employee.java create mode 100644 guice/src/main/java/com/baeldung/examples/guice/Foo.java create mode 100644 guice/src/main/java/com/baeldung/examples/guice/FooGenerator.java create mode 100644 guice/src/main/java/com/baeldung/examples/guice/GuiceUser.java create mode 100644 guice/src/main/java/com/baeldung/examples/guice/GuiceUserService.java create mode 100644 guice/src/main/java/com/baeldung/examples/guice/Person.java create mode 100644 guice/src/main/java/com/baeldung/examples/guice/modules/GuiceModule.java create mode 100644 guice/src/main/java/com/baeldung/examples/spring/AppConfig.java create mode 100644 guice/src/main/java/com/baeldung/examples/spring/SpringUser.java create mode 100644 guice/src/main/java/com/baeldung/examples/spring/Student.java create mode 100644 guice/src/main/java/com/baeldung/examples/spring/UserService.java create mode 100644 guice/src/test/java/com/baeldung/examples/GuiceTests.java create mode 100644 guice/src/test/java/com/baeldung/examples/SpringTests.java diff --git a/guice/src/main/java/com/baeldung/examples/common/Account.java b/guice/src/main/java/com/baeldung/examples/common/Account.java new file mode 100644 index 0000000000..09a9d80b6a --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/Account.java @@ -0,0 +1,27 @@ +package com.baeldung.examples.common; + +import org.springframework.stereotype.Component; + +@Component +public class Account { + + private String accountNumber; + private String type; + + public String getAccountNumber() { + return accountNumber; + } + + public void setAccountNumber(String accountNumber) { + this.accountNumber = accountNumber; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AccountService.java b/guice/src/main/java/com/baeldung/examples/common/AccountService.java new file mode 100644 index 0000000000..d6a7fe1d11 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AccountService.java @@ -0,0 +1,8 @@ +package com.baeldung.examples.common; + +import java.util.List; + +public interface AccountService { + public List listAccountTypes(); + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/AccountServiceImpl.java b/guice/src/main/java/com/baeldung/examples/common/AccountServiceImpl.java new file mode 100644 index 0000000000..9cecf021fe --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/AccountServiceImpl.java @@ -0,0 +1,15 @@ +package com.baeldung.examples.common; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.stereotype.Component; + +@Component +public class AccountServiceImpl implements AccountService { + + public List listAccountTypes() { + return Arrays.asList("Checking", "Saving"); + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/Address.java b/guice/src/main/java/com/baeldung/examples/common/Address.java new file mode 100644 index 0000000000..3b07c47011 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/Address.java @@ -0,0 +1,35 @@ +package com.baeldung.examples.common; + +import org.springframework.stereotype.Component; + +@Component +public class Address { + private String city; + private String state; + private String county; + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getCounty() { + return county; + } + + public void setCounty(String county) { + this.county = county; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/BookService.java b/guice/src/main/java/com/baeldung/examples/common/BookService.java new file mode 100644 index 0000000000..3aca9d90d7 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/BookService.java @@ -0,0 +1,9 @@ +package com.baeldung.examples.common; + +import java.util.List; + +public interface BookService { + + public List findBestSellerBooks(); + +} diff --git a/guice/src/main/java/com/baeldung/examples/common/BookServiceImpl.java b/guice/src/main/java/com/baeldung/examples/common/BookServiceImpl.java new file mode 100644 index 0000000000..b5499c678d --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/BookServiceImpl.java @@ -0,0 +1,12 @@ +package com.baeldung.examples.common; + +import java.util.Arrays; +import java.util.List; + +public class BookServiceImpl implements BookService { + + public List findBestSellerBooks() { + return Arrays.asList("Harry Potter", "Lord of The Rings"); + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/Employee.java b/guice/src/main/java/com/baeldung/examples/guice/Employee.java new file mode 100644 index 0000000000..b85d251a05 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/Employee.java @@ -0,0 +1,32 @@ +package com.baeldung.examples.guice; + +import com.google.inject.Inject; + +public class Employee { + + private String firstName; + private String lastName; + + @Inject + public Employee(String firstName) { + this.firstName = firstName; + this.lastName = "Default"; + } + + 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/guice/src/main/java/com/baeldung/examples/guice/Foo.java b/guice/src/main/java/com/baeldung/examples/guice/Foo.java new file mode 100644 index 0000000000..a4f22a6f69 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/Foo.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.guice; + + +public class Foo { +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/FooGenerator.java b/guice/src/main/java/com/baeldung/examples/guice/FooGenerator.java new file mode 100644 index 0000000000..b2d3309d0e --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/FooGenerator.java @@ -0,0 +1,11 @@ +package com.baeldung.examples.guice; + +import org.springframework.lang.Nullable; + +import com.google.inject.Inject; + +public class FooGenerator { + @Inject + public FooGenerator(@Nullable Foo foo) { + } +} \ No newline at end of file diff --git a/guice/src/main/java/com/baeldung/examples/guice/GuiceUser.java b/guice/src/main/java/com/baeldung/examples/guice/GuiceUser.java new file mode 100644 index 0000000000..df438add5b --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/GuiceUser.java @@ -0,0 +1,32 @@ +package com.baeldung.examples.guice; + +import com.baeldung.examples.common.Account; +import com.baeldung.examples.common.Address; +import com.google.inject.Inject; + +public class GuiceUser { + + @Inject + private Account account; + + private Address address; + + public Account getAccount() { + return account; + } + + public void setAccount(Account account) { + this.account = account; + } + + public Address getAddress() { + return address; + } + + @Inject + public void setAddress(Address address) { + this.address = address; + address.setCity("Default"); + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/GuiceUserService.java b/guice/src/main/java/com/baeldung/examples/guice/GuiceUserService.java new file mode 100644 index 0000000000..18cb076661 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/GuiceUserService.java @@ -0,0 +1,19 @@ +package com.baeldung.examples.guice; + +import com.baeldung.examples.common.AccountService; +import com.google.inject.Inject; + +public class GuiceUserService { + + @Inject + private AccountService accountService; + + public AccountService getAccountService() { + return accountService; + } + + public void setAccountService(AccountService accountService) { + this.accountService = accountService; + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/Person.java b/guice/src/main/java/com/baeldung/examples/guice/Person.java new file mode 100644 index 0000000000..45ee5f4b89 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/Person.java @@ -0,0 +1,39 @@ +package com.baeldung.examples.guice; + +import com.baeldung.examples.common.Address; +import com.google.inject.Inject; + +public class Person { + private String firstName; + + private String lastName; + + private Address address; + + 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 Address getAddress() { + return address; + } + + @Inject + public void setAddress(Address address) { + this.address = address; + address.setCity("Default"); + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/modules/GuiceModule.java b/guice/src/main/java/com/baeldung/examples/guice/modules/GuiceModule.java new file mode 100644 index 0000000000..44b566240e --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/modules/GuiceModule.java @@ -0,0 +1,47 @@ +package com.baeldung.examples.guice.modules; + +import com.baeldung.examples.common.AccountService; +import com.baeldung.examples.common.AccountServiceImpl; +import com.baeldung.examples.common.BookService; +import com.baeldung.examples.common.BookServiceImpl; +import com.baeldung.examples.guice.Foo; +import com.baeldung.examples.guice.Person; +import com.google.inject.AbstractModule; +import com.google.inject.Provider; +import com.google.inject.Provides; + +public class GuiceModule extends AbstractModule { + + @Override + protected void configure() { + try { + bind(AccountService.class).to(AccountServiceImpl.class); + bind(Foo.class).toProvider(new Provider() { + public Foo get() { + return null; + } + }); + + bind(Person.class).toConstructor(Person.class.getConstructor()); + // bind(Person.class).toProvider(new Provider() { + // public Person get() { + // Person p = new Person(); + // return p; + // } + // }); + } catch (NoSuchMethodException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + @Provides + public BookService bookServiceGenerator() { + return new BookServiceImpl(); + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/spring/AppConfig.java b/guice/src/main/java/com/baeldung/examples/spring/AppConfig.java new file mode 100644 index 0000000000..e5b6648e0d --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/spring/AppConfig.java @@ -0,0 +1,19 @@ +package com.baeldung.examples.spring; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import com.baeldung.examples.common.BookService; +import com.baeldung.examples.common.BookServiceImpl; + +@Configuration +@ComponentScan("com.baeldung.examples") +public class AppConfig { + + @Bean + public BookService bookServiceGenerator() { + return new BookServiceImpl(); + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/spring/SpringUser.java b/guice/src/main/java/com/baeldung/examples/spring/SpringUser.java new file mode 100644 index 0000000000..ba6aaab09b --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/spring/SpringUser.java @@ -0,0 +1,35 @@ +package com.baeldung.examples.spring; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.baeldung.examples.common.Account; +import com.baeldung.examples.common.Address; + +@Component +public class SpringUser { + + @Autowired + private Account account; + + private Address address; + + public Account getAccount() { + return account; + } + + public void setAccount(Account account) { + this.account = account; + } + + public Address getAddress() { + return address; + } + + @Autowired + public void setAddress(Address address) { + this.address = address; + address.setCity("Default"); + } + +} diff --git a/guice/src/main/java/com/baeldung/examples/spring/Student.java b/guice/src/main/java/com/baeldung/examples/spring/Student.java new file mode 100644 index 0000000000..d8b61a91ef --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/spring/Student.java @@ -0,0 +1,34 @@ +package com.baeldung.examples.spring; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class Student { + private String firstName; + private String lastName; + + @Autowired + public Student(@Value("Default") String firstName, @Value("Default") 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/guice/src/main/java/com/baeldung/examples/spring/UserService.java b/guice/src/main/java/com/baeldung/examples/spring/UserService.java new file mode 100644 index 0000000000..91b95c100d --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/spring/UserService.java @@ -0,0 +1,22 @@ +package com.baeldung.examples.spring; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.baeldung.examples.common.AccountService; + +@Component +public class UserService { + + @Autowired + private AccountService accountService; + + public AccountService getAccountService() { + return accountService; + } + + public void setAccountService(AccountService accountService) { + this.accountService = accountService; + } + +} diff --git a/guice/src/test/java/com/baeldung/examples/GuiceTests.java b/guice/src/test/java/com/baeldung/examples/GuiceTests.java new file mode 100644 index 0000000000..b87289a1a4 --- /dev/null +++ b/guice/src/test/java/com/baeldung/examples/GuiceTests.java @@ -0,0 +1,72 @@ +package com.baeldung.examples; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +import com.baeldung.examples.common.BookService; +import com.baeldung.examples.guice.Employee; +import com.baeldung.examples.guice.FooGenerator; +import com.baeldung.examples.guice.GuiceUser; +import com.baeldung.examples.guice.GuiceUserService; +import com.baeldung.examples.guice.Person; +import com.baeldung.examples.guice.modules.GuiceModule; +import com.google.inject.Guice; +import com.google.inject.Injector; + +public class GuiceTests { + + @Test + public void givenAccountFieldInjectedInGuiceUser_WhenGetAccountInvoked_ThenReturnValueIsNotNull() { + Injector injector = Guice.createInjector(new GuiceModule()); + GuiceUser guiceUser = injector.getInstance(GuiceUser.class); + assertNotNull(guiceUser.getAccount()); + } + + @Test + public void givenAccountServiceInjectedInGuiceUserService_WhenGetAccountServiceInvoked_ThenReturnValueIsNotNull() { + Injector injector = Guice.createInjector(new GuiceModule()); + GuiceUserService guiceUserService = injector.getInstance(GuiceUserService.class); + assertNotNull(guiceUserService.getAccountService()); + } + + @Test + public void givenBookServiceIsRegisteredInModule_WhenBookServiceIsInjected_ThenReturnValueIsNotNull() { + Injector injector = Guice.createInjector(new GuiceModule()); + BookService bookService = injector.getInstance(BookService.class); + assertNotNull(bookService); + } + + @Test + public void givenFooGeneratorConstructorParameterIsNotNullable_WhenFooGeneratorIsInjected_ThenTestFailsByProvisionException() { + Injector injector = Guice.createInjector(new GuiceModule()); + FooGenerator fooGenerator = injector.getInstance(FooGenerator.class); + assertNotNull(fooGenerator); + } + + @Test + public void givenMultipleBindingsForPerson_WhenPersonIsInjected_ThenTestFailsByProvisionException() { + Injector injector = Guice.createInjector(new GuiceModule()); + Person person = injector.getInstance(Person.class); + assertNotNull(person); + } + + @Test + public void givenEmployeeConstructorAnnotatedByInject_WhenEmployeeIsInjected_ThenInstanceWillBeCreatedFromTheConstructor() { + Injector injector = Guice.createInjector(new GuiceModule()); + Employee employee = injector.getInstance(Employee.class); + assertNotNull(employee); + assertEquals("Default", employee.getLastName()); + } + + @Test + public void givenAddressAutowiredToGuiceUserBySetterInjection_WhenGuiceUserIsInjected_ThenAddressInitializedByTheSetter() { + Injector injector = Guice.createInjector(new GuiceModule()); + GuiceUser guiceUser = injector.getInstance(GuiceUser.class); + assertNotNull(guiceUser); + assertNotNull(guiceUser.getAddress()); + assertEquals("Default", guiceUser.getAddress().getCity()); + } + +} diff --git a/guice/src/test/java/com/baeldung/examples/SpringTests.java b/guice/src/test/java/com/baeldung/examples/SpringTests.java new file mode 100644 index 0000000000..327e409cc1 --- /dev/null +++ b/guice/src/test/java/com/baeldung/examples/SpringTests.java @@ -0,0 +1,58 @@ +package com.baeldung.examples; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +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.SpringRunner; + +import com.baeldung.examples.common.BookService; +import com.baeldung.examples.spring.AppConfig; +import com.baeldung.examples.spring.SpringUser; +import com.baeldung.examples.spring.Student; +import com.baeldung.examples.spring.UserService; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = { AppConfig.class }) +public class SpringTests { + @Autowired + ApplicationContext context; + + @Test + public void givenAccountFieldAutowiredToSpringUser_WhenGetAccountInvoked_ThenReturnValueIsNotNull() { + SpringUser springUser = context.getBean(SpringUser.class); + assertNotNull(springUser.getAccount()); + } + + @Test + public void givenAccountServiceFieldAutowiredToUserService_WhenGetAccountServiceInvoked_ThenReturnValueIsNotNull() { + UserService userService = context.getBean(UserService.class); + assertNotNull(userService.getAccountService()); + } + + @Test + public void givenBookServiceIsRegisteredAsBeanInContext_WhenBookServiceIsRetrievedFromContext_ThenReturnValueIsNotNull() { + BookService bookService = context.getBean(BookService.class); + assertNotNull(bookService); + } + + @Test + public void givenStudentConstructorAnnotatedByAutowired_WhenStudentIsRetrievedFromContext_ThenInstanceWillBeCreatedFromTheConstructor() { + Student student = context.getBean(Student.class); + assertNotNull(student); + assertEquals("Default", student.getFirstName()); + assertEquals("Default", student.getLastName()); + } + + @Test + public void givenAddressAutowiredToSpringUserBySetterInjection_WhenSpringUserRetrievedFromContext_ThenAddressInitializedByTheSetter() { + SpringUser springUser = context.getBean(SpringUser.class); + assertNotNull(springUser.getAddress()); + assertEquals("Default", springUser.getAddress().getCity()); + } + +} From acf8034d9352feded9a4e442e654ae517c182e10 Mon Sep 17 00:00:00 2001 From: codehunter34 Date: Wed, 26 Dec 2018 23:58:04 -0500 Subject: [PATCH 002/190] BAEL-2399: Guice vs Spring - Dependency Injection --- guice/pom.xml | 62 ++++++++++++------- .../{GuiceTests.java => GuiceUnitTest.java} | 2 +- .../{SpringTests.java => SpringUnitTest.java} | 2 +- 3 files changed, 41 insertions(+), 25 deletions(-) rename guice/src/test/java/com/baeldung/examples/{GuiceTests.java => GuiceUnitTest.java} (96%) rename guice/src/test/java/com/baeldung/examples/{SpringTests.java => SpringUnitTest.java} (96%) diff --git a/guice/pom.xml b/guice/pom.xml index f3e7873245..54532bc992 100644 --- a/guice/pom.xml +++ b/guice/pom.xml @@ -1,29 +1,45 @@ - - 4.0.0 - com.baeldung.examples.guice - guice - 1.0-SNAPSHOT - jar - guice + + 4.0.0 + com.baeldung.examples.guice + guice + 1.0-SNAPSHOT + jar + guice - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + - - - com.google.inject - guice - ${guice.version} - - + + + com.google.inject + guice + ${guice.version} + - - 4.1.0 - + + org.springframework + spring-context + ${spring.version} + + + + org.springframework + spring-test + ${springtest.version} + test + + + + + 4.1.0 + 5.1.3.RELEASE + 5.1.3.RELEASE + diff --git a/guice/src/test/java/com/baeldung/examples/GuiceTests.java b/guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java similarity index 96% rename from guice/src/test/java/com/baeldung/examples/GuiceTests.java rename to guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java index b87289a1a4..ebc35de405 100644 --- a/guice/src/test/java/com/baeldung/examples/GuiceTests.java +++ b/guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java @@ -15,7 +15,7 @@ import com.baeldung.examples.guice.modules.GuiceModule; import com.google.inject.Guice; import com.google.inject.Injector; -public class GuiceTests { +public class GuiceUnitTest { @Test public void givenAccountFieldInjectedInGuiceUser_WhenGetAccountInvoked_ThenReturnValueIsNotNull() { diff --git a/guice/src/test/java/com/baeldung/examples/SpringTests.java b/guice/src/test/java/com/baeldung/examples/SpringUnitTest.java similarity index 96% rename from guice/src/test/java/com/baeldung/examples/SpringTests.java rename to guice/src/test/java/com/baeldung/examples/SpringUnitTest.java index 327e409cc1..0bd6770909 100644 --- a/guice/src/test/java/com/baeldung/examples/SpringTests.java +++ b/guice/src/test/java/com/baeldung/examples/SpringUnitTest.java @@ -18,7 +18,7 @@ import com.baeldung.examples.spring.UserService; @RunWith(SpringRunner.class) @ContextConfiguration(classes = { AppConfig.class }) -public class SpringTests { +public class SpringUnitTest { @Autowired ApplicationContext context; From aeba601c1f5bd14ad061a18c69babe92db97735d Mon Sep 17 00:00:00 2001 From: codehunter34 Date: Wed, 26 Dec 2018 23:58:04 -0500 Subject: [PATCH 003/190] BAEL-2399: Guice vs Spring - Dependency Injection --- guice/pom.xml | 62 ++++++++++++------- .../{GuiceTests.java => GuiceUnitTest.java} | 2 +- .../{SpringTests.java => SpringUnitTest.java} | 2 +- 3 files changed, 41 insertions(+), 25 deletions(-) rename guice/src/test/java/com/baeldung/examples/{GuiceTests.java => GuiceUnitTest.java} (96%) rename guice/src/test/java/com/baeldung/examples/{SpringTests.java => SpringUnitTest.java} (96%) diff --git a/guice/pom.xml b/guice/pom.xml index f3e7873245..54532bc992 100644 --- a/guice/pom.xml +++ b/guice/pom.xml @@ -1,29 +1,45 @@ - - 4.0.0 - com.baeldung.examples.guice - guice - 1.0-SNAPSHOT - jar - guice + + 4.0.0 + com.baeldung.examples.guice + guice + 1.0-SNAPSHOT + jar + guice - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + - - - com.google.inject - guice - ${guice.version} - - + + + com.google.inject + guice + ${guice.version} + - - 4.1.0 - + + org.springframework + spring-context + ${spring.version} + + + + org.springframework + spring-test + ${springtest.version} + test + + + + + 4.1.0 + 5.1.3.RELEASE + 5.1.3.RELEASE + diff --git a/guice/src/test/java/com/baeldung/examples/GuiceTests.java b/guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java similarity index 96% rename from guice/src/test/java/com/baeldung/examples/GuiceTests.java rename to guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java index b87289a1a4..ebc35de405 100644 --- a/guice/src/test/java/com/baeldung/examples/GuiceTests.java +++ b/guice/src/test/java/com/baeldung/examples/GuiceUnitTest.java @@ -15,7 +15,7 @@ import com.baeldung.examples.guice.modules.GuiceModule; import com.google.inject.Guice; import com.google.inject.Injector; -public class GuiceTests { +public class GuiceUnitTest { @Test public void givenAccountFieldInjectedInGuiceUser_WhenGetAccountInvoked_ThenReturnValueIsNotNull() { diff --git a/guice/src/test/java/com/baeldung/examples/SpringTests.java b/guice/src/test/java/com/baeldung/examples/SpringUnitTest.java similarity index 96% rename from guice/src/test/java/com/baeldung/examples/SpringTests.java rename to guice/src/test/java/com/baeldung/examples/SpringUnitTest.java index 327e409cc1..0bd6770909 100644 --- a/guice/src/test/java/com/baeldung/examples/SpringTests.java +++ b/guice/src/test/java/com/baeldung/examples/SpringUnitTest.java @@ -18,7 +18,7 @@ import com.baeldung.examples.spring.UserService; @RunWith(SpringRunner.class) @ContextConfiguration(classes = { AppConfig.class }) -public class SpringTests { +public class SpringUnitTest { @Autowired ApplicationContext context; From bd63df8caf05acee9307f84f94c83a304cbc401b Mon Sep 17 00:00:00 2001 From: codehunter34 Date: Tue, 1 Jan 2019 02:46:06 -0500 Subject: [PATCH 004/190] BAEL-2399: Guice vs Spring - Dependency Injection --- .../main/java/com/baeldung/examples/common/PersonDao.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 guice/src/main/java/com/baeldung/examples/common/PersonDao.java diff --git a/guice/src/main/java/com/baeldung/examples/common/PersonDao.java b/guice/src/main/java/com/baeldung/examples/common/PersonDao.java new file mode 100644 index 0000000000..980fee0252 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/PersonDao.java @@ -0,0 +1,5 @@ +package com.baeldung.examples.common; + +public interface PersonDao { + +} From d740cb2da09e0dfeef3ae166473785aa92f3a443 Mon Sep 17 00:00:00 2001 From: codehunter34 Date: Tue, 1 Jan 2019 02:46:06 -0500 Subject: [PATCH 005/190] BAEL-2399: Guice vs Spring - Dependency Injection --- .../java/com/baeldung/examples/common/PersonDaoImpl.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java diff --git a/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java b/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java new file mode 100644 index 0000000000..971db5aa87 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java @@ -0,0 +1,8 @@ +package com.baeldung.examples.common; + +import org.springframework.stereotype.Component; + +@Component +public class PersonDaoImpl implements PersonDao { + +} \ No newline at end of file From 3ac96662fc8d9f83936f21fc688a13ffd648af40 Mon Sep 17 00:00:00 2001 From: codehunter34 Date: Tue, 1 Jan 2019 02:46:06 -0500 Subject: [PATCH 006/190] BAEL-2399: Guice vs Spring - Dependency Injection --- .../examples/common/PersonDaoImpl.java | 8 ++++++++ .../examples/guice/GuicePersonService.java | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java create mode 100644 guice/src/main/java/com/baeldung/examples/guice/GuicePersonService.java diff --git a/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java b/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java new file mode 100644 index 0000000000..971db5aa87 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/common/PersonDaoImpl.java @@ -0,0 +1,8 @@ +package com.baeldung.examples.common; + +import org.springframework.stereotype.Component; + +@Component +public class PersonDaoImpl implements PersonDao { + +} \ No newline at end of file diff --git a/guice/src/main/java/com/baeldung/examples/guice/GuicePersonService.java b/guice/src/main/java/com/baeldung/examples/guice/GuicePersonService.java new file mode 100644 index 0000000000..ce12e3e528 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/GuicePersonService.java @@ -0,0 +1,19 @@ +package com.baeldung.examples.guice; + +import com.baeldung.examples.common.PersonDao; +import com.google.inject.Inject; + +public class GuicePersonService { + + @Inject + private PersonDao personDao; + + public PersonDao getPersonDao() { + return personDao; + } + + public void setPersonDao(PersonDao personDao) { + this.personDao = personDao; + } + +} From 66016332f82446179aaae1ed5bd41c15b26773c0 Mon Sep 17 00:00:00 2001 From: Mikhail Chugunov Date: Wed, 2 Jan 2019 19:09:00 +0300 Subject: [PATCH 007/190] BAEL-2475: Add sample code and tests --- .../immutable/MaritalAwarePerson.java | 58 +++++++++++++++++++ .../deserialization/immutable/Person.java | 24 ++++++++ ...mmutableObjectDeserializationUnitTest.java | 40 +++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/MaritalAwarePerson.java create mode 100644 jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java create mode 100644 jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/MaritalAwarePerson.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/MaritalAwarePerson.java new file mode 100644 index 0000000000..cb593b3bb7 --- /dev/null +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/MaritalAwarePerson.java @@ -0,0 +1,58 @@ +package com.baeldung.jackson.deserialization.immutable; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; + +@JsonDeserialize(builder = MaritalAwarePerson.Builder.class) +public class MaritalAwarePerson { + + private final String name; + private final int age; + private final Boolean married; + + private MaritalAwarePerson(String name, int age, Boolean married) { + this.name = name; + this.age = age; + this.married = married; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + public Boolean getMarried() { + return married; + } + + @JsonPOJOBuilder + static class Builder { + String name; + int age; + Boolean married; + + Builder withName(String name) { + this.name = name; + return this; + } + + Builder withAge(int age) { + this.age = age; + return this; + } + + Builder withMarried(boolean married) { + this.married = married; + return this; + } + + public MaritalAwarePerson build() { + return new MaritalAwarePerson(name, age, married); + } + + + } +} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java new file mode 100644 index 0000000000..0214f93ca9 --- /dev/null +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java @@ -0,0 +1,24 @@ +package com.baeldung.jackson.deserialization.immutable; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Person { + + private final String name; + private final int age; + + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + public Person(@JsonProperty("name") String name, @JsonProperty("age") int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java new file mode 100644 index 0000000000..348ece4a09 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.jackson.deserialization.immutable; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.*; + +public class ImmutableObjectDeserializationUnitTest { + + @Test + public void testPublicConstructor() throws IOException { + final String json = "{\"name\":\"Frank\",\"age\":50}"; + Person person = new ObjectMapper().readValue(json, Person.class); + + assertEquals("Frank", person.getName()); + assertEquals(50, person.getAge()); + } + + @Test + public void testBuilderNullField() throws IOException { + final String json = "{\"name\":\"Frank\",\"age\":50}"; + MaritalAwarePerson person = new ObjectMapper().readValue(json, MaritalAwarePerson.class); + + assertEquals("Frank", person.getName()); + assertEquals(50, person.getAge()); + assertNull(person.getMarried()); + } + + @Test + public void testBuilderAllFields() throws IOException { + final String json = "{\"name\":\"Frank\",\"age\":50,\"married\":true}"; + MaritalAwarePerson person = new ObjectMapper().readValue(json, MaritalAwarePerson.class); + + assertEquals("Frank", person.getName()); + assertEquals(50, person.getAge()); + assertTrue(person.getMarried()); + } +} From 2e436ce3e8e31c6791257f624b9661b4ba3368b3 Mon Sep 17 00:00:00 2001 From: Mikhail Chugunov Date: Wed, 2 Jan 2019 19:14:09 +0300 Subject: [PATCH 008/190] BAEL-2475: Rename tests --- .../immutable/ImmutableObjectDeserializationUnitTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java index 348ece4a09..5c33a2da26 100644 --- a/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java @@ -10,7 +10,7 @@ import static org.junit.Assert.*; public class ImmutableObjectDeserializationUnitTest { @Test - public void testPublicConstructor() throws IOException { + public void whenPublicConstructorIsUsed_thenObjectIsDeserialized() throws IOException { final String json = "{\"name\":\"Frank\",\"age\":50}"; Person person = new ObjectMapper().readValue(json, Person.class); @@ -19,7 +19,7 @@ public class ImmutableObjectDeserializationUnitTest { } @Test - public void testBuilderNullField() throws IOException { + public void whenBuilderIsUsedAndFieldIsNull_thenObjectIsDeserialized() throws IOException { final String json = "{\"name\":\"Frank\",\"age\":50}"; MaritalAwarePerson person = new ObjectMapper().readValue(json, MaritalAwarePerson.class); @@ -29,7 +29,7 @@ public class ImmutableObjectDeserializationUnitTest { } @Test - public void testBuilderAllFields() throws IOException { + public void whenBuilderIsUsedAndAllFieldsPresent_thenObjectIsDeserialized() throws IOException { final String json = "{\"name\":\"Frank\",\"age\":50,\"married\":true}"; MaritalAwarePerson person = new ObjectMapper().readValue(json, MaritalAwarePerson.class); From e89c0948d8b33be57cecf099b189748c2dc7cc29 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sat, 5 Jan 2019 19:58:09 +0530 Subject: [PATCH 009/190] [BAEL-11415] - Initial commit with sparing-kafka version and topic creation configuration onstatup --- spring-kafka/pom.xml | 2 +- .../spring/kafka/KafkaApplication.java | 18 +++++- .../spring/kafka/KafkaTopicConfig.java | 57 +++++++++++++++++++ .../org/baeldung/SpringContextLiveTest.java | 17 ++++++ 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java create mode 100644 spring-kafka/src/test/java/org/baeldung/SpringContextLiveTest.java diff --git a/spring-kafka/pom.xml b/spring-kafka/pom.xml index 5c370880b4..b76d4f10c0 100644 --- a/spring-kafka/pom.xml +++ b/spring-kafka/pom.xml @@ -33,7 +33,7 @@ - 1.1.3.RELEASE + 2.2.2.RELEASE 2.9.7 diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java index 4ee7f40335..b313eafdb9 100644 --- a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java @@ -13,8 +13,11 @@ import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.annotation.TopicPartition; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.kafka.support.KafkaHeaders; +import org.springframework.kafka.support.SendResult; import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.util.concurrent.ListenableFuture; +import org.springframework.util.concurrent.ListenableFutureCallback; @SpringBootApplication public class KafkaApplication { @@ -98,7 +101,20 @@ public class KafkaApplication { private String greetingTopicName; public void sendMessage(String message) { - kafkaTemplate.send(topicName, message); + + ListenableFuture> future = kafkaTemplate.send(topicName, message); + + future.addCallback(new ListenableFutureCallback>() { + + @Override + public void onSuccess(SendResult result) { + System.out.println("Sent message=[" + message + "] with offset=[" + result.getRecordMetadata().offset() + "]"); + } + @Override + public void onFailure(Throwable ex) { + System.out.println("Unable to send message=[" + message + "] due to : " + ex.getMessage()); + } + }); } public void sendMessageToPartion(String message, int partition) { diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java new file mode 100644 index 0000000000..a3426e78a3 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java @@ -0,0 +1,57 @@ +package com.baeldung.spring.kafka; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.kafka.clients.admin.AdminClientConfig; +import org.apache.kafka.clients.admin.NewTopic; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.core.KafkaAdmin; + +@Configuration +public class KafkaTopicConfig { + + @Value(value = "${kafka.bootstrapAddress}") + private String bootstrapAddress; + + @Value(value = "${message.topic.name}") + private String topicName; + + @Value(value = "${partitioned.topic.name}") + private String partionedTopicName; + + @Value(value = "${filtered.topic.name}") + private String filteredTopicName; + + @Value(value = "${greeting.topic.name}") + private String greetingTopicName; + + @Bean + public KafkaAdmin kafkaAdmin() { + Map configs = new HashMap<>(); + configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); + return new KafkaAdmin(configs); + } + + @Bean + public NewTopic topic1() { + return new NewTopic(topicName, 1, (short) 1); + } + + @Bean + public NewTopic topic2() { + return new NewTopic(partionedTopicName, 6, (short) 1); + } + + @Bean + public NewTopic topic3() { + return new NewTopic(filteredTopicName, 1, (short) 1); + } + + @Bean + public NewTopic topic4() { + return new NewTopic(greetingTopicName, 1, (short) 1); + } +} diff --git a/spring-kafka/src/test/java/org/baeldung/SpringContextLiveTest.java b/spring-kafka/src/test/java/org/baeldung/SpringContextLiveTest.java new file mode 100644 index 0000000000..d8fb3131f5 --- /dev/null +++ b/spring-kafka/src/test/java/org/baeldung/SpringContextLiveTest.java @@ -0,0 +1,17 @@ +package org.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.spring.kafka.KafkaApplication; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = KafkaApplication.class) +public class SpringContextLiveTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} From 115a52a124ce455bbe1c844a6cea93ed3d56cae8 Mon Sep 17 00:00:00 2001 From: Urvy Agrawal Date: Mon, 7 Jan 2019 22:03:52 +0530 Subject: [PATCH 010/190] Adding files for BAEL-2543 --- .../java/com/baeldung/keyword/Circle.java | 4 ++ .../main/java/com/baeldung/keyword/Ring.java | 4 ++ .../main/java/com/baeldung/keyword/Round.java | 4 ++ .../main/java/com/baeldung/keyword/Shape.java | 4 ++ .../java/com/baeldung/keyword/Triangle.java | 4 ++ .../keyword/test/InstanceOfUnitTest.java | 49 +++++++++++++++++++ 6 files changed, 69 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/keyword/Circle.java create mode 100644 core-java/src/main/java/com/baeldung/keyword/Ring.java create mode 100644 core-java/src/main/java/com/baeldung/keyword/Round.java create mode 100644 core-java/src/main/java/com/baeldung/keyword/Shape.java create mode 100644 core-java/src/main/java/com/baeldung/keyword/Triangle.java create mode 100644 core-java/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java diff --git a/core-java/src/main/java/com/baeldung/keyword/Circle.java b/core-java/src/main/java/com/baeldung/keyword/Circle.java new file mode 100644 index 0000000000..4ec91d1b8a --- /dev/null +++ b/core-java/src/main/java/com/baeldung/keyword/Circle.java @@ -0,0 +1,4 @@ +package com.baeldung.keyword; + +public class Circle extends Round implements Shape { +} diff --git a/core-java/src/main/java/com/baeldung/keyword/Ring.java b/core-java/src/main/java/com/baeldung/keyword/Ring.java new file mode 100644 index 0000000000..99873f9640 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/keyword/Ring.java @@ -0,0 +1,4 @@ +package com.baeldung.keyword; + +public class Ring extends Round { +} diff --git a/core-java/src/main/java/com/baeldung/keyword/Round.java b/core-java/src/main/java/com/baeldung/keyword/Round.java new file mode 100644 index 0000000000..0e2cc2c8c7 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/keyword/Round.java @@ -0,0 +1,4 @@ +package com.baeldung.keyword; + +public class Round { +} diff --git a/core-java/src/main/java/com/baeldung/keyword/Shape.java b/core-java/src/main/java/com/baeldung/keyword/Shape.java new file mode 100644 index 0000000000..8d00c165a3 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/keyword/Shape.java @@ -0,0 +1,4 @@ +package com.baeldung.keyword; + +public interface Shape { +} diff --git a/core-java/src/main/java/com/baeldung/keyword/Triangle.java b/core-java/src/main/java/com/baeldung/keyword/Triangle.java new file mode 100644 index 0000000000..406b8f23e5 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/keyword/Triangle.java @@ -0,0 +1,4 @@ +package com.baeldung.keyword; + +public class Triangle implements Shape { +} diff --git a/core-java/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java b/core-java/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java new file mode 100644 index 0000000000..fbeec3a077 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.keyword.test; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import com.baeldung.keyword.Circle; +import com.baeldung.keyword.Ring; +import com.baeldung.keyword.Round; +import com.baeldung.keyword.Shape; +import com.baeldung.keyword.Triangle; + +public class InstanceOfUnitTest { + + @Test + public void giveWhenInstanceIsCorrect_thenReturnTrue() { + Ring ring = new Ring(); + Assert.assertTrue("ring is instance of Round ", ring instanceof Round); + } + + @Test + public void giveWhenObjectIsInstanceOfType_thenReturnTrue() { + Circle circle = new Circle(); + Assert.assertTrue("circle is instance of Circle ", circle instanceof Circle); + } + + + @Test + public void giveWhenInstanceIsOfSubtype_thenReturnTrue() { + Circle circle = new Circle(); + Assert.assertTrue("circle is instance of Round", circle instanceof Round); + } + + @Test + public void giveWhenTypeIsInterface_thenReturnTrue() { + Circle circle = new Circle(); + Assert.assertTrue("circle is instance of Shape", circle instanceof Shape); + } + + @Test + public void giveWhenInstanceValueIsNull_thenReturnFalse() { + Circle circle = null; + Assert.assertFalse("circle is instance of Round", circle instanceof Round); + } + + @Test + public void giveWhenComparingClassInDiffHierarchy_thenCompilationError() { + // Assert.assertFalse("circle is instance of Triangle", circle instanceof Triangle); + } +} From ea1a4678929221680fcf15005ff9c1cfad775bae Mon Sep 17 00:00:00 2001 From: eric-martin Date: Mon, 7 Jan 2019 20:32:55 -0600 Subject: [PATCH 011/190] BAEL-2386: Moved FlightRecorder from core-java to core-java-perf --- .../src/main/java/com/baeldung/flightrecorder/FlightRecorder.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {core-java => core-java-perf}/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java (100%) diff --git a/core-java/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java b/core-java-perf/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java similarity index 100% rename from core-java/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java rename to core-java-perf/src/main/java/com/baeldung/flightrecorder/FlightRecorder.java From ffcb8f586625f20ada94658ebeba6cd92e965b80 Mon Sep 17 00:00:00 2001 From: Graham Cox Date: Tue, 8 Jan 2019 10:44:18 +0000 Subject: [PATCH 012/190] Kovert (#6092) * Kovert examples * Moved the Kovert examples to kotlin-libraries --- kotlin-libraries/pom.xml | 19 ++++- .../com/baeldung/kovert/AnnotatedServer.kt | 73 ++++++++++++++++++ .../kotlin/com/baeldung/kovert/ErrorServer.kt | 75 ++++++++++++++++++ .../kotlin/com/baeldung/kovert/JsonServer.kt | 76 +++++++++++++++++++ .../kotlin/com/baeldung/kovert/NoopServer.kt | 57 ++++++++++++++ .../com/baeldung/kovert/SecuredServer.kt | 68 +++++++++++++++++ .../com/baeldung/kovert/SimpleServer.kt | 65 ++++++++++++++++ .../src/main/resources/kovert.conf | 15 ++++ 8 files changed, 447 insertions(+), 1 deletion(-) create mode 100644 kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt create mode 100644 kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt create mode 100644 kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt create mode 100644 kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt create mode 100644 kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt create mode 100644 kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt create mode 100644 kotlin-libraries/src/main/resources/kovert.conf diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml index ae77a9aa2d..507e5820d4 100644 --- a/kotlin-libraries/pom.xml +++ b/kotlin-libraries/pom.xml @@ -95,6 +95,23 @@ 0.7.3 + + uy.kohesive.kovert + kovert-vertx + [1.5.0,1.6.0) + + + nl.komponents.kovenant + kovenant + + + + + nl.komponents.kovenant + kovenant + 3.3.0 + pom + @@ -110,4 +127,4 @@ 0.10.4 - \ No newline at end of file + diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt new file mode 100644 index 0000000000..da2bbe4208 --- /dev/null +++ b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt @@ -0,0 +1,73 @@ +package com.baeldung.kovert + +import io.vertx.ext.web.Router +import io.vertx.ext.web.RoutingContext +import nl.komponents.kovenant.functional.bind +import org.kodein.di.Kodein +import org.kodein.di.conf.global +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import uy.klutter.config.typesafe.ClassResourceConfig +import uy.klutter.config.typesafe.ReferenceConfig +import uy.klutter.config.typesafe.kodein.importConfig +import uy.klutter.config.typesafe.loadConfig +import uy.klutter.vertx.kodein.KodeinVertx +import uy.kohesive.kovert.core.HttpVerb +import uy.kohesive.kovert.core.Location +import uy.kohesive.kovert.core.Verb +import uy.kohesive.kovert.core.VerbAlias +import uy.kohesive.kovert.vertx.bindController +import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx +import uy.kohesive.kovert.vertx.boot.KovertVerticle +import uy.kohesive.kovert.vertx.boot.KovertVerticleModule +import uy.kohesive.kovert.vertx.boot.KovertVertx + + +class AnnotatedServer { + companion object { + private val LOG: Logger = LoggerFactory.getLogger(AnnotatedServer::class.java) + + @JvmStatic + fun main(args: Array) { + AnnotatedServer().start() + } + } + + @VerbAlias("show", HttpVerb.GET) + class AnnotatedController { + fun RoutingContext.showStringById(id: String) = id + + @Verb(HttpVerb.GET) + @Location("/ping/:id") + fun RoutingContext.ping(id: String) = id + } + + fun start() { + Kodein.global.addImport(Kodein.Module { + importConfig(loadConfig(ClassResourceConfig("/kovert.conf", AnnotatedServer::class.java), ReferenceConfig())) { + import("kovert.vertx", KodeinKovertVertx.configModule) + import("kovert.server", KovertVerticleModule.configModule) + } + + // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j + import(KodeinVertx.moduleWithLoggingToSlf4j) + // Kovert boot + import(KodeinKovertVertx.module) + import(KovertVerticleModule.module) + }) + + val initControllers = fun Router.() { + bindController(AnnotatedController(), "api") + } + + // startup asynchronously... + KovertVertx.start() bind { vertx -> + KovertVerticle.deploy(vertx, routerInit = initControllers) + } success { deploymentId -> + LOG.warn("Deployment complete.") + } fail { error -> + LOG.error("Deployment failed!", error) + } + + } +} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt new file mode 100644 index 0000000000..a596391ed8 --- /dev/null +++ b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt @@ -0,0 +1,75 @@ +package com.baeldung.kovert + +import io.vertx.ext.web.Router +import io.vertx.ext.web.RoutingContext +import nl.komponents.kovenant.functional.bind +import org.kodein.di.Kodein +import org.kodein.di.conf.global +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import uy.klutter.config.typesafe.ClassResourceConfig +import uy.klutter.config.typesafe.ReferenceConfig +import uy.klutter.config.typesafe.kodein.importConfig +import uy.klutter.config.typesafe.loadConfig +import uy.klutter.vertx.kodein.KodeinVertx +import uy.kohesive.kovert.core.HttpErrorCode +import uy.kohesive.kovert.core.HttpErrorCodeWithBody +import uy.kohesive.kovert.core.HttpErrorForbidden +import uy.kohesive.kovert.vertx.bindController +import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx +import uy.kohesive.kovert.vertx.boot.KovertVerticle +import uy.kohesive.kovert.vertx.boot.KovertVerticleModule +import uy.kohesive.kovert.vertx.boot.KovertVertx + + +class ErrorServer { + companion object { + private val LOG: Logger = LoggerFactory.getLogger(ErrorServer::class.java) + + @JvmStatic + fun main(args: Array) { + ErrorServer().start() + } + } + + class ErrorController { + fun RoutingContext.getForbidden() { + throw HttpErrorForbidden() + } + fun RoutingContext.getError() { + throw HttpErrorCode("Something went wrong", 590) + } + fun RoutingContext.getErrorbody() { + throw HttpErrorCodeWithBody("Something went wrong", 591, "Body here") + } + } + + fun start() { + Kodein.global.addImport(Kodein.Module { + importConfig(loadConfig(ClassResourceConfig("/kovert.conf", ErrorServer::class.java), ReferenceConfig())) { + import("kovert.vertx", KodeinKovertVertx.configModule) + import("kovert.server", KovertVerticleModule.configModule) + } + + // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j + import(KodeinVertx.moduleWithLoggingToSlf4j) + // Kovert boot + import(KodeinKovertVertx.module) + import(KovertVerticleModule.module) + }) + + val initControllers = fun Router.() { + bindController(ErrorController(), "api") + } + + // startup asynchronously... + KovertVertx.start() bind { vertx -> + KovertVerticle.deploy(vertx, routerInit = initControllers) + } success { deploymentId -> + LOG.warn("Deployment complete.") + } fail { error -> + LOG.error("Deployment failed!", error) + } + + } +} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt new file mode 100644 index 0000000000..310fe2a7a0 --- /dev/null +++ b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt @@ -0,0 +1,76 @@ +package com.baeldung.kovert + +import com.fasterxml.jackson.annotation.JsonProperty +import io.vertx.ext.web.Router +import io.vertx.ext.web.RoutingContext +import nl.komponents.kovenant.functional.bind +import org.kodein.di.Kodein +import org.kodein.di.conf.global +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import uy.klutter.config.typesafe.ClassResourceConfig +import uy.klutter.config.typesafe.ReferenceConfig +import uy.klutter.config.typesafe.kodein.importConfig +import uy.klutter.config.typesafe.loadConfig +import uy.klutter.vertx.kodein.KodeinVertx +import uy.kohesive.kovert.vertx.bindController +import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx +import uy.kohesive.kovert.vertx.boot.KovertVerticle +import uy.kohesive.kovert.vertx.boot.KovertVerticleModule +import uy.kohesive.kovert.vertx.boot.KovertVertx + +class JsonServer { + companion object { + private val LOG: Logger = LoggerFactory.getLogger(JsonServer::class.java) + + @JvmStatic + fun main(args: Array) { + JsonServer().start() + } + } + + data class Person( + @JsonProperty("_id") + val id: String, + val name: String, + val job: String + ) + + class JsonController { + fun RoutingContext.getPersonById(id: String) = Person( + id = id, + name = "Tony Stark", + job = "Iron Man" + ) + fun RoutingContext.putPersonById(id: String, person: Person) = person + } + + fun start() { + Kodein.global.addImport(Kodein.Module { + importConfig(loadConfig(ClassResourceConfig("/kovert.conf", JsonServer::class.java), ReferenceConfig())) { + import("kovert.vertx", KodeinKovertVertx.configModule) + import("kovert.server", KovertVerticleModule.configModule) + } + + // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j + import(KodeinVertx.moduleWithLoggingToSlf4j) + // Kovert boot + import(KodeinKovertVertx.module) + import(KovertVerticleModule.module) + }) + + val initControllers = fun Router.() { + bindController(JsonController(), "api") + } + + // startup asynchronously... + KovertVertx.start() bind { vertx -> + KovertVerticle.deploy(vertx, routerInit = initControllers) + } success { deploymentId -> + LOG.warn("Deployment complete.") + } fail { error -> + LOG.error("Deployment failed!", error) + } + + } +} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt new file mode 100644 index 0000000000..98ce775e66 --- /dev/null +++ b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt @@ -0,0 +1,57 @@ +package com.baeldung.kovert + +import io.vertx.ext.web.Router +import nl.komponents.kovenant.functional.bind +import org.kodein.di.Kodein +import org.kodein.di.conf.global +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import uy.klutter.config.typesafe.ClassResourceConfig +import uy.klutter.config.typesafe.ReferenceConfig +import uy.klutter.config.typesafe.kodein.importConfig +import uy.klutter.config.typesafe.loadConfig +import uy.klutter.vertx.kodein.KodeinVertx +import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx +import uy.kohesive.kovert.vertx.boot.KovertVerticle +import uy.kohesive.kovert.vertx.boot.KovertVerticleModule +import uy.kohesive.kovert.vertx.boot.KovertVertx + +class NoopServer { + companion object { + private val LOG: Logger = LoggerFactory.getLogger(NoopServer::class.java) + + @JvmStatic + fun main(args: Array) { + NoopServer().start() + } + } + + + fun start() { + Kodein.global.addImport(Kodein.Module { + importConfig(loadConfig(ClassResourceConfig("/kovert.conf", NoopServer::class.java), ReferenceConfig())) { + import("kovert.vertx", KodeinKovertVertx.configModule) + import("kovert.server", KovertVerticleModule.configModule) + } + + // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j + import(KodeinVertx.moduleWithLoggingToSlf4j) + // Kovert boot + import(KodeinKovertVertx.module) + import(KovertVerticleModule.module) + }) + + val initControllers = fun Router.() { + } + + // startup asynchronously... + KovertVertx.start() bind { vertx -> + KovertVerticle.deploy(vertx, routerInit = initControllers) + } success { deploymentId -> + LOG.warn("Deployment complete.") + } fail { error -> + LOG.error("Deployment failed!", error) + } + + } +} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt new file mode 100644 index 0000000000..86ca482808 --- /dev/null +++ b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt @@ -0,0 +1,68 @@ +package com.baeldung.kovert + +import io.vertx.ext.web.Router +import io.vertx.ext.web.RoutingContext +import nl.komponents.kovenant.functional.bind +import org.kodein.di.Kodein +import org.kodein.di.conf.global +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import uy.klutter.config.typesafe.ClassResourceConfig +import uy.klutter.config.typesafe.ReferenceConfig +import uy.klutter.config.typesafe.kodein.importConfig +import uy.klutter.config.typesafe.loadConfig +import uy.klutter.vertx.kodein.KodeinVertx +import uy.kohesive.kovert.vertx.bindController +import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx +import uy.kohesive.kovert.vertx.boot.KovertVerticle +import uy.kohesive.kovert.vertx.boot.KovertVerticleModule +import uy.kohesive.kovert.vertx.boot.KovertVertx + + +class SecuredServer { + companion object { + private val LOG: Logger = LoggerFactory.getLogger(SecuredServer::class.java) + + @JvmStatic + fun main(args: Array) { + SecuredServer().start() + } + } + + class SecuredContext(private val routingContext: RoutingContext) { + val authenticated = routingContext.request().getHeader("Authorization") == "Secure" + } + + class SecuredController { + fun SecuredContext.getSecured() = this.authenticated + } + + fun start() { + Kodein.global.addImport(Kodein.Module { + importConfig(loadConfig(ClassResourceConfig("/kovert.conf", SecuredServer::class.java), ReferenceConfig())) { + import("kovert.vertx", KodeinKovertVertx.configModule) + import("kovert.server", KovertVerticleModule.configModule) + } + + // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j + import(KodeinVertx.moduleWithLoggingToSlf4j) + // Kovert boot + import(KodeinKovertVertx.module) + import(KovertVerticleModule.module) + }) + + val initControllers = fun Router.() { + bindController(SecuredController(), "api") + } + + // startup asynchronously... + KovertVertx.start() bind { vertx -> + KovertVerticle.deploy(vertx, routerInit = initControllers) + } success { deploymentId -> + LOG.warn("Deployment complete.") + } fail { error -> + LOG.error("Deployment failed!", error) + } + + } +} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt new file mode 100644 index 0000000000..172469ab46 --- /dev/null +++ b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt @@ -0,0 +1,65 @@ +package com.baeldung.kovert + +import io.vertx.ext.web.Router +import io.vertx.ext.web.RoutingContext +import nl.komponents.kovenant.functional.bind +import org.kodein.di.Kodein +import org.kodein.di.conf.global +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import uy.klutter.config.typesafe.ClassResourceConfig +import uy.klutter.config.typesafe.ReferenceConfig +import uy.klutter.config.typesafe.kodein.importConfig +import uy.klutter.config.typesafe.loadConfig +import uy.klutter.vertx.kodein.KodeinVertx +import uy.kohesive.kovert.vertx.bindController +import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx +import uy.kohesive.kovert.vertx.boot.KovertVerticle +import uy.kohesive.kovert.vertx.boot.KovertVerticleModule +import uy.kohesive.kovert.vertx.boot.KovertVertx + + +class SimpleServer { + companion object { + private val LOG: Logger = LoggerFactory.getLogger(SimpleServer::class.java) + + @JvmStatic + fun main(args: Array) { + SimpleServer().start() + } + } + + class SimpleController { + fun RoutingContext.getStringById(id: String) = id + fun RoutingContext.get_truncatedString_by_id(id: String, length: Int = 1) = id.subSequence(0, length) + } + + fun start() { + Kodein.global.addImport(Kodein.Module { + importConfig(loadConfig(ClassResourceConfig("/kovert.conf", SimpleServer::class.java), ReferenceConfig())) { + import("kovert.vertx", KodeinKovertVertx.configModule) + import("kovert.server", KovertVerticleModule.configModule) + } + + // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j + import(KodeinVertx.moduleWithLoggingToSlf4j) + // Kovert boot + import(KodeinKovertVertx.module) + import(KovertVerticleModule.module) + }) + + val initControllers = fun Router.() { + bindController(SimpleController(), "api") + } + + // startup asynchronously... + KovertVertx.start() bind { vertx -> + KovertVerticle.deploy(vertx, routerInit = initControllers) + } success { deploymentId -> + LOG.warn("Deployment complete.") + } fail { error -> + LOG.error("Deployment failed!", error) + } + + } +} diff --git a/kotlin-libraries/src/main/resources/kovert.conf b/kotlin-libraries/src/main/resources/kovert.conf new file mode 100644 index 0000000000..3b08641693 --- /dev/null +++ b/kotlin-libraries/src/main/resources/kovert.conf @@ -0,0 +1,15 @@ +{ + kovert: { + vertx: { + clustered: false + } + server: { + listeners: [ + { + host: "0.0.0.0" + port: "8000" + } + ] + } + } +} From 802e2b0398f46f9939308416066fe9bfe0bf3c6c Mon Sep 17 00:00:00 2001 From: Graham Cox Date: Tue, 8 Jan 2019 14:06:25 +0000 Subject: [PATCH 013/190] Removed Kovert from core-kotlin now it's in kotlin-libraries instead (#6101) --- core-kotlin/pom.xml | 11 --- .../com/baeldung/kovert/AnnotatedServer.kt | 73 ------------------ .../kotlin/com/baeldung/kovert/ErrorServer.kt | 75 ------------------ .../kotlin/com/baeldung/kovert/JsonServer.kt | 76 ------------------- .../kotlin/com/baeldung/kovert/NoopServer.kt | 57 -------------- .../com/baeldung/kovert/SecuredServer.kt | 68 ----------------- .../com/baeldung/kovert/SimpleServer.kt | 65 ---------------- core-kotlin/src/main/resources/kovert.conf | 15 ---- 8 files changed, 440 deletions(-) delete mode 100644 core-kotlin/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt delete mode 100644 core-kotlin/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt delete mode 100644 core-kotlin/src/main/kotlin/com/baeldung/kovert/JsonServer.kt delete mode 100644 core-kotlin/src/main/kotlin/com/baeldung/kovert/NoopServer.kt delete mode 100644 core-kotlin/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt delete mode 100644 core-kotlin/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt delete mode 100644 core-kotlin/src/main/resources/kovert.conf diff --git a/core-kotlin/pom.xml b/core-kotlin/pom.xml index 8b871f28ee..ed79ebc01b 100644 --- a/core-kotlin/pom.xml +++ b/core-kotlin/pom.xml @@ -72,17 +72,6 @@ injekt-core 1.16.1 - - uy.kohesive.kovert - kovert-vertx - [1.5.0,1.6.0) - - - nl.komponents.kovenant - kovenant - - - diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt b/core-kotlin/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt deleted file mode 100644 index da2bbe4208..0000000000 --- a/core-kotlin/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.baeldung.kovert - -import io.vertx.ext.web.Router -import io.vertx.ext.web.RoutingContext -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.core.HttpVerb -import uy.kohesive.kovert.core.Location -import uy.kohesive.kovert.core.Verb -import uy.kohesive.kovert.core.VerbAlias -import uy.kohesive.kovert.vertx.bindController -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - - -class AnnotatedServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(AnnotatedServer::class.java) - - @JvmStatic - fun main(args: Array) { - AnnotatedServer().start() - } - } - - @VerbAlias("show", HttpVerb.GET) - class AnnotatedController { - fun RoutingContext.showStringById(id: String) = id - - @Verb(HttpVerb.GET) - @Location("/ping/:id") - fun RoutingContext.ping(id: String) = id - } - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", AnnotatedServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - bindController(AnnotatedController(), "api") - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt b/core-kotlin/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt deleted file mode 100644 index a596391ed8..0000000000 --- a/core-kotlin/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.baeldung.kovert - -import io.vertx.ext.web.Router -import io.vertx.ext.web.RoutingContext -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.core.HttpErrorCode -import uy.kohesive.kovert.core.HttpErrorCodeWithBody -import uy.kohesive.kovert.core.HttpErrorForbidden -import uy.kohesive.kovert.vertx.bindController -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - - -class ErrorServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(ErrorServer::class.java) - - @JvmStatic - fun main(args: Array) { - ErrorServer().start() - } - } - - class ErrorController { - fun RoutingContext.getForbidden() { - throw HttpErrorForbidden() - } - fun RoutingContext.getError() { - throw HttpErrorCode("Something went wrong", 590) - } - fun RoutingContext.getErrorbody() { - throw HttpErrorCodeWithBody("Something went wrong", 591, "Body here") - } - } - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", ErrorServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - bindController(ErrorController(), "api") - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/JsonServer.kt b/core-kotlin/src/main/kotlin/com/baeldung/kovert/JsonServer.kt deleted file mode 100644 index 310fe2a7a0..0000000000 --- a/core-kotlin/src/main/kotlin/com/baeldung/kovert/JsonServer.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.baeldung.kovert - -import com.fasterxml.jackson.annotation.JsonProperty -import io.vertx.ext.web.Router -import io.vertx.ext.web.RoutingContext -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.vertx.bindController -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - -class JsonServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(JsonServer::class.java) - - @JvmStatic - fun main(args: Array) { - JsonServer().start() - } - } - - data class Person( - @JsonProperty("_id") - val id: String, - val name: String, - val job: String - ) - - class JsonController { - fun RoutingContext.getPersonById(id: String) = Person( - id = id, - name = "Tony Stark", - job = "Iron Man" - ) - fun RoutingContext.putPersonById(id: String, person: Person) = person - } - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", JsonServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - bindController(JsonController(), "api") - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/NoopServer.kt b/core-kotlin/src/main/kotlin/com/baeldung/kovert/NoopServer.kt deleted file mode 100644 index 98ce775e66..0000000000 --- a/core-kotlin/src/main/kotlin/com/baeldung/kovert/NoopServer.kt +++ /dev/null @@ -1,57 +0,0 @@ -package com.baeldung.kovert - -import io.vertx.ext.web.Router -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - -class NoopServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(NoopServer::class.java) - - @JvmStatic - fun main(args: Array) { - NoopServer().start() - } - } - - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", NoopServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt b/core-kotlin/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt deleted file mode 100644 index 86ca482808..0000000000 --- a/core-kotlin/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.baeldung.kovert - -import io.vertx.ext.web.Router -import io.vertx.ext.web.RoutingContext -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.vertx.bindController -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - - -class SecuredServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(SecuredServer::class.java) - - @JvmStatic - fun main(args: Array) { - SecuredServer().start() - } - } - - class SecuredContext(private val routingContext: RoutingContext) { - val authenticated = routingContext.request().getHeader("Authorization") == "Secure" - } - - class SecuredController { - fun SecuredContext.getSecured() = this.authenticated - } - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", SecuredServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - bindController(SecuredController(), "api") - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt b/core-kotlin/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt deleted file mode 100644 index 172469ab46..0000000000 --- a/core-kotlin/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.baeldung.kovert - -import io.vertx.ext.web.Router -import io.vertx.ext.web.RoutingContext -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.vertx.bindController -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - - -class SimpleServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(SimpleServer::class.java) - - @JvmStatic - fun main(args: Array) { - SimpleServer().start() - } - } - - class SimpleController { - fun RoutingContext.getStringById(id: String) = id - fun RoutingContext.get_truncatedString_by_id(id: String, length: Int = 1) = id.subSequence(0, length) - } - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", SimpleServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - bindController(SimpleController(), "api") - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/core-kotlin/src/main/resources/kovert.conf b/core-kotlin/src/main/resources/kovert.conf deleted file mode 100644 index 3b08641693..0000000000 --- a/core-kotlin/src/main/resources/kovert.conf +++ /dev/null @@ -1,15 +0,0 @@ -{ - kovert: { - vertx: { - clustered: false - } - server: { - listeners: [ - { - host: "0.0.0.0" - port: "8000" - } - ] - } - } -} From 5faa406cb062ae194f84a19ab029eb5176ecbcb4 Mon Sep 17 00:00:00 2001 From: myluckagain Date: Tue, 8 Jan 2019 19:36:42 +0500 Subject: [PATCH 014/190] BAEL-2474 (#5997) * BAEL-2474 * rename UserRepositoryImpl.java into UserRepositoryCustomImpl.java --- .../dao/repositories/user/UserRepository.java | 3 +- .../user/UserRepositoryCustom.java | 10 ++++ .../user/UserRepositoryCustomImpl.java | 43 +++++++++++++++ .../UserRepositoryIntegrationTest.java | 55 +++++++++++++------ 4 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java create mode 100644 persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java index 5bb0232e4a..7f54254832 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java @@ -1,6 +1,7 @@ package com.baeldung.dao.repositories.user; import com.baeldung.domain.user.User; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @@ -13,7 +14,7 @@ import java.util.Collection; import java.util.List; import java.util.stream.Stream; -public interface UserRepository extends JpaRepository { +public interface UserRepository extends JpaRepository , UserRepositoryCustom{ Stream findAllByName(String name); diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java new file mode 100644 index 0000000000..72c1fd5d00 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java @@ -0,0 +1,10 @@ +package com.baeldung.dao.repositories.user; + +import java.util.List; +import java.util.Set; + +import com.baeldung.domain.user.User; + +public interface UserRepositoryCustom { + List findUserByEmails(Set emails); +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java new file mode 100644 index 0000000000..9f841caf68 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java @@ -0,0 +1,43 @@ +package com.baeldung.dao.repositories.user; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import com.baeldung.domain.user.User; + +public class UserRepositoryCustomImpl implements UserRepositoryCustom { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public List findUserByEmails(Set emails) { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + CriteriaQuery query = cb.createQuery(User.class); + Root user = query.from(User.class); + + Path emailPath = user.get("email"); + + List predicates = new ArrayList<>(); + for (String email : emails) { + + predicates.add(cb.like(emailPath, email)); + + } + query.select(user) + .where(cb.or(predicates.toArray(new Predicate[predicates.size()]))); + + return entityManager.createQuery(query) + .getResultList(); + } + +} diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java index e29161394b..b05086d00e 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java @@ -18,7 +18,9 @@ import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; @@ -274,9 +276,8 @@ public class UserRepositoryIntegrationTest { List usersSortByName = userRepository.findAll(new Sort(Sort.Direction.ASC, "name")); - assertThat(usersSortByName - .get(0) - .getName()).isEqualTo(USER_NAME_ADAM); + assertThat(usersSortByName.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); } @Test(expected = PropertyReferenceException.class) @@ -289,9 +290,8 @@ public class UserRepositoryIntegrationTest { List usersSortByNameLength = userRepository.findAll(new Sort("LENGTH(name)")); - assertThat(usersSortByNameLength - .get(0) - .getName()).isEqualTo(USER_NAME_ADAM); + assertThat(usersSortByNameLength.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); } @Test @@ -304,9 +304,8 @@ public class UserRepositoryIntegrationTest { List usersSortByNameLength = userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)")); - assertThat(usersSortByNameLength - .get(0) - .getName()).isEqualTo(USER_NAME_ADAM); + assertThat(usersSortByNameLength.get(0) + .getName()).isEqualTo(USER_NAME_ADAM); } @Test @@ -320,10 +319,9 @@ public class UserRepositoryIntegrationTest { Page usersPage = userRepository.findAllUsersWithPagination(new PageRequest(1, 3)); - assertThat(usersPage - .getContent() - .get(0) - .getName()).isEqualTo("SAMPLE1"); + assertThat(usersPage.getContent() + .get(0) + .getName()).isEqualTo("SAMPLE1"); } @Test @@ -337,10 +335,9 @@ public class UserRepositoryIntegrationTest { Page usersSortByNameLength = userRepository.findAllUsersWithPaginationNative(new PageRequest(1, 3)); - assertThat(usersSortByNameLength - .getContent() - .get(0) - .getName()).isEqualTo("SAMPLE1"); + assertThat(usersSortByNameLength.getContent() + .get(0) + .getName()).isEqualTo("SAMPLE1"); } @Test @@ -370,6 +367,30 @@ public class UserRepositoryIntegrationTest { assertThat(updatedUsersSize).isEqualTo(2); } + @Test + public void givenUsersInDBWhenFindByEmailsWithDynamicQueryThenReturnCollection() { + + User user1 = new User(); + user1.setEmail(USER_EMAIL); + userRepository.save(user1); + + User user2 = new User(); + user2.setEmail(USER_EMAIL2); + userRepository.save(user2); + + User user3 = new User(); + user3.setEmail(USER_EMAIL3); + userRepository.save(user3); + + Set emails = new HashSet<>(); + emails.add(USER_EMAIL2); + emails.add(USER_EMAIL3); + + Collection usersWithEmails = userRepository.findUserByEmails(emails); + + assertThat(usersWithEmails.size()).isEqualTo(2); + } + @After public void cleanUp() { userRepository.deleteAll(); From 26101769311c7de0285f23e34f00c90187e53f64 Mon Sep 17 00:00:00 2001 From: Urvy Agrawal Date: Tue, 8 Jan 2019 20:09:51 +0530 Subject: [PATCH 015/190] Review comments added --- .../java/com/baeldung/keyword/test/InstanceOfUnitTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core-java/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java b/core-java/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java index fbeec3a077..4c010e3a16 100644 --- a/core-java/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java +++ b/core-java/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java @@ -35,6 +35,12 @@ public class InstanceOfUnitTest { Circle circle = new Circle(); Assert.assertTrue("circle is instance of Shape", circle instanceof Shape); } + + @Test + public void giveWhenTypeIsOfObjectType_thenReturnTrue() { + Thread thread = new Thread(); + Assert.assertTrue("thread is instance of Object", thread instanceof Object); + } @Test public void giveWhenInstanceValueIsNull_thenReturnFalse() { From f1fa9c8253a9db826ad4de40dd71be2ec2ac7527 Mon Sep 17 00:00:00 2001 From: pandachris Date: Tue, 8 Jan 2019 22:18:47 +0700 Subject: [PATCH 016/190] BAEL-2565 move code to different project (#6099) * BAEL-2565 * BAEL-2565 Test code consistency * BAEL-2565 Move code to different project --- .../src/main/java/com/baeldung/enums/values/Element1.java | 0 .../src/main/java/com/baeldung/enums/values/Element2.java | 0 .../src/main/java/com/baeldung/enums/values/Element3.java | 0 .../src/main/java/com/baeldung/enums/values/Element4.java | 0 .../src/main/java/com/baeldung/enums/values/Labeled.java | 0 .../src/test/java/com/baeldung/enums/values/Element1UnitTest.java | 0 .../src/test/java/com/baeldung/enums/values/Element2UnitTest.java | 0 .../src/test/java/com/baeldung/enums/values/Element3UnitTest.java | 0 .../src/test/java/com/baeldung/enums/values/Element4UnitTest.java | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename {core-java-8 => core-java-lang}/src/main/java/com/baeldung/enums/values/Element1.java (100%) rename {core-java-8 => core-java-lang}/src/main/java/com/baeldung/enums/values/Element2.java (100%) rename {core-java-8 => core-java-lang}/src/main/java/com/baeldung/enums/values/Element3.java (100%) rename {core-java-8 => core-java-lang}/src/main/java/com/baeldung/enums/values/Element4.java (100%) rename {core-java-8 => core-java-lang}/src/main/java/com/baeldung/enums/values/Labeled.java (100%) rename {core-java-8 => core-java-lang}/src/test/java/com/baeldung/enums/values/Element1UnitTest.java (100%) rename {core-java-8 => core-java-lang}/src/test/java/com/baeldung/enums/values/Element2UnitTest.java (100%) rename {core-java-8 => core-java-lang}/src/test/java/com/baeldung/enums/values/Element3UnitTest.java (100%) rename {core-java-8 => core-java-lang}/src/test/java/com/baeldung/enums/values/Element4UnitTest.java (100%) diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element1.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/enums/values/Element1.java rename to core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element2.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/enums/values/Element2.java rename to core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element3.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/enums/values/Element3.java rename to core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element4.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/enums/values/Element4.java rename to core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Labeled.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/enums/values/Labeled.java rename to core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element1UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/enums/values/Element1UnitTest.java rename to core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element2UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/enums/values/Element2UnitTest.java rename to core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element3UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/enums/values/Element3UnitTest.java rename to core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java rename to core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java From c0e36d5b10ca8716390ac1954218b037e9775b83 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 9 Jan 2019 00:30:54 +0530 Subject: [PATCH 017/190] BAEL-10925 New module spring-boot-rest --- pom.xml | 6 ++- spring-boot-rest/pom.xml | 43 +++++++++++++++++++ .../web/SpringBootRestApplication.java | 13 ++++++ .../com/baeldung/web/config/WebConfig.java | 8 ++++ .../src/main/resources/application.properties | 0 .../SpringBootRestApplicationUnitTest.java | 16 +++++++ 6 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 spring-boot-rest/pom.xml create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java create mode 100644 spring-boot-rest/src/main/resources/application.properties create mode 100644 spring-boot-rest/src/test/java/com/baeldung/web/SpringBootRestApplicationUnitTest.java diff --git a/pom.xml b/pom.xml index 4dba0da173..cf7eb1f394 100644 --- a/pom.xml +++ b/pom.xml @@ -645,6 +645,7 @@ spring-boot-mvc spring-boot-ops spring-boot-property-exp + spring-boot-rest spring-boot-security spring-boot-testing spring-boot-vue @@ -1356,8 +1357,11 @@ spring-boot-mvc spring-boot-ops spring-boot-property-exp + spring-boot-rest spring-boot-security + spring-boot-testing spring-boot-vue + spring-boot-libraries spring-cloud spring-cloud-bus @@ -1372,7 +1376,7 @@ spring-dispatcher-servlet spring-drools - spring-ehcache + spring-ehcache spring-ejb spring-exceptions diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml new file mode 100644 index 0000000000..baf9d35a09 --- /dev/null +++ b/spring-boot-rest/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + com.baeldung.web + spring-boot-rest + spring-boot-rest + Spring Boot Rest Module + war + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + com.baeldung.SpringBootRestApplication + + diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java b/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java new file mode 100644 index 0000000000..62aae7619d --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootRestApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootRestApplication.class, args); + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java new file mode 100644 index 0000000000..808e946218 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java @@ -0,0 +1,8 @@ +package com.baeldung.web.config; + +import org.springframework.context.annotation.Configuration; + +@Configuration +public class WebConfig { + +} \ No newline at end of file diff --git a/spring-boot-rest/src/main/resources/application.properties b/spring-boot-rest/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/SpringBootRestApplicationUnitTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/SpringBootRestApplicationUnitTest.java new file mode 100644 index 0000000000..747e08f6f8 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/SpringBootRestApplicationUnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.boot.rest; + +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 SpringBootRestApplicationUnitTest { + + @Test + public void contextLoads() { + } + +} From 842d8573af8bef74a34b3b65d3f7bae59ffa5742 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 9 Jan 2019 00:38:14 +0530 Subject: [PATCH 018/190] Revert parent pom.xml --- pom.xml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index cf7eb1f394..4dba0da173 100644 --- a/pom.xml +++ b/pom.xml @@ -645,7 +645,6 @@ spring-boot-mvc spring-boot-ops spring-boot-property-exp - spring-boot-rest spring-boot-security spring-boot-testing spring-boot-vue @@ -1357,11 +1356,8 @@ spring-boot-mvc spring-boot-ops spring-boot-property-exp - spring-boot-rest spring-boot-security - spring-boot-testing spring-boot-vue - spring-boot-libraries spring-cloud spring-cloud-bus @@ -1376,7 +1372,7 @@ spring-dispatcher-servlet spring-drools - spring-ehcache + spring-ehcache spring-ejb spring-exceptions From 6cd561d91a1ef1d8b5fc52f2d10ceff16e4bcf1f Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 9 Jan 2019 00:41:57 +0530 Subject: [PATCH 019/190] Fixed pom.xml --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 4dba0da173..324f6129db 100644 --- a/pom.xml +++ b/pom.xml @@ -644,6 +644,7 @@ spring-boot-logging-log4j2 spring-boot-mvc spring-boot-ops + spring-boot-rest spring-boot-property-exp spring-boot-security spring-boot-testing @@ -1355,6 +1356,7 @@ spring-boot-logging-log4j2 spring-boot-mvc spring-boot-ops + spring-boot-rest spring-boot-property-exp spring-boot-security spring-boot-vue From e6f28c61a3484d5cd488c1160981ac36c35e8b05 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Wed, 9 Jan 2019 00:09:02 +0200 Subject: [PATCH 020/190] Create README.md --- spring-boot-rest/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 spring-boot-rest/README.md diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md new file mode 100644 index 0000000000..0a8d13cf76 --- /dev/null +++ b/spring-boot-rest/README.md @@ -0,0 +1,3 @@ +Module for the articles that are part of the Spring REST E-book: + +1. [Bootstrap a Web Application with Spring 5](https://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) From 58ed9e47b204652bae2ced49cb0b541840272f8f Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Wed, 9 Jan 2019 00:12:40 +0200 Subject: [PATCH 021/190] Update and rename SpringBootRestApplicationUnitTest.java to SpringContextIntegrationTest.java --- ...plicationUnitTest.java => SpringContextIntegrationTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename spring-boot-rest/src/test/java/com/baeldung/web/{SpringBootRestApplicationUnitTest.java => SpringContextIntegrationTest.java} (86%) diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/SpringBootRestApplicationUnitTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java similarity index 86% rename from spring-boot-rest/src/test/java/com/baeldung/web/SpringBootRestApplicationUnitTest.java rename to spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java index 747e08f6f8..0c1fdf372b 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/SpringBootRestApplicationUnitTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java @@ -7,7 +7,7 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest -public class SpringBootRestApplicationUnitTest { +public class SpringContextIntegrationTest { @Test public void contextLoads() { From 065a6e2519d5b52093381a388f9075c5580d8f7f Mon Sep 17 00:00:00 2001 From: jose Date: Tue, 8 Jan 2019 23:55:48 -0300 Subject: [PATCH 022/190] BAEL-2472 code examples --- .../com/baeldung/scope/ClassScopeExample.java | 15 +++++++++++++++ .../com/baeldung/scope/LoopScopeExample.java | 18 ++++++++++++++++++ .../com/baeldung/scope/MethodScopeExample.java | 16 ++++++++++++++++ .../baeldung/scope/NestedScopesExample.java | 13 +++++++++++++ .../com/baeldung/scope/OutOfScopeExample.java | 14 ++++++++++++++ 5 files changed, 76 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java create mode 100644 core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java create mode 100644 core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java create mode 100644 core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java create mode 100644 core-java/src/main/java/com/baeldung/scope/OutOfScopeExample.java diff --git a/core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java b/core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java new file mode 100644 index 0000000000..17ca1e01eb --- /dev/null +++ b/core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java @@ -0,0 +1,15 @@ +package org.baeldung.variable.scope.examples; + +public class ClassScopeExample { + + Integer amount = 0; + + public void exampleMethod() { + amount++; + } + + public void anotherExampleMethod() { + amount--; + } + +} diff --git a/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java b/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java new file mode 100644 index 0000000000..2dd3be3333 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java @@ -0,0 +1,18 @@ +package org.baeldung.variable.scope.examples; + +import java.util.Arrays; +import java.util.List; + +public class LoopScopeExample { + + List listOfNames = Arrays.asList("Joe", "Susan", "Pattrick"); + + public void iterationOfNames() { + String allNames = ""; + for (String name : listOfNames) { + allNames = allNames + " " + name; + } + + } + +} diff --git a/core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java b/core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java new file mode 100644 index 0000000000..122d12e2fc --- /dev/null +++ b/core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java @@ -0,0 +1,16 @@ +package org.baeldung.variable.scope.examples; + +public class MethodScopeExample { + + Integer size = 2; + + public void methodA() { + Integer area = 2; + area = area + size; + } + + public void methodB() { + size = size + 5; + } + +} diff --git a/core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java b/core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java new file mode 100644 index 0000000000..9bd2268e52 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java @@ -0,0 +1,13 @@ +package org.baeldung.variable.scope.examples; + +public class NestedScopesExample { + + String title = "Baeldung"; + + public void printTitle() { + System.out.println(title); + String title = "John Doe"; + System.out.println(title); + } + +} diff --git a/core-java/src/main/java/com/baeldung/scope/OutOfScopeExample.java b/core-java/src/main/java/com/baeldung/scope/OutOfScopeExample.java new file mode 100644 index 0000000000..774095228c --- /dev/null +++ b/core-java/src/main/java/com/baeldung/scope/OutOfScopeExample.java @@ -0,0 +1,14 @@ +package org.baeldung.variable.scope.examples; + +public class OutOfScopeExample { + + public void methodWithAVariableDeclaredInside() { + String name = "John Doe"; + System.out.println(name); + } + + public void methodWithoutVariables() { + System.out.println("Pattrick"); + } + +} From f1e3ceaea75f6b5e6efcd2517523baa48b8ccfa8 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Wed, 9 Jan 2019 12:21:43 +0400 Subject: [PATCH 023/190] text searching Aho-Corasick algorithm --- java-strings/pom.xml | 6 +++ .../java/com/baeldung/string/MatchWords.java | 48 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 java-strings/src/main/java/com/baeldung/string/MatchWords.java diff --git a/java-strings/pom.xml b/java-strings/pom.xml index f4fb1c0865..9f89ed6d76 100755 --- a/java-strings/pom.xml +++ b/java-strings/pom.xml @@ -95,6 +95,12 @@ 1.4 + + org.ahocorasick + ahocorasick + 0.4.0 + + diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java new file mode 100644 index 0000000000..ec926d99c4 --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -0,0 +1,48 @@ +package com.baeldung.string; + +import org.ahocorasick.trie.Emit; +import org.ahocorasick.trie.Trie; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.regex.Pattern; + +public class MatchWords { + + // *778*1# *778*00# + public static void main(String[] args) { + String[] items = {"hello", "Baeldung"}; + String inputString = "hello there, Baeldung"; + + boolean isMatch = java8(inputString, new ArrayList<>(Arrays.asList(items))); + + System.out.println(isMatch); + + System.out.println(patternMatch(inputString)); + + ahoCorasick(); + } + + private static void ahoCorasick() { + Trie trie = Trie.builder() + .onlyWholeWords() + .addKeyword("hello") + .addKeyword("Baeldung") + .build(); + Collection emits = trie.parseText("hello there, Baeldung"); + emits.forEach(System.out::println); + } + + private static boolean patternMatch(String inputString) { + Pattern pattern = Pattern.compile("(?=.*hello)(?=.*Baeldung)"); + if (pattern.matcher(inputString).find()) { + return true; + } + return false; + } + + private static boolean java8(String inputString, ArrayList items) { + return Arrays.stream(inputString.split(" ")).allMatch(items::contains); + } +} From 1861e9b94ccadeaed1dd796c5e55bddfbe28607f Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Wed, 9 Jan 2019 16:16:48 +0400 Subject: [PATCH 024/190] match words --- .../java/com/baeldung/string/MatchWords.java | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index ec926d99c4..0cdb4cde6a 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -10,18 +10,28 @@ import java.util.regex.Pattern; public class MatchWords { - // *778*1# *778*00# public static void main(String[] args) { String[] items = {"hello", "Baeldung"}; String inputString = "hello there, Baeldung"; - boolean isMatch = java8(inputString, new ArrayList<>(Arrays.asList(items))); + //System.out.println(containsWords(inputString, items)); - System.out.println(isMatch); + System.out.println(java8(new ArrayList<>(Arrays.asList(inputString.split(" "))), new ArrayList<>(Arrays.asList(items)))); - System.out.println(patternMatch(inputString)); + //System.out.println(patternMatch(inputString)); - ahoCorasick(); + //ahoCorasick(); + } + + private static boolean containsWords(String inputString, String[] items) { + boolean found = true; + for (String item : items) { + if (!inputString.contains(item)) { + found = false; + break; + } + } + return found; } private static void ahoCorasick() { @@ -42,7 +52,12 @@ public class MatchWords { return false; } - private static boolean java8(String inputString, ArrayList items) { - return Arrays.stream(inputString.split(" ")).allMatch(items::contains); + private static boolean java8(ArrayList inputString, ArrayList items) { + return items.stream().allMatch(inputString::contains); } + + private static boolean array(ArrayList inputString, ArrayList items) { + return inputString.containsAll(items); + } + } From d413ec768f99a2967075f2dff2d6e456dd7b629c Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Wed, 9 Jan 2019 16:18:32 +0400 Subject: [PATCH 025/190] match words final --- .../src/main/java/com/baeldung/string/MatchWords.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index 0cdb4cde6a..6e6acb24cf 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -14,13 +14,13 @@ public class MatchWords { String[] items = {"hello", "Baeldung"}; String inputString = "hello there, Baeldung"; - //System.out.println(containsWords(inputString, items)); + System.out.println(containsWords(inputString, items)); System.out.println(java8(new ArrayList<>(Arrays.asList(inputString.split(" "))), new ArrayList<>(Arrays.asList(items)))); - //System.out.println(patternMatch(inputString)); + System.out.println(patternMatch(inputString)); - //ahoCorasick(); + ahoCorasick(); } private static boolean containsWords(String inputString, String[] items) { From 9e9458ea5f000131a76c9105666b77f0c3454fc7 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Wed, 9 Jan 2019 17:17:35 +0400 Subject: [PATCH 026/190] indexOf example --- .../java/com/baeldung/string/MatchWords.java | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index 6e6acb24cf..c0f89b635d 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -3,9 +3,7 @@ package com.baeldung.string; import org.ahocorasick.trie.Emit; import org.ahocorasick.trie.Trie; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; +import java.util.*; import java.util.regex.Pattern; public class MatchWords { @@ -21,6 +19,25 @@ public class MatchWords { System.out.println(patternMatch(inputString)); ahoCorasick(); + + wordIndices(inputString); + } + + private static void wordIndices(String inputString) { + Map wordIndices = new TreeMap<>(); + List words = new ArrayList<>(); + words.add("hello"); + words.add("Baeldung"); + + for (String word : words) { + int index = inputString.indexOf(word); + + if (index != -1) { + wordIndices.put(index, word); + } + } + + wordIndices.keySet().forEach(System.out::println); } private static boolean containsWords(String inputString, String[] items) { From a094e49a6292aaad494f6d66194066c69a81c43f Mon Sep 17 00:00:00 2001 From: Mikhail Chugunov Date: Wed, 9 Jan 2019 19:53:12 +0300 Subject: [PATCH 027/190] BAEL-2475: Changes after first review --- .../deserialization/immutable/Employee.java | 24 ++++++++ .../immutable/MaritalAwarePerson.java | 58 ------------------- .../deserialization/immutable/Person.java | 32 ++++++++-- ...mmutableObjectDeserializationUnitTest.java | 22 ++++--- 4 files changed, 60 insertions(+), 76 deletions(-) create mode 100644 jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Employee.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/MaritalAwarePerson.java diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Employee.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Employee.java new file mode 100644 index 0000000000..44b10ee39b --- /dev/null +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Employee.java @@ -0,0 +1,24 @@ +package com.baeldung.jackson.deserialization.immutable; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Employee { + + private final long id; + private final String name; + + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + public Employee(@JsonProperty("id") long id, @JsonProperty("name") String name) { + this.id = id; + this.name = name; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } +} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/MaritalAwarePerson.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/MaritalAwarePerson.java deleted file mode 100644 index cb593b3bb7..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/MaritalAwarePerson.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.baeldung.jackson.deserialization.immutable; - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; - -@JsonDeserialize(builder = MaritalAwarePerson.Builder.class) -public class MaritalAwarePerson { - - private final String name; - private final int age; - private final Boolean married; - - private MaritalAwarePerson(String name, int age, Boolean married) { - this.name = name; - this.age = age; - this.married = married; - } - - public String getName() { - return name; - } - - public int getAge() { - return age; - } - - public Boolean getMarried() { - return married; - } - - @JsonPOJOBuilder - static class Builder { - String name; - int age; - Boolean married; - - Builder withName(String name) { - this.name = name; - return this; - } - - Builder withAge(int age) { - this.age = age; - return this; - } - - Builder withMarried(boolean married) { - this.married = married; - return this; - } - - public MaritalAwarePerson build() { - return new MaritalAwarePerson(name, age, married); - } - - - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java index 0214f93ca9..d9041720b6 100644 --- a/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/immutable/Person.java @@ -1,15 +1,15 @@ package com.baeldung.jackson.deserialization.immutable; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; +@JsonDeserialize(builder = Person.Builder.class) public class Person { private final String name; - private final int age; + private final Integer age; - @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) - public Person(@JsonProperty("name") String name, @JsonProperty("age") int age) { + private Person(String name, Integer age) { this.name = name; this.age = age; } @@ -18,7 +18,27 @@ public class Person { return name; } - public int getAge() { + public Integer getAge() { return age; } + + @JsonPOJOBuilder + static class Builder { + String name; + Integer age; + + Builder withName(String name) { + this.name = name; + return this; + } + + Builder withAge(Integer age) { + this.age = age; + return this; + } + + Person build() { + return new Person(name, age); + } + } } diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java index 5c33a2da26..1252179e3a 100644 --- a/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/immutable/ImmutableObjectDeserializationUnitTest.java @@ -11,30 +11,28 @@ public class ImmutableObjectDeserializationUnitTest { @Test public void whenPublicConstructorIsUsed_thenObjectIsDeserialized() throws IOException { - final String json = "{\"name\":\"Frank\",\"age\":50}"; - Person person = new ObjectMapper().readValue(json, Person.class); + final String json = "{\"name\":\"Frank\",\"id\":5000}"; + Employee employee = new ObjectMapper().readValue(json, Employee.class); - assertEquals("Frank", person.getName()); - assertEquals(50, person.getAge()); + assertEquals("Frank", employee.getName()); + assertEquals(5000, employee.getId()); } @Test public void whenBuilderIsUsedAndFieldIsNull_thenObjectIsDeserialized() throws IOException { - final String json = "{\"name\":\"Frank\",\"age\":50}"; - MaritalAwarePerson person = new ObjectMapper().readValue(json, MaritalAwarePerson.class); + final String json = "{\"name\":\"Frank\"}"; + Person person = new ObjectMapper().readValue(json, Person.class); assertEquals("Frank", person.getName()); - assertEquals(50, person.getAge()); - assertNull(person.getMarried()); + assertNull(person.getAge()); } @Test public void whenBuilderIsUsedAndAllFieldsPresent_thenObjectIsDeserialized() throws IOException { - final String json = "{\"name\":\"Frank\",\"age\":50,\"married\":true}"; - MaritalAwarePerson person = new ObjectMapper().readValue(json, MaritalAwarePerson.class); + final String json = "{\"name\":\"Frank\",\"age\":50}"; + Person person = new ObjectMapper().readValue(json, Person.class); assertEquals("Frank", person.getName()); - assertEquals(50, person.getAge()); - assertTrue(person.getMarried()); + assertEquals(50, (int) person.getAge()); } } From 44490a052ff0760b5115ba5764e53553c41ccf44 Mon Sep 17 00:00:00 2001 From: Sam Millington Date: Wed, 9 Jan 2019 18:06:47 +0000 Subject: [PATCH 028/190] BAEL2526 queue interface code (#6115) * BAEL2526 queue interface code * renamed test class to end with 'UnitTest', removed camel case from package name --- .../queueInterface/CustomBaeldungQueue.java | 48 +++++++++++++++++ .../queueInterface/PriorityQueueUnitTest.java | 53 +++++++++++++++++++ .../CustomBaeldungQueueUnitTest.java | 30 +++++++++++ 3 files changed, 131 insertions(+) create mode 100644 core-java-collections/src/main/java/com/baeldung/queueInterface/CustomBaeldungQueue.java create mode 100644 core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java create mode 100644 core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java diff --git a/core-java-collections/src/main/java/com/baeldung/queueInterface/CustomBaeldungQueue.java b/core-java-collections/src/main/java/com/baeldung/queueInterface/CustomBaeldungQueue.java new file mode 100644 index 0000000000..6b088a5079 --- /dev/null +++ b/core-java-collections/src/main/java/com/baeldung/queueInterface/CustomBaeldungQueue.java @@ -0,0 +1,48 @@ +package com.baeldung.queueinterface; + +import java.util.AbstractQueue; +import java.util.Iterator; +import java.util.LinkedList; + +public class CustomBaeldungQueue extends AbstractQueue { + + private LinkedList elements; + + public CustomBaeldungQueue() { + this.elements = new LinkedList(); + } + + @Override + public Iterator iterator() { + return elements.iterator(); + } + + @Override + public int size() { + return elements.size(); + } + + @Override + public boolean offer(T t) { + if(t == null) return false; + elements.add(t); + return true; + } + + @Override + public T poll() { + + Iterator iter = elements.iterator(); + T t = iter.next(); + if(t != null){ + iter.remove(); + return t; + } + return null; + } + + @Override + public T peek() { + return elements.getFirst(); + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java b/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java new file mode 100644 index 0000000000..c5b564b55b --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.queueinterface; + +import org.junit.Before; +import org.junit.Test; + +import java.util.PriorityQueue; + +import static org.junit.Assert.assertEquals; + +public class PriorityQueueUnitTest { + + + + @Test + public void givenIntegerQueue_whenIntegersOutOfOrder_checkRetrievalOrderIsNatural() { + + PriorityQueue integerQueue = new PriorityQueue<>(); + + integerQueue.add(9); + integerQueue.add(2); + integerQueue.add(4); + + int first = integerQueue.poll(); + int second = integerQueue.poll(); + int third = integerQueue.poll(); + + assertEquals(2, first); + assertEquals(4, second); + assertEquals(9, third); + + + } + + @Test + public void givenStringQueue_whenStringsAddedOutOfNaturalOrder_checkRetrievalOrderNatural() { + + PriorityQueue stringQueue = new PriorityQueue<>(); + + stringQueue.add("banana"); + stringQueue.add("apple"); + stringQueue.add("cherry"); + + String first = stringQueue.poll(); + String second = stringQueue.poll(); + String third = stringQueue.poll(); + + assertEquals("apple", first); + assertEquals("banana", second); + assertEquals("cherry", third); + + + } +} diff --git a/core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java b/core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java new file mode 100644 index 0000000000..6dec768542 --- /dev/null +++ b/core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.queueinterface; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class CustomBaeldungQueueUnitTest { + + private CustomBaeldungQueue customQueue; + + @Before + public void setUp() throws Exception { + customQueue = new CustomBaeldungQueue<>(); + } + + @Test + public void givenQueueWithTwoElements_whenElementsRetrieved_checkRetrievalCorrect() { + + customQueue.add(7); + customQueue.add(5); + + int first = customQueue.poll(); + int second = customQueue.poll(); + + assertEquals(7, first); + assertEquals(5, second); + + } +} From 128817cfebe533b21c4248f6d14099579108a52d Mon Sep 17 00:00:00 2001 From: Amy DeGregorio Date: Wed, 9 Jan 2019 15:20:47 -0500 Subject: [PATCH 029/190] example code for Article How to Write to a CSV File in Java (#6102) --- .../com/baeldung/csv/WriteCsvFileExample.java | 29 ++++++ .../csv/WriteCsvFileExampleUnitTest.java | 90 +++++++++++++++++++ .../src/test/resources/exampleOutput.csv | 2 + 3 files changed, 121 insertions(+) create mode 100644 core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java create mode 100644 core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java create mode 100644 core-java-io/src/test/resources/exampleOutput.csv diff --git a/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java b/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java new file mode 100644 index 0000000000..fd3678d2c5 --- /dev/null +++ b/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java @@ -0,0 +1,29 @@ +package com.baeldung.csv; + +import java.io.BufferedWriter; +import java.io.IOException; + +public class WriteCsvFileExample { + + public void writeLine(BufferedWriter writer, String[] data) throws IOException { + StringBuilder csvLine = new StringBuilder(); + + for (int i = 0; i < data.length; i++) { + if (i > 0) { + csvLine.append(","); + } + csvLine.append(escapeSpecialCharacters(data[i])); + } + + writer.write(csvLine.toString()); + } + + public String escapeSpecialCharacters(String data) { + String escapedData = data.replaceAll("\\R", " "); + if (data.contains(",") || data.contains("\"") || data.contains("'")) { + data = data.replace("\"", "\"\""); + escapedData = "\"" + data + "\""; + } + return escapedData; + } +} diff --git a/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java b/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java new file mode 100644 index 0000000000..4ac84f939d --- /dev/null +++ b/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java @@ -0,0 +1,90 @@ +package com.baeldung.csv; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WriteCsvFileExampleUnitTest { + private static final Logger LOG = LoggerFactory.getLogger(WriteCsvFileExampleUnitTest.class); + + private static final String CSV_FILE_NAME = "src/test/resources/exampleOutput.csv"; + private WriteCsvFileExample csvExample; + + @Before + public void setupClass() { + csvExample = new WriteCsvFileExample(); + } + + @Test + public void givenCommaContainingData_whenEscapeSpecialCharacters_stringReturnedInQuotes() { + String data = "three,two,one"; + String escapedData = csvExample.escapeSpecialCharacters(data); + + String expectedData = "\"three,two,one\""; + assertEquals(expectedData, escapedData); + } + + @Test + public void givenQuoteContainingData_whenEscapeSpecialCharacters_stringReturnedFormatted() { + String data = "She said \"Hello\""; + String escapedData = csvExample.escapeSpecialCharacters(data); + + String expectedData = "\"She said \"\"Hello\"\"\""; + assertEquals(expectedData, escapedData); + } + + @Test + public void givenNewlineContainingData_whenEscapeSpecialCharacters_stringReturnedInQuotes() { + String dataNewline = "This contains\na newline"; + String dataCarriageReturn = "This contains\r\na newline and carriage return"; + String escapedDataNl = csvExample.escapeSpecialCharacters(dataNewline); + String escapedDataCr = csvExample.escapeSpecialCharacters(dataCarriageReturn); + + String expectedData = "This contains a newline"; + assertEquals(expectedData, escapedDataNl); + String expectedDataCr = "This contains a newline and carriage return"; + assertEquals(expectedDataCr, escapedDataCr); + } + + @Test + public void givenNonSpecialData_whenEscapeSpecialCharacters_stringReturnedUnchanged() { + String data = "This is nothing special"; + String returnedData = csvExample.escapeSpecialCharacters(data); + + assertEquals(data, returnedData); + } + + @Test + public void givenBufferedWriter_whenWriteLine_thenOutputCreated() { + List dataLines = new ArrayList(); + dataLines.add(new String[] { "John", "Doe", "38", "Comment Data\nAnother line of comment data" }); + dataLines.add(new String[] { "Jane", "Doe, Jr.", "19", "She said \"I'm being quoted\"" }); + + File csvOutputFile = new File(CSV_FILE_NAME); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(csvOutputFile))) { + for (Iterator dataIterator = dataLines.iterator(); dataIterator.hasNext();) { + csvExample.writeLine(writer, dataIterator.next()); + if (dataIterator.hasNext()) { + writer.newLine(); + } + } + writer.flush(); + } catch (IOException e) { + LOG.error("IOException " + e.getMessage()); + } + + assertTrue(csvOutputFile.exists()); + } +} diff --git a/core-java-io/src/test/resources/exampleOutput.csv b/core-java-io/src/test/resources/exampleOutput.csv new file mode 100644 index 0000000000..45c37f3a3b --- /dev/null +++ b/core-java-io/src/test/resources/exampleOutput.csv @@ -0,0 +1,2 @@ +John,Doe,38,Comment Data Another line of comment data +Jane,"Doe, Jr.",19,"She said ""I'm being quoted""" \ No newline at end of file From 70a7aaa4fc25ad2d40e314d3f1c3ae8d8b760101 Mon Sep 17 00:00:00 2001 From: Kumar Chandrakant Date: Thu, 10 Jan 2019 02:20:46 +0530 Subject: [PATCH 030/190] Kafka spark cassandra (#6089) * Adding files for the tutorial BAEL-2301 * Incorporating review comments on the article. * Incorporated additional review comments on the article. --- .../data/pipeline/WordCountingApp.java | 18 ++++++------------ .../WordCountingAppWithCheckpoint.java | 19 ++++++------------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingApp.java b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingApp.java index 1155644e1e..db2a73b411 100644 --- a/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingApp.java +++ b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingApp.java @@ -14,13 +14,7 @@ import org.apache.kafka.common.serialization.StringDeserializer; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.spark.SparkConf; -import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.java.JavaRDD; -import org.apache.spark.api.java.function.FlatMapFunction; -import org.apache.spark.api.java.function.Function; -import org.apache.spark.api.java.function.Function2; -import org.apache.spark.api.java.function.PairFunction; -import org.apache.spark.api.java.function.VoidFunction; import org.apache.spark.streaming.Durations; import org.apache.spark.streaming.api.java.JavaDStream; import org.apache.spark.streaming.api.java.JavaInputDStream; @@ -59,17 +53,17 @@ public class WordCountingApp { JavaInputDStream> messages = KafkaUtils.createDirectStream(streamingContext, LocationStrategies.PreferConsistent(), ConsumerStrategies. Subscribe(topics, kafkaParams)); - JavaPairDStream results = messages.mapToPair((PairFunction, String, String>) record -> new Tuple2<>(record.key(), record.value())); + JavaPairDStream results = messages.mapToPair(record -> new Tuple2<>(record.key(), record.value())); - JavaDStream lines = results.map((Function, String>) tuple2 -> tuple2._2()); + JavaDStream lines = results.map(tuple2 -> tuple2._2()); - JavaDStream words = lines.flatMap((FlatMapFunction) x -> Arrays.asList(x.split("\\s+")) + JavaDStream words = lines.flatMap(x -> Arrays.asList(x.split("\\s+")) .iterator()); - JavaPairDStream wordCounts = words.mapToPair((PairFunction) s -> new Tuple2<>(s, 1)) - .reduceByKey((Function2) (i1, i2) -> i1 + i2); + JavaPairDStream wordCounts = words.mapToPair(s -> new Tuple2<>(s, 1)) + .reduceByKey((i1, i2) -> i1 + i2); - wordCounts.foreachRDD((VoidFunction>) javaRdd -> { + wordCounts.foreachRDD(javaRdd -> { Map wordCountMap = javaRdd.collectAsMap(); for (String key : wordCountMap.keySet()) { List wordList = Arrays.asList(new Word(key, wordCountMap.get(key))); diff --git a/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingAppWithCheckpoint.java b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingAppWithCheckpoint.java index 79e21f7209..efbe5f3851 100644 --- a/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingAppWithCheckpoint.java +++ b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingAppWithCheckpoint.java @@ -16,15 +16,8 @@ import org.apache.log4j.Logger; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaRDD; import org.apache.spark.api.java.JavaSparkContext; -import org.apache.spark.api.java.Optional; -import org.apache.spark.api.java.function.FlatMapFunction; -import org.apache.spark.api.java.function.Function; import org.apache.spark.api.java.function.Function2; -import org.apache.spark.api.java.function.Function3; -import org.apache.spark.api.java.function.PairFunction; -import org.apache.spark.api.java.function.VoidFunction; import org.apache.spark.streaming.Durations; -import org.apache.spark.streaming.State; import org.apache.spark.streaming.StateSpec; import org.apache.spark.streaming.api.java.JavaDStream; import org.apache.spark.streaming.api.java.JavaInputDStream; @@ -71,24 +64,24 @@ public class WordCountingAppWithCheckpoint { JavaInputDStream> messages = KafkaUtils.createDirectStream(streamingContext, LocationStrategies.PreferConsistent(), ConsumerStrategies. Subscribe(topics, kafkaParams)); - JavaPairDStream results = messages.mapToPair((PairFunction, String, String>) record -> new Tuple2<>(record.key(), record.value())); + JavaPairDStream results = messages.mapToPair(record -> new Tuple2<>(record.key(), record.value())); - JavaDStream lines = results.map((Function, String>) tuple2 -> tuple2._2()); + JavaDStream lines = results.map(tuple2 -> tuple2._2()); - JavaDStream words = lines.flatMap((FlatMapFunction) x -> Arrays.asList(x.split("\\s+")) + JavaDStream words = lines.flatMap(x -> Arrays.asList(x.split("\\s+")) .iterator()); - JavaPairDStream wordCounts = words.mapToPair((PairFunction) s -> new Tuple2<>(s, 1)) + JavaPairDStream wordCounts = words.mapToPair(s -> new Tuple2<>(s, 1)) .reduceByKey((Function2) (i1, i2) -> i1 + i2); - JavaMapWithStateDStream> cumulativeWordCounts = wordCounts.mapWithState(StateSpec.function((Function3, State, Tuple2>) (word, one, state) -> { + JavaMapWithStateDStream> cumulativeWordCounts = wordCounts.mapWithState(StateSpec.function((word, one, state) -> { int sum = one.orElse(0) + (state.exists() ? state.get() : 0); Tuple2 output = new Tuple2<>(word, sum); state.update(sum); return output; })); - cumulativeWordCounts.foreachRDD((VoidFunction>>) javaRdd -> { + cumulativeWordCounts.foreachRDD(javaRdd -> { List> wordCountList = javaRdd.collect(); for (Tuple2 tuple : wordCountList) { List wordList = Arrays.asList(new Word(tuple._1, tuple._2)); From 288fc3db8af02097cd1cb7bca13aa5a2569af9de Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 10 Jan 2019 01:04:16 +0200 Subject: [PATCH 031/190] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 324f6129db..07e90cca94 100644 --- a/pom.xml +++ b/pom.xml @@ -436,7 +436,7 @@ java-collections-conversions java-collections-maps - java-ee-8-security-api + java-lite java-numbers java-rmi From c7ba38ffcd805b088e9e44d7145eb393ef162025 Mon Sep 17 00:00:00 2001 From: geroza Date: Tue, 8 Jan 2019 16:16:51 -0200 Subject: [PATCH 032/190] migrated the following modules using parent-spring-5 to spring 5.1: spring-mvc-simple spring-security-mvc-custom spring-security-mvc-login spring-security-rest spring-security-rest-basic-auth spring-static-resources spring-thymeleaf --- ethereum/pom.xml | 4 +- parent-spring-5-1/README.md | 1 + parent-spring-5-1/pom.xml | 39 +++++++++++++++++++ parent-spring-5/pom.xml | 4 +- .../spring-data-elasticsearch/pom.xml | 4 +- .../spring-data-mongodb/pom.xml | 5 +-- pom.xml | 6 +++ spring-dispatcher-servlet/pom.xml | 4 +- spring-mvc-forms-jsp/pom.xml | 4 +- spring-mvc-java/pom.xml | 4 +- spring-mvc-simple/pom.xml | 19 --------- .../java/com/baeldung/spring/MvcConfig.java | 1 - .../baeldung/client/RestTemplateFactory.java | 4 +- .../java/org/baeldung/spring/WebConfig.java | 1 - .../SpringContextIntegrationTest.java | 2 +- .../java/org/baeldung/web/FooLiveTest.java | 2 +- 16 files changed, 64 insertions(+), 40 deletions(-) create mode 100644 parent-spring-5-1/README.md create mode 100644 parent-spring-5-1/pom.xml diff --git a/ethereum/pom.xml b/ethereum/pom.xml index 85cb260670..334840edaf 100644 --- a/ethereum/pom.xml +++ b/ethereum/pom.xml @@ -7,10 +7,10 @@ ethereum - parent-spring-5 + parent-spring-5-1 com.baeldung 0.0.1-SNAPSHOT - ../parent-spring-5 + ../parent-spring-5-1 diff --git a/parent-spring-5-1/README.md b/parent-spring-5-1/README.md new file mode 100644 index 0000000000..ff12555376 --- /dev/null +++ b/parent-spring-5-1/README.md @@ -0,0 +1 @@ +## Relevant articles: diff --git a/parent-spring-5-1/pom.xml b/parent-spring-5-1/pom.xml new file mode 100644 index 0000000000..983e5e63eb --- /dev/null +++ b/parent-spring-5-1/pom.xml @@ -0,0 +1,39 @@ + + 4.0.0 + com.baeldung + parent-spring-5-1 + 0.0.1-SNAPSHOT + pom + parent-spring-5-1 + Parent for all spring 5 core modules + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.springframework + spring-core + ${spring.version} + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test + + + + + 5.0.6.RELEASE + 5.0.2 + 2.9.6 + 2.9.6 + 5.0.6.RELEASE + + + diff --git a/parent-spring-5/pom.xml b/parent-spring-5/pom.xml index 6a15f38884..51a2c1fd1f 100644 --- a/parent-spring-5/pom.xml +++ b/parent-spring-5/pom.xml @@ -29,11 +29,11 @@ - 5.0.6.RELEASE + 5.1.2.RELEASE 5.0.2 2.9.6 2.9.6 - 5.0.6.RELEASE + 5.1.2.RELEASE \ No newline at end of file diff --git a/persistence-modules/spring-data-elasticsearch/pom.xml b/persistence-modules/spring-data-elasticsearch/pom.xml index ee9e71a1cb..c5ad9b64f9 100644 --- a/persistence-modules/spring-data-elasticsearch/pom.xml +++ b/persistence-modules/spring-data-elasticsearch/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-spring-5 + parent-spring-5-1 0.0.1-SNAPSHOT - ../../parent-spring-5 + ../../parent-spring-5-1 diff --git a/persistence-modules/spring-data-mongodb/pom.xml b/persistence-modules/spring-data-mongodb/pom.xml index 63b9c3c1b0..4da0526ca6 100644 --- a/persistence-modules/spring-data-mongodb/pom.xml +++ b/persistence-modules/spring-data-mongodb/pom.xml @@ -6,9 +6,9 @@ com.baeldung - parent-spring-5 + parent-spring-5-1 0.0.1-SNAPSHOT - ../../parent-spring-5 + ../../parent-spring-5-1 @@ -99,7 +99,6 @@ 2.1.2.RELEASE 4.1.4 1.1.3 - 5.1.0.RELEASE 1.9.2 3.2.0.RELEASE diff --git a/pom.xml b/pom.xml index 324f6129db..13b866b968 100644 --- a/pom.xml +++ b/pom.xml @@ -329,6 +329,7 @@ parent-boot-2 parent-spring-4 parent-spring-5 + parent-spring-5-1 parent-java parent-kotlin @@ -600,6 +601,7 @@ parent-boot-2 parent-spring-4 parent-spring-5 + parent-spring-5-1 parent-java parent-kotlin @@ -993,6 +995,7 @@ parent-boot-2 parent-spring-4 parent-spring-5 + parent-spring-5-1 parent-java parent-kotlin @@ -1045,6 +1048,7 @@ parent-boot-2 parent-spring-4 parent-spring-5 + parent-spring-5-1 parent-java parent-kotlin @@ -1312,6 +1316,7 @@ parent-boot-2 parent-spring-4 parent-spring-5 + parent-spring-5-1 parent-java parent-kotlin @@ -1544,6 +1549,7 @@ parent-boot-2 parent-spring-4 parent-spring-5 + parent-spring-5-1 parent-java parent-kotlin diff --git a/spring-dispatcher-servlet/pom.xml b/spring-dispatcher-servlet/pom.xml index 7ac291740e..ea5eb8845e 100644 --- a/spring-dispatcher-servlet/pom.xml +++ b/spring-dispatcher-servlet/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-spring-5 + parent-spring-5-1 0.0.1-SNAPSHOT - ../parent-spring-5 + ../parent-spring-5-1 diff --git a/spring-mvc-forms-jsp/pom.xml b/spring-mvc-forms-jsp/pom.xml index 5536314086..80818f4e88 100644 --- a/spring-mvc-forms-jsp/pom.xml +++ b/spring-mvc-forms-jsp/pom.xml @@ -11,9 +11,9 @@ com.baeldung - parent-spring-5 + parent-spring-5-1 0.0.1-SNAPSHOT - ../parent-spring-5 + ../parent-spring-5-1 diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml index 9d3e0ca1b2..b0b187ee84 100644 --- a/spring-mvc-java/pom.xml +++ b/spring-mvc-java/pom.xml @@ -8,10 +8,10 @@ war - parent-spring-5 + parent-spring-5-1 com.baeldung 0.0.1-SNAPSHOT - ../parent-spring-5 + ../parent-spring-5-1 diff --git a/spring-mvc-simple/pom.xml b/spring-mvc-simple/pom.xml index 65fa4339d6..087ffea46d 100644 --- a/spring-mvc-simple/pom.xml +++ b/spring-mvc-simple/pom.xml @@ -154,25 +154,6 @@ ${deploy-path} - - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - default-test - - true - - - - - - org.junit.platform - junit-platform-surefire-provider - ${junit.platform.version} - - - spring-mvc-simple diff --git a/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java b/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java index a9c7e0cf15..082477c98c 100644 --- a/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java +++ b/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java @@ -1,7 +1,6 @@ package com.baeldung.spring; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; diff --git a/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java b/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java index 5e15648e9b..3ed0bc82b7 100644 --- a/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java +++ b/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java @@ -4,7 +4,7 @@ import org.apache.http.HttpHost; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.http.client.ClientHttpRequestFactory; -import org.springframework.http.client.support.BasicAuthorizationInterceptor; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; @@ -38,7 +38,7 @@ public class RestTemplateFactory implements FactoryBean, Initializ HttpHost host = new HttpHost("localhost", 8082, "http"); final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth(host); restTemplate = new RestTemplate(requestFactory); - restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("user1", "user1Pass")); + restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor("user1", "user1Pass")); } } \ No newline at end of file diff --git a/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java b/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java index 2305a7b6c2..5876e1307b 100644 --- a/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java +++ b/spring-security-rest-basic-auth/src/main/java/org/baeldung/spring/WebConfig.java @@ -8,7 +8,6 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration @EnableWebMvc diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java index 6cf624c179..31b3f2be87 100644 --- a/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-security-rest-basic-auth/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -6,7 +6,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration({ "/WebSecurityConfig.xml" }) +@ContextConfiguration({ "/webSecurityConfig.xml" }) public class SpringContextIntegrationTest { @Test 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 0a53da674a..86beeb46a9 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 @@ -29,7 +29,7 @@ public class FooLiveTest { // } // return RestAssured.given().cookie("JSESSIONID", cookie); return RestAssured.given() - .auth() + .auth().preemptive() .basic("user", "userPass"); } From cde1d1c7ad72c3d3608b97aa45c933b4ded0b86b Mon Sep 17 00:00:00 2001 From: geroza Date: Tue, 8 Jan 2019 17:17:28 -0200 Subject: [PATCH 033/190] Fixed usage of deprecated GzipResourceResolver in spring-static-resources added back spring-version modification in module that hasnt been worked yet cleaned unused classes --- persistence-modules/spring-data-mongodb/pom.xml | 1 + .../src/main/java/com/baeldung/spring/MvcConfig.java | 1 - .../src/main/java/org/baeldung/spring/MvcConfig.java | 6 +++--- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/persistence-modules/spring-data-mongodb/pom.xml b/persistence-modules/spring-data-mongodb/pom.xml index 4da0526ca6..86e4b275e7 100644 --- a/persistence-modules/spring-data-mongodb/pom.xml +++ b/persistence-modules/spring-data-mongodb/pom.xml @@ -96,6 +96,7 @@ + 5.1.0.RELEASE 2.1.2.RELEASE 4.1.4 1.1.3 diff --git a/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java b/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java index 082477c98c..629e203b56 100644 --- a/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java +++ b/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java @@ -1,7 +1,6 @@ package com.baeldung.spring; import org.springframework.context.annotation.Bean; -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; diff --git a/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java b/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java index dbc548e028..7bd03617be 100644 --- a/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java +++ b/spring-static-resources/src/main/java/org/baeldung/spring/MvcConfig.java @@ -18,7 +18,7 @@ import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.i18n.CookieLocaleResolver; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; -import org.springframework.web.servlet.resource.GzipResourceResolver; +import org.springframework.web.servlet.resource.EncodedResourceResolver; import org.springframework.web.servlet.resource.PathResourceResolver; import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter; import org.springframework.web.servlet.view.InternalResourceViewResolver; @@ -57,10 +57,10 @@ public class MvcConfig implements WebMvcConfigurer { public void addResourceHandlers(ResourceHandlerRegistry registry) { // For examples using Spring 4.1.0 if ((env.getProperty("resource.handler.conf")).equals("4.1.0")) { - registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(3600).resourceChain(true).addResolver(new GzipResourceResolver()).addResolver(new PathResourceResolver()); + registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(3600).resourceChain(true).addResolver(new EncodedResourceResolver()).addResolver(new PathResourceResolver()); registry.addResourceHandler("/resources/**").addResourceLocations("/resources/", "classpath:/other-resources/").setCachePeriod(3600).resourceChain(true).addResolver(new PathResourceResolver()); registry.addResourceHandler("/files/**").addResourceLocations("file:/Users/Elena/").setCachePeriod(3600).resourceChain(true).addResolver(new PathResourceResolver()); - registry.addResourceHandler("/other-files/**").addResourceLocations("file:/Users/Elena/").setCachePeriod(3600).resourceChain(true).addResolver(new GzipResourceResolver()); + registry.addResourceHandler("/other-files/**").addResourceLocations("file:/Users/Elena/").setCachePeriod(3600).resourceChain(true).addResolver(new EncodedResourceResolver()); } // For examples using Spring 4.0.7 else if ((env.getProperty("resource.handler.conf")).equals("4.0.7")) { From 74df0da304af2152a45ecf60a5f65ae77e0bc474 Mon Sep 17 00:00:00 2001 From: geroza Date: Wed, 9 Jan 2019 12:28:21 -0200 Subject: [PATCH 034/190] fixed removed import by mistake --- .../src/main/java/com/baeldung/spring/MvcConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java b/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java index 629e203b56..082477c98c 100644 --- a/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java +++ b/spring-security-mvc-login/src/main/java/com/baeldung/spring/MvcConfig.java @@ -1,6 +1,7 @@ package com.baeldung.spring; import org.springframework.context.annotation.Bean; +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; From 63258737ceb25dd435d3437920b2e8d8fff709aa Mon Sep 17 00:00:00 2001 From: geroza Date: Wed, 9 Jan 2019 13:33:39 -0200 Subject: [PATCH 035/190] modified readme file to kick off travis build --- ethereum/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ethereum/README.md b/ethereum/README.md index d06ca09636..0c7ae3d4d2 100644 --- a/ethereum/README.md +++ b/ethereum/README.md @@ -4,3 +4,4 @@ - [Introduction to EthereumJ](http://www.baeldung.com/ethereumj) - [Creating and Deploying Smart Contracts with Solidity](http://www.baeldung.com/smart-contracts-ethereum-solidity) - [Lightweight Ethereum Clients Using Web3j](http://www.baeldung.com/web3j) + From 04a4c339b767267739690c633901f911a621b46f Mon Sep 17 00:00:00 2001 From: geroza Date: Wed, 9 Jan 2019 14:53:44 -0200 Subject: [PATCH 036/190] change to kick off build --- ethereum/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/ethereum/README.md b/ethereum/README.md index 0c7ae3d4d2..d06ca09636 100644 --- a/ethereum/README.md +++ b/ethereum/README.md @@ -4,4 +4,3 @@ - [Introduction to EthereumJ](http://www.baeldung.com/ethereumj) - [Creating and Deploying Smart Contracts with Solidity](http://www.baeldung.com/smart-contracts-ethereum-solidity) - [Lightweight Ethereum Clients Using Web3j](http://www.baeldung.com/web3j) - From 39bfa04d11d34b8b3fe98deb43936854eaea9fcf Mon Sep 17 00:00:00 2001 From: geroza Date: Wed, 9 Jan 2019 23:51:39 -0200 Subject: [PATCH 037/190] change to kick off build --- ethereum/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ethereum/README.md b/ethereum/README.md index d06ca09636..7accb4cd53 100644 --- a/ethereum/README.md +++ b/ethereum/README.md @@ -4,3 +4,4 @@ - [Introduction to EthereumJ](http://www.baeldung.com/ethereumj) - [Creating and Deploying Smart Contracts with Solidity](http://www.baeldung.com/smart-contracts-ethereum-solidity) - [Lightweight Ethereum Clients Using Web3j](http://www.baeldung.com/web3j) + \ No newline at end of file From 57228dfc6b9ec1af0658f9b616056708c070bb28 Mon Sep 17 00:00:00 2001 From: Rodolfo Felipe Date: Wed, 9 Jan 2019 22:29:44 -0400 Subject: [PATCH 038/190] BAEL-2446 Unit tests for new added examples. --- .../StringReplaceAndRemoveUnitTest.java | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java b/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java index d952d2383b..d54bf09b35 100644 --- a/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java +++ b/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java @@ -1,15 +1,16 @@ package com.baeldung.string; - import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.RegExUtils; import org.junit.Test; +import com.sun.source.tree.AssertTree; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class StringReplaceAndRemoveUnitTest { - @Test public void givenTestStrings_whenReplace_thenProcessedString() { @@ -26,7 +27,7 @@ public class StringReplaceAndRemoveUnitTest { public void givenTestStrings_whenReplaceAll_thenProcessedString() { String master2 = "Welcome to Baeldung, Hello World Baeldung"; - String regexTarget= "(Baeldung)$"; + String regexTarget = "(Baeldung)$"; String replacement = "Java"; String processed2 = master2.replaceAll(regexTarget, replacement); assertTrue(processed2.endsWith("Java")); @@ -45,18 +46,16 @@ public class StringReplaceAndRemoveUnitTest { StringBuilder builder = new StringBuilder(master); - builder.delete(startIndex, stopIndex); - assertFalse(builder.toString().contains(target)); - + assertFalse(builder.toString() + .contains(target)); builder.replace(startIndex, stopIndex, replacement); - assertTrue(builder.toString().contains(replacement)); - + assertTrue(builder.toString() + .contains(replacement)); } - @Test public void givenTestStrings_whenStringUtilsMethods_thenProcessedStrings() { @@ -74,10 +73,20 @@ public class StringReplaceAndRemoveUnitTest { } + @Test + public void givenTestStrings_whenReplaceExactWord_thenProcessedString() { + String sentence = "A car is not the same as a carriage, and some planes can carry cars inside them!"; + String regexTarget = "\\bcar\\b"; + String exactWordReplaced = sentence.replaceAll(regexTarget, "truck"); + assertTrue("A truck is not the same as a carriage, and some planes can carry cars inside them!".equals(exactWordReplaced)); + } - - - - + @Test + public void givenTestStrings_whenReplaceExactWordUsingRegExUtilsMethod_thenProcessedString() { + String sentence = "A car is not the same as a carriage, and some planes can carry cars inside them!"; + String regexTarget = "\\bcar\\b"; + String exactWordReplaced = RegExUtils.replaceAll(sentence, regexTarget, "truck"); + assertTrue("A truck is not the same as a carriage, and some planes can carry cars inside them!".equals(exactWordReplaced)); + } } From 44a796b9e66aa8ff28fa464ecaca486bdbcf0277 Mon Sep 17 00:00:00 2001 From: Rodolfo Felipe Date: Wed, 9 Jan 2019 23:16:44 -0400 Subject: [PATCH 039/190] Deleting invalid package Package added by eclipse. Nonexistent. --- .../com/baeldung/string/StringReplaceAndRemoveUnitTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java b/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java index d54bf09b35..4d2b54241b 100644 --- a/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java +++ b/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java @@ -4,8 +4,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.RegExUtils; import org.junit.Test; -import com.sun.source.tree.AssertTree; - import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; From bb966c8e1461083cc6d3617242bc7cf9ac7c0fac Mon Sep 17 00:00:00 2001 From: dupirefr Date: Thu, 10 Jan 2019 08:51:53 +0100 Subject: [PATCH 040/190] [BAEL-2531] Directories creation tests --- .../directories/NewDirectoryUnitTest.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java diff --git a/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java b/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java new file mode 100644 index 0000000000..e0111c2702 --- /dev/null +++ b/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java @@ -0,0 +1,100 @@ +package com.baeldung.directories; + +import org.junit.Before; +import org.junit.Test; + +import java.io.File; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class NewDirectoryUnitTest { + + private static final File TEMP_DIRECTORY = new File(System.getProperty("java.io.tmpdir")); + + @Before + public void beforeEach() { + File newDirectory = new File(TEMP_DIRECTORY, "new_directory"); + File nestedInNewDirectory = new File(newDirectory, "nested_directory"); + File existingDirectory = new File(TEMP_DIRECTORY, "existing_directory"); + File existingNestedDirectory = new File(existingDirectory, "existing_nested_directory"); + File nestedInExistingDirectory = new File(existingDirectory, "nested_directory"); + + nestedInNewDirectory.delete(); + newDirectory.delete(); + nestedInExistingDirectory.delete(); + existingDirectory.mkdir(); + existingNestedDirectory.mkdir(); + } + + @Test + public void givenUnexistingDirectory_whenMkdir_thenTrue() { + File newDirectory = new File(TEMP_DIRECTORY, "new_directory"); + assertFalse(newDirectory.exists()); + + boolean directoryCreated = newDirectory.mkdir(); + + assertTrue(directoryCreated); + } + + @Test + public void givenExistingDirectory_whenMkdir_thenFalse() { + File newDirectory = new File(TEMP_DIRECTORY, "new_directory"); + newDirectory.mkdir(); + assertTrue(newDirectory.exists()); + + boolean directoryCreated = newDirectory.mkdir(); + + assertFalse(directoryCreated); + } + + @Test + public void givenUnexistingNestedDirectories_whenMkdir_thenFalse() { + File newDirectory = new File(TEMP_DIRECTORY, "new_directory"); + File nestedDirectory = new File(newDirectory, "nested_directory"); + assertFalse(newDirectory.exists()); + assertFalse(nestedDirectory.exists()); + + boolean directoriesCreated = nestedDirectory.mkdir(); + + assertFalse(directoriesCreated); + } + + @Test + public void givenUnexistingNestedDirectories_whenMkdirs_thenTrue() { + File newDirectory = new File(TEMP_DIRECTORY, "new_directory"); + File nestedDirectory = new File(newDirectory, "nested_directory"); + assertFalse(newDirectory.exists()); + assertFalse(nestedDirectory.exists()); + + boolean directoriesCreated = nestedDirectory.mkdirs(); + + assertTrue(directoriesCreated); + } + + @Test + public void givenExistingParentDirectories_whenMkdirs_thenTrue() { + File newDirectory = new File(TEMP_DIRECTORY, "existing_directory"); + newDirectory.mkdir(); + File nestedDirectory = new File(newDirectory, "nested_directory"); + assertTrue(newDirectory.exists()); + assertFalse(nestedDirectory.exists()); + + boolean directoriesCreated = nestedDirectory.mkdirs(); + + assertTrue(directoriesCreated); + } + + @Test + public void givenExistingNestedDirectories_whenMkdirs_thenFalse() { + File existingDirectory = new File(TEMP_DIRECTORY, "existing_directory"); + File existingNestedDirectory = new File(existingDirectory, "existing_nested_directory"); + assertTrue(existingDirectory.exists()); + assertTrue(existingNestedDirectory.exists()); + + boolean directoriesCreated = existingNestedDirectory.mkdirs(); + + assertFalse(directoriesCreated); + } + +} From 9b550e6554f0432f9e93a1f20273398909f17369 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Thu, 10 Jan 2019 15:00:38 +0400 Subject: [PATCH 041/190] localdate converter --- .../com/baeldung/util/LocalDateConverter.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java new file mode 100644 index 0000000000..341492d1fd --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java @@ -0,0 +1,25 @@ +package com.baeldung.util; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; +import java.sql.Date; +import java.time.LocalDate; +import java.util.Optional; + +@Converter(autoApply = true) +public class LocalDateConverter implements AttributeConverter { + + @Override + public Date convertToDatabaseColumn(LocalDate localDateTime) { + return Optional.ofNullable(localDateTime) + .map(Date::valueOf) + .orElse(null); + } + + @Override + public LocalDate convertToEntityAttribute(Date timestamp) { + return Optional.ofNullable(timestamp) + .map(Date::toLocalDate) + .orElse(null); + } +} \ No newline at end of file From 6202b7caab30ba5db67e992925efa60c21c2a881 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Thu, 10 Jan 2019 15:18:21 +0400 Subject: [PATCH 042/190] localdate converter --- .../main/java/com/baeldung/util/LocalDateConverter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java index 341492d1fd..00fd378b05 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java @@ -10,15 +10,15 @@ import java.util.Optional; public class LocalDateConverter implements AttributeConverter { @Override - public Date convertToDatabaseColumn(LocalDate localDateTime) { - return Optional.ofNullable(localDateTime) + public Date convertToDatabaseColumn(LocalDate localDate) { + return Optional.ofNullable(localDate) .map(Date::valueOf) .orElse(null); } @Override - public LocalDate convertToEntityAttribute(Date timestamp) { - return Optional.ofNullable(timestamp) + public LocalDate convertToEntityAttribute(Date date) { + return Optional.ofNullable(date) .map(Date::toLocalDate) .orElse(null); } From 1ca15e59190955a5bb53c1466d7aac68a8d79859 Mon Sep 17 00:00:00 2001 From: geroza Date: Wed, 9 Jan 2019 12:23:10 -0200 Subject: [PATCH 043/190] Migrated modules using parent-spring-5: ethereum persistence-modules/spring-data-elasticsearch persistence-modules/spring-data-mongodb spring-dispatcher-servlet spring-mvc-forms-jsp spring-mvc-java --- ethereum/pom.xml | 15 ++--- .../spring-data-elasticsearch/pom.xml | 4 +- .../ElasticSearchManualTest.java | 7 ++ ...ionTest.java => GeoQueriesManualTest.java} | 10 ++- ...Test.java => ElasticSearchManualTest.java} | 9 ++- ...java => ElasticSearchQueryManualTest.java} | 9 ++- ...Test.java => SpringContextManualTest.java} | 8 ++- .../spring-data-mongodb/pom.xml | 5 +- .../aggregation/ZipsAggregationLiveTest.java | 6 ++ .../com/baeldung/gridfs/GridFSLiveTest.java | 6 ++ .../mongotemplate/DocumentQueryLiveTest.java | 6 ++ .../MongoTemplateProjectionLiveTest.java | 6 ++ .../MongoTemplateQueryLiveTest.java | 6 ++ .../repository/ActionRepositoryLiveTest.java | 6 ++ .../repository/BaseQueryLiveTest.java | 6 ++ .../baeldung/repository/DSLQueryLiveTest.java | 8 ++- .../repository/JSONQueryLiveTest.java | 6 ++ .../repository/QueryMethodsLiveTest.java | 6 ++ .../repository/UserRepositoryLiveTest.java | 6 ++ .../UserRepositoryProjectionLiveTest.java | 6 ++ .../MongoTransactionReactiveLiveTest.java | 6 ++ .../MongoTransactionTemplateLiveTest.java | 6 ++ .../MongoTransactionalLiveTest.java | 6 ++ spring-4/README.md | 1 + spring-4/pom.xml | 16 +++++ .../com/baeldung/flips/ApplicationConfig.java | 8 ++- .../com/baeldung/jsonp/JsonPApplication.java | 27 ++++++++ .../com/baeldung/jsonp/model/Company.java | 38 +++++++++++ .../web/controller/CompanyController.java | 27 ++++++++ .../jsonp/web/controller/IndexController.java | 13 ++++ .../advice/JsonpControllerAdvice.java | 5 +- .../src/main/resources/application.properties | 2 +- .../resources/jsonp-application.properties | 2 + .../src/main/webapp/WEB-INF/jsp/index.jsp | 66 +++++++++++++++++++ spring-dispatcher-servlet/pom.xml | 4 +- spring-mvc-forms-jsp/pom.xml | 4 +- spring-mvc-java/README.md | 1 - spring-mvc-java/pom.xml | 20 +++++- .../web/controller/CompanyController.java | 13 ---- .../config/HandlerMappingDefaultConfig.java | 9 +-- .../com/baeldung/htmlunit/TestConfig.java | 1 - .../ClassValidationMvcIntegrationTest.java | 1 - .../GreetControllerIntegrationTest.java | 1 - 43 files changed, 366 insertions(+), 52 deletions(-) rename persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/{GeoQueriesIntegrationTest.java => GeoQueriesManualTest.java} (97%) rename persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/{ElasticSearchIntegrationTest.java => ElasticSearchManualTest.java} (97%) rename persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/{ElasticSearchQueryIntegrationTest.java => ElasticSearchQueryManualTest.java} (98%) rename persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/{SpringContextIntegrationTest.java => SpringContextManualTest.java} (77%) create mode 100644 spring-4/src/main/java/com/baeldung/jsonp/JsonPApplication.java create mode 100644 spring-4/src/main/java/com/baeldung/jsonp/model/Company.java create mode 100644 spring-4/src/main/java/com/baeldung/jsonp/web/controller/CompanyController.java create mode 100644 spring-4/src/main/java/com/baeldung/jsonp/web/controller/IndexController.java rename {spring-mvc-java/src/main/java/com/baeldung => spring-4/src/main/java/com/baeldung/jsonp}/web/controller/advice/JsonpControllerAdvice.java (53%) create mode 100644 spring-4/src/main/resources/jsonp-application.properties create mode 100644 spring-4/src/main/webapp/WEB-INF/jsp/index.jsp diff --git a/ethereum/pom.xml b/ethereum/pom.xml index 334840edaf..c7f82eaf22 100644 --- a/ethereum/pom.xml +++ b/ethereum/pom.xml @@ -7,10 +7,10 @@ ethereum - parent-spring-5-1 + parent-spring-5 com.baeldung 0.0.1-SNAPSHOT - ../parent-spring-5-1 + ../parent-spring-5 @@ -37,17 +37,17 @@ org.springframework spring-core - ${springframework.version} + ${spring.version} org.springframework spring-web - ${springframework.version} + ${spring.version} org.springframework spring-webmvc - ${springframework.version} + ${spring.version} @@ -123,12 +123,12 @@ org.springframework spring-context - ${springframework.version} + ${spring.version} org.springframework spring-test - ${springframework.version} + ${spring.version} test @@ -212,7 +212,6 @@ 8.5.4 1.5.0-RELEASE 3.3.1 - 5.0.5.RELEASE 1.5.6.RELEASE 2.21.0 2.9.7 diff --git a/persistence-modules/spring-data-elasticsearch/pom.xml b/persistence-modules/spring-data-elasticsearch/pom.xml index c5ad9b64f9..ee9e71a1cb 100644 --- a/persistence-modules/spring-data-elasticsearch/pom.xml +++ b/persistence-modules/spring-data-elasticsearch/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-spring-5-1 + parent-spring-5 0.0.1-SNAPSHOT - ../../parent-spring-5-1 + ../../parent-spring-5 diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java index fbf4e5ab99..e43dcdf43e 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java @@ -30,6 +30,13 @@ import org.junit.Test; import com.alibaba.fastjson.JSON; +/** + * + * This Manual test requires: + * * Elasticsearch instance running on host + * * with cluster name = elasticsearch + * + */ public class ElasticSearchManualTest { private List listOfPersons = new ArrayList<>(); private Client client = null; diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java similarity index 97% rename from persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesIntegrationTest.java rename to persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java index 1f55379418..f9a42050b6 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesIntegrationTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java @@ -31,9 +31,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.spring.data.es.config.Config; import com.vividsolutions.jts.geom.Coordinate; +/** + * + * This Manual test requires: + * * Elasticsearch instance running on host + * * with cluster name = elasticsearch + * * and further configurations + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = Config.class) -public class GeoQueriesIntegrationTest { +public class GeoQueriesManualTest { private static final String WONDERS_OF_WORLD = "wonders-of-world"; private static final String WONDERS = "Wonders"; diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java similarity index 97% rename from persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchIntegrationTest.java rename to persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java index 6ecb11cdbe..bed2e2ff25 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchIntegrationTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java @@ -27,9 +27,16 @@ import com.baeldung.spring.data.es.model.Article; import com.baeldung.spring.data.es.model.Author; import com.baeldung.spring.data.es.service.ArticleService; +/** + * + * This Manual test requires: + * * Elasticsearch instance running on host + * * with cluster name = elasticsearch + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = Config.class) -public class ElasticSearchIntegrationTest { +public class ElasticSearchManualTest { @Autowired private ElasticsearchTemplate elasticsearchTemplate; diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java similarity index 98% rename from persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryIntegrationTest.java rename to persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java index 2348c49830..5e24d8398c 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryIntegrationTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java @@ -41,9 +41,16 @@ import com.baeldung.spring.data.es.model.Article; import com.baeldung.spring.data.es.model.Author; import com.baeldung.spring.data.es.service.ArticleService; +/** + * + * This Manual test requires: + * * Elasticsearch instance running on host + * * with cluster name = elasticsearch + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = Config.class) -public class ElasticSearchQueryIntegrationTest { +public class ElasticSearchQueryManualTest { @Autowired private ElasticsearchTemplate elasticsearchTemplate; diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextManualTest.java similarity index 77% rename from persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextIntegrationTest.java rename to persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextManualTest.java index 6f45039c96..c6f095eae9 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/org/baeldung/SpringContextManualTest.java @@ -7,9 +7,15 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.spring.data.es.config.Config; +/** + * + * This Manual test requires: + * * Elasticsearch instance running on host + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = Config.class) -public class SpringContextIntegrationTest { +public class SpringContextManualTest { @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { diff --git a/persistence-modules/spring-data-mongodb/pom.xml b/persistence-modules/spring-data-mongodb/pom.xml index 86e4b275e7..c1faf72103 100644 --- a/persistence-modules/spring-data-mongodb/pom.xml +++ b/persistence-modules/spring-data-mongodb/pom.xml @@ -6,9 +6,9 @@ com.baeldung - parent-spring-5-1 + parent-spring-5 0.0.1-SNAPSHOT - ../../parent-spring-5-1 + ../../parent-spring-5 @@ -96,7 +96,6 @@ - 5.1.0.RELEASE 2.1.2.RELEASE 4.1.4 1.1.3 diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java index 1da50d7cb4..1002dc79eb 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java @@ -44,6 +44,12 @@ import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class ZipsAggregationLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java index 3a88a1e654..d25b9ece4f 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java @@ -31,6 +31,12 @@ import com.mongodb.BasicDBObject; import com.mongodb.DBObject; import com.mongodb.client.gridfs.model.GridFSFile; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @ContextConfiguration("file:src/main/resources/mongoConfig.xml") @RunWith(SpringJUnit4ClassRunner.class) public class GridFSLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java index d05bde0f1b..e5e4a188ec 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java @@ -24,6 +24,12 @@ import com.baeldung.config.MongoConfig; import com.baeldung.model.EmailAddress; import com.baeldung.model.User; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class DocumentQueryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java index 309f14e995..9e12997c67 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java @@ -16,6 +16,12 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SimpleMongoConfig.class) public class MongoTemplateProjectionLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java index fc78921b75..4f62f0d7a7 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java @@ -27,6 +27,12 @@ import com.baeldung.config.MongoConfig; import com.baeldung.model.EmailAddress; import com.baeldung.model.User; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class MongoTemplateQueryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java index 096015ca0a..79648f1a20 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java @@ -15,6 +15,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.time.ZoneOffset; import java.time.ZonedDateTime; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class ActionRepositoryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java index e4849181e5..c94bb2ae4c 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/BaseQueryLiveTest.java @@ -7,6 +7,12 @@ import org.junit.Before; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoOperations; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ public class BaseQueryLiveTest { @Autowired diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java index f87ca5cbb5..0ccf677b3e 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/DSLQueryLiveTest.java @@ -15,8 +15,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.querydsl.core.types.Predicate; - - +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class DSLQueryLiveTest extends BaseQueryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java index 4e99c0b140..3a99407350 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/JSONQueryLiveTest.java @@ -12,6 +12,12 @@ import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class JSONQueryLiveTest extends BaseQueryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java index 47e67a6b4c..ef8ce10dd1 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/QueryMethodsLiveTest.java @@ -12,6 +12,12 @@ import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class QueryMethodsLiveTest extends BaseQueryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java index 901610e42d..dd7215af7e 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java @@ -23,6 +23,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.config.MongoConfig; import com.baeldung.model.User; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class UserRepositoryLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java index 80f4275794..8972246041 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryProjectionLiveTest.java @@ -13,6 +13,12 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class UserRepositoryProjectionLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java index 70908552fe..3fc8dcf977 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveLiveTest.java @@ -12,6 +12,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.config.MongoReactiveConfig; import com.baeldung.model.User; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoReactiveConfig.class) public class MongoTransactionReactiveLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java index 20ac6974bc..53b2c7a0e7 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateLiveTest.java @@ -24,6 +24,12 @@ import org.springframework.transaction.support.TransactionTemplate; import com.baeldung.config.MongoConfig; import com.baeldung.model.User; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) public class MongoTransactionTemplateLiveTest { diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java index 0cf86aa43e..bafcd770ec 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalLiveTest.java @@ -24,6 +24,12 @@ import com.baeldung.model.User; import com.baeldung.repository.UserRepository; import com.mongodb.MongoCommandException; +/** + * + * This test requires: + * * mongodb instance running on the environment + * + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = MongoConfig.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/spring-4/README.md b/spring-4/README.md index 402557eb41..57cb8c3eeb 100644 --- a/spring-4/README.md +++ b/spring-4/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [A Guide to Flips for Spring](http://www.baeldung.com/flips-spring) - [Configuring a Hikari Connection Pool with Spring Boot](https://www.baeldung.com/spring-boot-hikari) +- [Spring JSON-P with Jackson](http://www.baeldung.com/spring-jackson-jsonp) diff --git a/spring-4/pom.xml b/spring-4/pom.xml index 78939bba95..60f1555d8f 100644 --- a/spring-4/pom.xml +++ b/spring-4/pom.xml @@ -52,6 +52,21 @@ provided + + javax.servlet + jstl + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.apache.tomcat.embed + tomcat-embed-jasper + provided + @@ -71,6 +86,7 @@ + com.baeldung.flips.ApplicationConfig 1.0.1 1.16.18 1.4.197 diff --git a/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java b/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java index 7001aeb991..1bd6ffa336 100644 --- a/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java +++ b/spring-4/src/main/java/com/baeldung/flips/ApplicationConfig.java @@ -3,9 +3,15 @@ package com.baeldung.flips; import org.flips.describe.config.FlipWebContextConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.context.annotation.Import; -@SpringBootApplication +@SpringBootApplication(exclude = { + DataSourceAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class, + HibernateJpaAutoConfiguration.class }) @Import(FlipWebContextConfiguration.class) public class ApplicationConfig { diff --git a/spring-4/src/main/java/com/baeldung/jsonp/JsonPApplication.java b/spring-4/src/main/java/com/baeldung/jsonp/JsonPApplication.java new file mode 100644 index 0000000000..a8f3c0e102 --- /dev/null +++ b/spring-4/src/main/java/com/baeldung/jsonp/JsonPApplication.java @@ -0,0 +1,27 @@ +package com.baeldung.jsonp; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication(exclude = { + DataSourceAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class, + HibernateJpaAutoConfiguration.class }) +@PropertySource("classpath:jsonp-application.properties") +public class JsonPApplication extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(JsonPApplication.class); + } + + public static void main(String[] args) throws Exception { + SpringApplication.run(JsonPApplication.class, args); + } +} diff --git a/spring-4/src/main/java/com/baeldung/jsonp/model/Company.java b/spring-4/src/main/java/com/baeldung/jsonp/model/Company.java new file mode 100644 index 0000000000..b11a216e52 --- /dev/null +++ b/spring-4/src/main/java/com/baeldung/jsonp/model/Company.java @@ -0,0 +1,38 @@ +package com.baeldung.jsonp.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-4/src/main/java/com/baeldung/jsonp/web/controller/CompanyController.java b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/CompanyController.java new file mode 100644 index 0000000000..8710359365 --- /dev/null +++ b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/CompanyController.java @@ -0,0 +1,27 @@ +package com.baeldung.jsonp.web.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.baeldung.jsonp.model.Company; + +@Controller +public class CompanyController { + + @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-4/src/main/java/com/baeldung/jsonp/web/controller/IndexController.java b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/IndexController.java new file mode 100644 index 0000000000..8469e19458 --- /dev/null +++ b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/IndexController.java @@ -0,0 +1,13 @@ +package com.baeldung.jsonp.web.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class IndexController { + + @RequestMapping() + public String retrieveIndex() { + return "index"; + } +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/advice/JsonpControllerAdvice.java similarity index 53% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java rename to spring-4/src/main/java/com/baeldung/jsonp/web/controller/advice/JsonpControllerAdvice.java index 7b2c6870df..be7c65cb1e 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/advice/JsonpControllerAdvice.java +++ b/spring-4/src/main/java/com/baeldung/jsonp/web/controller/advice/JsonpControllerAdvice.java @@ -1,8 +1,11 @@ -package com.baeldung.web.controller.advice; +package com.baeldung.jsonp.web.controller.advice; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice; +// AbstractJsonpResponseBodyAdvice was deprecated in favor of configuring CORS properly +// We still want to cover the usage of JSON-P in our articles, therefore we don't care that it was deprecated. +@SuppressWarnings("deprecation") @ControllerAdvice public class JsonpControllerAdvice extends AbstractJsonpResponseBodyAdvice { diff --git a/spring-4/src/main/resources/application.properties b/spring-4/src/main/resources/application.properties index 274896be15..e67700b7be 100644 --- a/spring-4/src/main/resources/application.properties +++ b/spring-4/src/main/resources/application.properties @@ -2,4 +2,4 @@ feature.foo.by.id=Y feature.new.foo=Y last.active.after=2018-03-14T00:00:00Z first.active.after=2999-03-15T00:00:00Z -logging.level.org.flips=info \ No newline at end of file +logging.level.org.flips=info diff --git a/spring-4/src/main/resources/jsonp-application.properties b/spring-4/src/main/resources/jsonp-application.properties new file mode 100644 index 0000000000..94e7fcc026 --- /dev/null +++ b/spring-4/src/main/resources/jsonp-application.properties @@ -0,0 +1,2 @@ +spring.mvc.view.prefix=/WEB-INF/jsp/ +spring.mvc.view.suffix=.jsp diff --git a/spring-4/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-4/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 0000000000..fa5498c966 --- /dev/null +++ b/spring-4/src/main/webapp/WEB-INF/jsp/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-dispatcher-servlet/pom.xml b/spring-dispatcher-servlet/pom.xml index ea5eb8845e..7ac291740e 100644 --- a/spring-dispatcher-servlet/pom.xml +++ b/spring-dispatcher-servlet/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-spring-5-1 + parent-spring-5 0.0.1-SNAPSHOT - ../parent-spring-5-1 + ../parent-spring-5 diff --git a/spring-mvc-forms-jsp/pom.xml b/spring-mvc-forms-jsp/pom.xml index 80818f4e88..5536314086 100644 --- a/spring-mvc-forms-jsp/pom.xml +++ b/spring-mvc-forms-jsp/pom.xml @@ -11,9 +11,9 @@ com.baeldung - parent-spring-5-1 + parent-spring-5 0.0.1-SNAPSHOT - ../parent-spring-5-1 + ../parent-spring-5 diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md index c7fcbd400b..851a3689ab 100644 --- a/spring-mvc-java/README.md +++ b/spring-mvc-java/README.md @@ -11,7 +11,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [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) - [Integration Testing in Spring](http://www.baeldung.com/integration-testing-in-spring) -- [Spring JSON-P with Jackson](http://www.baeldung.com/spring-jackson-jsonp) - [A Quick Guide to Spring MVC Matrix Variables](http://www.baeldung.com/spring-mvc-matrix-variables) - [Intro to WebSockets with Spring](http://www.baeldung.com/websockets-spring) - [File Upload with Spring MVC](http://www.baeldung.com/spring-file-upload) diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml index b0b187ee84..562df30318 100644 --- a/spring-mvc-java/pom.xml +++ b/spring-mvc-java/pom.xml @@ -8,10 +8,10 @@ war - parent-spring-5-1 + parent-spring-5 com.baeldung 0.0.1-SNAPSHOT - ../parent-spring-5-1 + ../parent-spring-5 @@ -60,6 +60,12 @@ commons-fileupload commons-fileupload ${commons-fileupload.version} + + + commons-io + commons-io + + net.sourceforge.htmlunit @@ -70,8 +76,17 @@ commons-logging commons-logging + + commons-io + commons-io + + + commons-io + commons-io + ${commons-io.version} + @@ -255,6 +270,7 @@ 19.0 3.5 1.3.2 + 2.5 2.2.0 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 index e92abfdc47..af1e729c13 100644 --- 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 @@ -60,17 +60,4 @@ public class CompanyController { 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/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java b/spring-mvc-java/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java index 9190d07d6b..d3a329a387 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java +++ b/spring-mvc-java/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java @@ -1,15 +1,10 @@ package com.baeldung.config; -import com.baeldung.web.controller.handlermapping.BeanNameHandlerMappingController; -import com.baeldung.web.controller.handlermapping.SimpleUrlMappingController; -import com.baeldung.web.controller.handlermapping.WelcomeController; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; -import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; -import java.util.HashMap; -import java.util.Map; +import com.baeldung.web.controller.handlermapping.BeanNameHandlerMappingController; +import com.baeldung.web.controller.handlermapping.WelcomeController; @Configuration 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 index 5b86b59095..529879fada 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java +++ b/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java @@ -9,7 +9,6 @@ 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.WebMvcConfigurer; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.thymeleaf.spring4.SpringTemplateEngine; import org.thymeleaf.spring4.view.ThymeleafViewResolver; import org.thymeleaf.templateresolver.ServletContextTemplateResolver; diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java index a86f71011c..2cd225a775 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java @@ -1,6 +1,5 @@ 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; 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 index 384bd85ec6..bce5ab0a8c 100644 --- 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 @@ -20,7 +20,6 @@ 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.WebConfig; import com.baeldung.spring.web.config.WebConfig; @RunWith(SpringJUnit4ClassRunner.class) From 8c34b3e93ba35f8d06cbda55d9e46f048997abe4 Mon Sep 17 00:00:00 2001 From: geroza Date: Wed, 9 Jan 2019 12:43:11 -0200 Subject: [PATCH 044/190] * removed temporary parent module parent-spring-5 --- parent-spring-5-1/README.md | 1 - parent-spring-5-1/pom.xml | 39 ------------------------------------- pom.xml | 6 ------ 3 files changed, 46 deletions(-) delete mode 100644 parent-spring-5-1/README.md delete mode 100644 parent-spring-5-1/pom.xml diff --git a/parent-spring-5-1/README.md b/parent-spring-5-1/README.md deleted file mode 100644 index ff12555376..0000000000 --- a/parent-spring-5-1/README.md +++ /dev/null @@ -1 +0,0 @@ -## Relevant articles: diff --git a/parent-spring-5-1/pom.xml b/parent-spring-5-1/pom.xml deleted file mode 100644 index 983e5e63eb..0000000000 --- a/parent-spring-5-1/pom.xml +++ /dev/null @@ -1,39 +0,0 @@ - - 4.0.0 - com.baeldung - parent-spring-5-1 - 0.0.1-SNAPSHOT - pom - parent-spring-5-1 - Parent for all spring 5 core modules - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - org.springframework - spring-core - ${spring.version} - - - org.junit.jupiter - junit-jupiter-engine - ${junit.jupiter.version} - test - - - - - 5.0.6.RELEASE - 5.0.2 - 2.9.6 - 2.9.6 - 5.0.6.RELEASE - - - diff --git a/pom.xml b/pom.xml index 13b866b968..324f6129db 100644 --- a/pom.xml +++ b/pom.xml @@ -329,7 +329,6 @@ parent-boot-2 parent-spring-4 parent-spring-5 - parent-spring-5-1 parent-java parent-kotlin @@ -601,7 +600,6 @@ parent-boot-2 parent-spring-4 parent-spring-5 - parent-spring-5-1 parent-java parent-kotlin @@ -995,7 +993,6 @@ parent-boot-2 parent-spring-4 parent-spring-5 - parent-spring-5-1 parent-java parent-kotlin @@ -1048,7 +1045,6 @@ parent-boot-2 parent-spring-4 parent-spring-5 - parent-spring-5-1 parent-java parent-kotlin @@ -1316,7 +1312,6 @@ parent-boot-2 parent-spring-4 parent-spring-5 - parent-spring-5-1 parent-java parent-kotlin @@ -1549,7 +1544,6 @@ parent-boot-2 parent-spring-4 parent-spring-5 - parent-spring-5-1 parent-java parent-kotlin From 2432527980d6adcd5fe77cf11857a45945b27a03 Mon Sep 17 00:00:00 2001 From: eelhazati Date: Thu, 10 Jan 2019 16:22:07 +0100 Subject: [PATCH 045/190] jpa 2.2 support for java 8 date and time types. --- persistence-modules/java-jpa/pom.xml | 31 ++- .../datetime/DateTimeEntityRepository.java | 68 +++++++ .../jpa/datetime/JPA22DateTimeEntity.java | 176 ++++++++++++++++++ .../com/baeldung/jpa/datetime/MainApp.java | 18 ++ .../main/resources/META-INF/persistence.xml | 22 ++- 5 files changed, 310 insertions(+), 5 deletions(-) create mode 100644 persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/DateTimeEntityRepository.java create mode 100644 persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/JPA22DateTimeEntity.java create mode 100644 persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/MainApp.java diff --git a/persistence-modules/java-jpa/pom.xml b/persistence-modules/java-jpa/pom.xml index ddab51a2e2..7e9c7b83f1 100644 --- a/persistence-modules/java-jpa/pom.xml +++ b/persistence-modules/java-jpa/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 java-jpa - java-jpa - + java-jpa + parent-modules com.baeldung @@ -24,10 +24,35 @@ h2 ${h2.version} + + + + javax.persistence + javax.persistence-api + 2.2 + + + + + org.eclipse.persistence + eclipselink + ${eclipselink.version} + runtime + + + org.postgresql + postgresql + ${postgres.version} + runtime + bundle + - 5.3.1.Final + 5.4.0.Final 1.4.197 + 2.7.4-RC1 + 42.2.5 + \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/DateTimeEntityRepository.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/DateTimeEntityRepository.java new file mode 100644 index 0000000000..0bd04da221 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/DateTimeEntityRepository.java @@ -0,0 +1,68 @@ +package com.baeldung.jpa.datetime; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.*; +import java.util.Calendar; + +public class DateTimeEntityRepository { + private EntityManagerFactory emf = null; + + public DateTimeEntityRepository() { + emf = Persistence.createEntityManagerFactory("java8-datetime-postgresql"); + } + + public JPA22DateTimeEntity find(Long id) { + EntityManager entityManager = emf.createEntityManager(); + + JPA22DateTimeEntity dateTimeTypes = entityManager.find(JPA22DateTimeEntity.class, id); + + entityManager.close(); + return dateTimeTypes; + } + + public void save(Long id) { + JPA22DateTimeEntity dateTimeTypes = new JPA22DateTimeEntity(); + dateTimeTypes.setId(id); + + //java.sql types: date/time + dateTimeTypes.setSqlTime(Time.valueOf(LocalTime.now())); + dateTimeTypes.setSqlDate(Date.valueOf(LocalDate.now())); + dateTimeTypes.setSqlTimestamp(Timestamp.valueOf(LocalDateTime.now())); + + //java.util types: date/calendar + java.util.Date date = new java.util.Date(); + dateTimeTypes.setUtilTime(date); + dateTimeTypes.setUtilDate(date); + dateTimeTypes.setUtilTimestamp(date); + + //Calendar + Calendar calendar = Calendar.getInstance(); + dateTimeTypes.setCalendarTime(calendar); + dateTimeTypes.setCalendarDate(calendar); + dateTimeTypes.setCalendarTimestamp(calendar); + + //java.time types + dateTimeTypes.setLocalTime(LocalTime.now()); + dateTimeTypes.setLocalDate(LocalDate.now()); + dateTimeTypes.setLocalDateTime(LocalDateTime.now()); + + //java.time types with offset + dateTimeTypes.setOffsetTime(OffsetTime.now()); + dateTimeTypes.setOffsetDateTime(OffsetDateTime.now()); + + EntityManager entityManager = emf.createEntityManager(); + entityManager.getTransaction().begin(); + entityManager.persist(dateTimeTypes); + entityManager.getTransaction().commit(); + entityManager.close(); + } + + public void clean() { + emf.close(); + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/JPA22DateTimeEntity.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/JPA22DateTimeEntity.java new file mode 100644 index 0000000000..065385bd86 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/JPA22DateTimeEntity.java @@ -0,0 +1,176 @@ +package com.baeldung.jpa.datetime; + +import javax.persistence.*; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.time.*; +import java.util.Calendar; + +@Entity +public class JPA22DateTimeEntity { + + @Id + private Long id; + + //java.sql types + private Time sqlTime; + private Date sqlDate; + private Timestamp sqlTimestamp; + + //java.util types + @Temporal(TemporalType.TIME) + private java.util.Date utilTime; + + @Temporal(TemporalType.DATE) + private java.util.Date utilDate; + + @Temporal(TemporalType.TIMESTAMP) + private java.util.Date utilTimestamp; + + //Calendar + @Temporal(TemporalType.TIME) + private Calendar calendarTime; + + @Temporal(TemporalType.DATE) + private Calendar calendarDate; + + @Temporal(TemporalType.TIMESTAMP) + private Calendar calendarTimestamp; + + // java.time types + @Column(name = "local_time", columnDefinition = "TIME") + private LocalTime localTime; + + @Column(name = "local_date", columnDefinition = "DATE") + private LocalDate localDate; + + @Column(name = "local_date_time", columnDefinition = "TIMESTAMP") + private LocalDateTime localDateTime; + + @Column(name = "offset_time", columnDefinition = "TIME WITH TIME ZONE") + private OffsetTime offsetTime; + + @Column(name = "offset_date_time", columnDefinition = "TIMESTAMP WITH TIME ZONE") + private OffsetDateTime offsetDateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Time getSqlTime() { + return sqlTime; + } + + public void setSqlTime(Time sqlTime) { + this.sqlTime = sqlTime; + } + + public Date getSqlDate() { + return sqlDate; + } + + public void setSqlDate(Date sqlDate) { + this.sqlDate = sqlDate; + } + + public Timestamp getSqlTimestamp() { + return sqlTimestamp; + } + + public void setSqlTimestamp(Timestamp sqlTimestamp) { + this.sqlTimestamp = sqlTimestamp; + } + + public java.util.Date getUtilTime() { + return utilTime; + } + + public void setUtilTime(java.util.Date utilTime) { + this.utilTime = utilTime; + } + + public java.util.Date getUtilDate() { + return utilDate; + } + + public void setUtilDate(java.util.Date utilDate) { + this.utilDate = utilDate; + } + + public java.util.Date getUtilTimestamp() { + return utilTimestamp; + } + + public void setUtilTimestamp(java.util.Date utilTimestamp) { + this.utilTimestamp = utilTimestamp; + } + + public Calendar getCalendarTime() { + return calendarTime; + } + + public void setCalendarTime(Calendar calendarTime) { + this.calendarTime = calendarTime; + } + + public Calendar getCalendarDate() { + return calendarDate; + } + + public void setCalendarDate(Calendar calendarDate) { + this.calendarDate = calendarDate; + } + + public Calendar getCalendarTimestamp() { + return calendarTimestamp; + } + + public void setCalendarTimestamp(Calendar calendarTimestamp) { + this.calendarTimestamp = calendarTimestamp; + } + + public LocalTime getLocalTime() { + return localTime; + } + + public void setLocalTime(LocalTime localTime) { + this.localTime = localTime; + } + + public LocalDate getLocalDate() { + return localDate; + } + + public void setLocalDate(LocalDate localDate) { + this.localDate = localDate; + } + + public LocalDateTime getLocalDateTime() { + return localDateTime; + } + + public void setLocalDateTime(LocalDateTime localDateTime) { + this.localDateTime = localDateTime; + } + + public OffsetTime getOffsetTime() { + return offsetTime; + } + + public void setOffsetTime(OffsetTime offsetTime) { + this.offsetTime = offsetTime; + } + + public OffsetDateTime getOffsetDateTime() { + return offsetDateTime; + } + + public void setOffsetDateTime(OffsetDateTime offsetDateTime) { + this.offsetDateTime = offsetDateTime; + } +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/MainApp.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/MainApp.java new file mode 100644 index 0000000000..7f23f44254 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/datetime/MainApp.java @@ -0,0 +1,18 @@ +package com.baeldung.jpa.datetime; + +public class MainApp { + + public static void main(String... args) { + + DateTimeEntityRepository dateTimeEntityRepository = new DateTimeEntityRepository(); + + //Persist + dateTimeEntityRepository.save(100L); + + //Find + JPA22DateTimeEntity dateTimeEntity = dateTimeEntityRepository.find(100L); + + dateTimeEntityRepository.clean(); + } + +} \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml index 433d456cc9..9e4f4bf4c9 100644 --- a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml @@ -2,8 +2,8 @@ + http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd" + version="2.2"> org.hibernate.jpa.HibernatePersistenceProvider @@ -66,4 +66,22 @@
+ + org.eclipse.persistence.jpa.PersistenceProvider + com.baeldung.jpa.datetime.JPA22DateTimeEntity + true + + + + + + + + + + + + + + \ No newline at end of file From 3907f624b57bf9314ec8a9bf73d354685ff50a80 Mon Sep 17 00:00:00 2001 From: eelhazati Date: Thu, 10 Jan 2019 16:36:52 +0100 Subject: [PATCH 046/190] jpa 2.2 support for java 8 date and time types. --- persistence-modules/java-jpa/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/persistence-modules/java-jpa/pom.xml b/persistence-modules/java-jpa/pom.xml index 7e9c7b83f1..fa47d6bd9c 100644 --- a/persistence-modules/java-jpa/pom.xml +++ b/persistence-modules/java-jpa/pom.xml @@ -44,7 +44,6 @@ postgresql ${postgres.version} runtime - bundle
From 1c6dba97187e598e25219291408b87be6dd8e793 Mon Sep 17 00:00:00 2001 From: eelhazati Date: Thu, 10 Jan 2019 16:50:29 +0100 Subject: [PATCH 047/190] excludes jpa entities. --- .../java-jpa/src/main/resources/META-INF/persistence.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml index 9e4f4bf4c9..f7258e3109 100644 --- a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml @@ -8,6 +8,8 @@ org.hibernate.jpa.HibernatePersistenceProvider com.baeldung.sqlresultsetmapping.ScheduledDay + com.baeldung.sqlresultsetmapping.Employee + true Date: Thu, 10 Jan 2019 17:08:47 +0100 Subject: [PATCH 048/190] exludes jpa entities. --- .../java-jpa/src/main/resources/META-INF/persistence.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml index f7258e3109..8592fce533 100644 --- a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml @@ -26,6 +26,7 @@ org.hibernate.jpa.HibernatePersistenceProvider com.baeldung.jpa.stringcast.Message + true @@ -41,6 +42,7 @@ org.hibernate.jpa.HibernatePersistenceProvider com.baeldung.jpa.model.Car + true From 94c146e245c78b2ddaf941f0f6e43fb1eff3a1b4 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Thu, 10 Jan 2019 14:21:27 -0200 Subject: [PATCH 049/190] just to trigger the Travis build --- ethereum/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/README.md b/ethereum/README.md index 7accb4cd53..0c7ae3d4d2 100644 --- a/ethereum/README.md +++ b/ethereum/README.md @@ -4,4 +4,4 @@ - [Introduction to EthereumJ](http://www.baeldung.com/ethereumj) - [Creating and Deploying Smart Contracts with Solidity](http://www.baeldung.com/smart-contracts-ethereum-solidity) - [Lightweight Ethereum Clients Using Web3j](http://www.baeldung.com/web3j) - \ No newline at end of file + From 4fb05ab3a27bc4267db4d344a3987e875d55537d Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 10 Jan 2019 21:22:46 +0200 Subject: [PATCH 050/190] Update pom.xml --- java-numbers/pom.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/java-numbers/pom.xml b/java-numbers/pom.xml index bb63c8cfe1..0f5140ea5e 100644 --- a/java-numbers/pom.xml +++ b/java-numbers/pom.xml @@ -72,16 +72,6 @@ - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*IntegrationTest.java - - true - - org.apache.maven.plugins From dfbff7aa19384117e758e12ae1eab870d183f097 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 10 Jan 2019 21:32:08 +0200 Subject: [PATCH 051/190] Update pom.xml --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 07e90cca94..a9b4b3f119 100644 --- a/pom.xml +++ b/pom.xml @@ -232,6 +232,7 @@ ${maven-war-plugin.version} + com.vackosar.gitflowincrementalbuilder From a15045f8a7f46a72268a088e4d0c7943cd17b456 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Thu, 10 Jan 2019 18:17:59 -0200 Subject: [PATCH 052/190] edit readme to trigger travis build --- ethereum/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/ethereum/README.md b/ethereum/README.md index 0c7ae3d4d2..d06ca09636 100644 --- a/ethereum/README.md +++ b/ethereum/README.md @@ -4,4 +4,3 @@ - [Introduction to EthereumJ](http://www.baeldung.com/ethereumj) - [Creating and Deploying Smart Contracts with Solidity](http://www.baeldung.com/smart-contracts-ethereum-solidity) - [Lightweight Ethereum Clients Using Web3j](http://www.baeldung.com/web3j) - From 7f501f169f7f7d22362e7e28cdb1331ad020ef55 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 10 Jan 2019 22:32:12 +0200 Subject: [PATCH 053/190] Update Circle.java --- core-java/src/main/java/com/baeldung/keyword/Circle.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java/src/main/java/com/baeldung/keyword/Circle.java b/core-java/src/main/java/com/baeldung/keyword/Circle.java index 4ec91d1b8a..231b2f5a59 100644 --- a/core-java/src/main/java/com/baeldung/keyword/Circle.java +++ b/core-java/src/main/java/com/baeldung/keyword/Circle.java @@ -1,4 +1,5 @@ package com.baeldung.keyword; public class Circle extends Round implements Shape { + } From b8dbc9d053a6f56eb2884baa7c811b713ce7a2ae Mon Sep 17 00:00:00 2001 From: Laurentiu Delcea Date: Thu, 10 Jan 2019 23:21:06 +0200 Subject: [PATCH 054/190] BAEL-2480 Java Map to String conversion (#6075) * BAEL-2480 Java Map to String conversion * BAEL-2480 Java Map to String conversion * BAEL-2480 Java Map to String conversion * BAEL-2480 Java Map to String conversion --- .../com/baeldung/convert/MapToString.java | 34 +++++++++++++ .../com/baeldung/convert/StringToMap.java | 21 ++++++++ .../baeldung/convert/MapToStringUnitTest.java | 48 +++++++++++++++++++ .../baeldung/convert/StringToMapUnitTest.java | 23 +++++++++ 4 files changed, 126 insertions(+) create mode 100644 java-collections-maps/src/main/java/com/baeldung/convert/MapToString.java create mode 100644 java-collections-maps/src/main/java/com/baeldung/convert/StringToMap.java create mode 100644 java-collections-maps/src/test/java/com/baeldung/convert/MapToStringUnitTest.java create mode 100644 java-collections-maps/src/test/java/com/baeldung/convert/StringToMapUnitTest.java diff --git a/java-collections-maps/src/main/java/com/baeldung/convert/MapToString.java b/java-collections-maps/src/main/java/com/baeldung/convert/MapToString.java new file mode 100644 index 0000000000..aca0d05ef1 --- /dev/null +++ b/java-collections-maps/src/main/java/com/baeldung/convert/MapToString.java @@ -0,0 +1,34 @@ +package com.baeldung.convert; + +import com.google.common.base.Joiner; +import org.apache.commons.lang3.StringUtils; + +import java.util.Map; +import java.util.stream.Collectors; + +public class MapToString { + + public static String convertWithIteration(Map map) { + StringBuilder mapAsString = new StringBuilder("{"); + for (Integer key : map.keySet()) { + mapAsString.append(key + "=" + map.get(key) + ", "); + } + mapAsString.delete(mapAsString.length()-2, mapAsString.length()).append("}"); + return mapAsString.toString(); + } + + public static String convertWithStream(Map map) { + String mapAsString = map.keySet().stream() + .map(key -> key + "=" + map.get(key)) + .collect(Collectors.joining(", ", "{", "}")); + return mapAsString; + } + + public static String convertWithGuava(Map map) { + return Joiner.on(",").withKeyValueSeparator("=").join(map); + } + + public static String convertWithApache(Map map) { + return StringUtils.join(map); + } +} diff --git a/java-collections-maps/src/main/java/com/baeldung/convert/StringToMap.java b/java-collections-maps/src/main/java/com/baeldung/convert/StringToMap.java new file mode 100644 index 0000000000..caabca4a09 --- /dev/null +++ b/java-collections-maps/src/main/java/com/baeldung/convert/StringToMap.java @@ -0,0 +1,21 @@ +package com.baeldung.convert; + +import com.google.common.base.Splitter; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +public class StringToMap { + + public static Map convertWithStream(String mapAsString) { + Map map = Arrays.stream(mapAsString.split(",")) + .map(entry -> entry.split("=")) + .collect(Collectors.toMap(entry -> entry[0], entry -> entry[1])); + return map; + } + + public static Map convertWithGuava(String mapAsString) { + return Splitter.on(',').withKeyValueSeparator('=').split(mapAsString); + } +} diff --git a/java-collections-maps/src/test/java/com/baeldung/convert/MapToStringUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/convert/MapToStringUnitTest.java new file mode 100644 index 0000000000..d9923e74a0 --- /dev/null +++ b/java-collections-maps/src/test/java/com/baeldung/convert/MapToStringUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.convert; + +import org.apache.commons.collections4.MapUtils; +import org.junit.Assert; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class MapToStringUnitTest { + + private Map wordsByKey = new HashMap<>(); + + @BeforeEach + public void setup() { + wordsByKey.clear(); + wordsByKey.put(1, "one"); + wordsByKey.put(2, "two"); + wordsByKey.put(3, "three"); + wordsByKey.put(4, "four"); + } + + @Test + public void givenMap_WhenUsingIteration_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithIteration(wordsByKey); + Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); + } + + @Test + public void givenMap_WhenUsingStream_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithStream(wordsByKey); + Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); + } + + @Test + public void givenMap_WhenUsingGuava_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithGuava(wordsByKey); + Assert.assertEquals("1=one,2=two,3=three,4=four", mapAsString); + } + + @Test + public void givenMap_WhenUsingApache_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithApache(wordsByKey); + Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); + MapUtils.debugPrint(System.out, "Map as String", wordsByKey); + } +} \ No newline at end of file diff --git a/java-collections-maps/src/test/java/com/baeldung/convert/StringToMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/convert/StringToMapUnitTest.java new file mode 100644 index 0000000000..8fb906efd0 --- /dev/null +++ b/java-collections-maps/src/test/java/com/baeldung/convert/StringToMapUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.convert; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +public class StringToMapUnitTest { + + @Test + public void givenString_WhenUsingStream_ThenResultingStringIsCorrect() { + Map wordsByKey = StringToMap.convertWithStream("1=one,2=two,3=three,4=four"); + Assert.assertEquals(4, wordsByKey.size()); + Assert.assertEquals("one", wordsByKey.get("1")); + } + + @Test + void givenString_WhenUsingGuava_ThenResultingStringIsCorrect() { + Map wordsByKey = StringToMap.convertWithGuava("1=one,2=two,3=three,4=four"); + Assert.assertEquals(4, wordsByKey.size()); + Assert.assertEquals("one", wordsByKey.get("1")); + } +} \ No newline at end of file From c65180c74f75f2cbb0d21b787d12b9098865a703 Mon Sep 17 00:00:00 2001 From: Emily Cheyne Date: Thu, 10 Jan 2019 15:05:00 -0700 Subject: [PATCH 055/190] BAEL-2535 Remove CustomerReflectionToStringUnitTest --- .../CustomerReflectionToStringUnitTest.java | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 java-strings/src/test/java/com/baeldung/string/tostring/CustomerReflectionToStringUnitTest.java diff --git a/java-strings/src/test/java/com/baeldung/string/tostring/CustomerReflectionToStringUnitTest.java b/java-strings/src/test/java/com/baeldung/string/tostring/CustomerReflectionToStringUnitTest.java deleted file mode 100644 index 77dcab52e6..0000000000 --- a/java-strings/src/test/java/com/baeldung/string/tostring/CustomerReflectionToStringUnitTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.string.tostring; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.jupiter.api.Test; - -public class CustomerReflectionToStringUnitTest { - private static final String CUSTOMER_REFLECTION_TO_STRING = "com.baeldung.string.tostring.CustomerReflectionToString"; - - @Test - public void givenWrapperCollectionStrBuffer_whenReflectionToString_thenCustomerDetails() { - CustomerReflectionToString customer = new CustomerReflectionToString(); - customer.setFirstName("Rajesh"); - customer.setLastName("Bhojwani"); - customer.setScore(8); - - List orders = new ArrayList(); - orders.add("Book"); - orders.add("Pen"); - customer.setOrders(orders); - - StringBuffer fullname = new StringBuffer(); - fullname.append(customer.getLastName()+", "+ customer.getFirstName()); - customer.setFullname(fullname); - - assertTrue(customer.toString().contains(CUSTOMER_REFLECTION_TO_STRING)); - } - -} From c5415eecac1322a79f30e6ecf9bcd946d231233d Mon Sep 17 00:00:00 2001 From: "Erick Audet M.Sc" Date: Thu, 10 Jan 2019 17:16:53 -0500 Subject: [PATCH 056/190] BAEL-2059 * New section in InputStream to byte array article and recreating branch. * Minor typo * Code reformat using intellij formatter. * Code reformat using intellij formatter. * guava implementation to be completed * guava implementation * Added assert to guava test * Fix formatting --- .../io/InputStreamToByteBufferUnitTest.java | 60 ++++++++++++++++++ .../resources/frontenac-2257154_960_720.jpg | Bin 0 -> 194684 bytes parent-java/pom.xml | 4 +- 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java create mode 100644 core-java-io/src/test/resources/frontenac-2257154_960_720.jpg diff --git a/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java b/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java new file mode 100644 index 0000000000..fedadde04b --- /dev/null +++ b/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java @@ -0,0 +1,60 @@ +package org.baeldung.java.io; + + +import com.google.common.io.ByteStreams; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class InputStreamToByteBufferUnitTest { + + @Test + public void givenUsingCoreClasses_whenWritingAFileIntoAByteBuffer_thenBytesLengthMustMatch() throws IOException { + File inputFile = getFile(); + ByteBuffer bufferByte = ByteBuffer.allocate((int) inputFile.length()); + FileInputStream in = new FileInputStream(inputFile); + in.getChannel().read(bufferByte); + + assertEquals(bufferByte.position(), inputFile.length()); + } + + @Test + public void givenUsingCommonsIo_whenWritingAFileIntoAByteBuffer_thenBytesLengthMustMatch() throws IOException { + File inputFile = getFile(); + ByteBuffer bufferByte = ByteBuffer.allocateDirect((int) inputFile.length()); + ReadableByteChannel readableByteChannel = new FileInputStream(inputFile).getChannel(); + IOUtils.readFully(readableByteChannel, bufferByte); + + assertEquals(bufferByte.position(), inputFile.length()); + } + + @Test + public void givenUsingGuava_whenWritingAFileIntoAByteBuffer_thenBytesLengthMustMatch() throws IOException { + File inputFile = getFile(); + FileInputStream in = new FileInputStream(inputFile); + byte[] targetArray = ByteStreams.toByteArray(in); + ByteBuffer bufferByte = ByteBuffer.wrap(targetArray); + bufferByte.rewind(); + while (bufferByte.hasRemaining()) { + bufferByte.get(); + } + + assertEquals(bufferByte.position(), inputFile.length()); + } + + private File getFile() { + ClassLoader classLoader = new InputStreamToByteBufferUnitTest().getClass().getClassLoader(); + + String fileName = "frontenac-2257154_960_720.jpg"; + + return new File(classLoader.getResource(fileName).getFile()); + } + +} diff --git a/core-java-io/src/test/resources/frontenac-2257154_960_720.jpg b/core-java-io/src/test/resources/frontenac-2257154_960_720.jpg new file mode 100644 index 0000000000000000000000000000000000000000..77c459b0e39604cbac6d0bd59e6ef3fceb22061b GIT binary patch literal 194684 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 - 22.0 + 23.0 - \ No newline at end of file + From c4edb95d4ef6733a1e520249861950743c0fa54c Mon Sep 17 00:00:00 2001 From: Olaniyi Anjola Date: Thu, 10 Jan 2019 18:51:30 -0500 Subject: [PATCH 057/190] BAEL-2452: Using curl from Java (#6113) * Renamed from Unit Test to Live Test * Update JavaCurlExamplesLiveTest.java --- ...est.java => JavaCurlExamplesLiveTest.java} | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) rename core-java/src/test/java/com/baeldung/curltojava/{JavaCurlExamplesUnitTest.java => JavaCurlExamplesLiveTest.java} (56%) diff --git a/core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesUnitTest.java b/core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesLiveTest.java similarity index 56% rename from core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesUnitTest.java rename to core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesLiveTest.java index 4e82059f2b..2ec62cbbf9 100644 --- a/core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesUnitTest.java +++ b/core-java/src/test/java/com/baeldung/curltojava/JavaCurlExamplesLiveTest.java @@ -3,19 +3,16 @@ package com.baeldung.curltojava; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; import org.junit.Assert; import org.junit.Test; -public class JavaCurlExamplesUnitTest { - +public class JavaCurlExamplesLiveTest { @Test public void givenCommand_whenCalled_thenProduceZeroExitCode() throws IOException { - String command = "curl --location --request GET \"https://postman-echo.com/get?foo1=bar1&foo2=bar2\""; - ProcessBuilder processBuilder = new ProcessBuilder(command.replaceAll("\"", "").split(" ")); + String command = "curl -X GET https://postman-echo.com/get?foo1=bar1&foo2=bar2"; + ProcessBuilder processBuilder = new ProcessBuilder(command.split(" ")); processBuilder.directory(new File("/home/")); Process process = processBuilder.start(); InputStream inputStream = process.getInputStream(); @@ -28,8 +25,8 @@ public class JavaCurlExamplesUnitTest { @Test public void givenNewCommands_whenCalled_thenCheckIfIsAlive() throws IOException { - String command = "curl --location --request GET \"https://postman-echo.com/get?foo1=bar1&foo2=bar2\""; - ProcessBuilder processBuilder = new ProcessBuilder(command.replaceAll("\"", "").split(" ")); + String command = "curl -X GET https://postman-echo.com/get?foo1=bar1&foo2=bar2"; + ProcessBuilder processBuilder = new ProcessBuilder(command.split(" ")); processBuilder.directory(new File("/home/")); Process process = processBuilder.start(); @@ -40,16 +37,14 @@ public class JavaCurlExamplesUnitTest { } @Test - public void whenRequestGet_thenReturnSuccessResponseCode() throws IOException { - String url = "https://postman-echo.com/get?foo1=bar1&foo2=bar2"; - URL urlObj = new URL(url); - HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection(); - connection.setDoOutput(true); - connection.setInstanceFollowRedirects(false); - connection.setRequestMethod("GET"); - connection.connect(); + public void whenRequestPost_thenCheckIfReturnContent() throws IOException { + String command = "curl -X POST https://postman-echo.com/post --data foo1=bar1&foo2=bar2"; + Process process = Runtime.getRuntime().exec(command); - Assert.assertEquals(HttpURLConnection.HTTP_OK, connection.getResponseCode()); + // Get the POST result + String content = JavaCurlExamples.inputStreamToString(process.getInputStream()); + + Assert.assertTrue(null != content && !content.isEmpty()); } } From ea5039f1a197156e9cb4686f6bd42e9659044e56 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Fri, 11 Jan 2019 15:05:34 +0400 Subject: [PATCH 058/190] indexOf changed example --- .../java/com/baeldung/string/MatchWords.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index c0f89b635d..f0b64c19cf 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -20,24 +20,19 @@ public class MatchWords { ahoCorasick(); - wordIndices(inputString); + indexOfWords(inputString, items); } - private static void wordIndices(String inputString) { - Map wordIndices = new TreeMap<>(); - List words = new ArrayList<>(); - words.add("hello"); - words.add("Baeldung"); - + private static boolean indexOfWords(String inputString, String[] words) { + boolean found = true; for (String word : words) { int index = inputString.indexOf(word); - - if (index != -1) { - wordIndices.put(index, word); + if (index == -1) { + found = false; + break; } } - - wordIndices.keySet().forEach(System.out::println); + return found; } private static boolean containsWords(String inputString, String[] items) { From 36e48924468b9030ec382bf537084635785fc5e1 Mon Sep 17 00:00:00 2001 From: Upendra Chintala Date: Fri, 11 Jan 2019 18:13:27 +0530 Subject: [PATCH 059/190] Check if a year/date is a leap year in Java (#6086) * Hexagonal architecture implementation in Java - upendra.chintala@gmail.com * An example program to find a leap year using java 8 java.time.Year API * Changed to add assertions * Remvoed evaluation article code * Added unit test suite for leap year testing using java.time.Year and java.util.GregorianCalendar * Update LeapYearUnitTest.java * Update LeapYearUnitTest.java --- .../baeldung/leapyear/LeapYearUnitTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java b/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java new file mode 100644 index 0000000000..9fb3d03838 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.leapyear; + +import java.time.Year; +import java.util.GregorianCalendar; + +import org.junit.Assert; +import org.junit.Test; + +public class LeapYearUnitTest { + + //Before Java8 + @Test + public void testLeapYearUsingGregorianCalendar () { + Assert.assertFalse(new GregorianCalendar().isLeapYear(2018)); + } + + //Java 8 and above + @Test + public void testLeapYearUsingJavaTimeYear () { + Assert.assertTrue(Year.isLeap(2012)); + } + + @Test + public void testBCYearUsingJavaTimeYear () { + Assert.assertTrue(Year.isLeap(-4)); + } + + @Test + public void testWrongLeapYearUsingJavaTimeYear () { + Assert.assertFalse(Year.isLeap(2018)); + } + + @Test + public void testLeapYearInDateUsingJavaTimeYear () { + LocalDate date = LocalDate.parse("2020-01-05", DateTimeFormatter.ISO_LOCAL_DATE); + Assert.assertTrue(Year.from(date).isLeap()); + } + +} From 583969b59d09e3a975e3da06823270a217103e41 Mon Sep 17 00:00:00 2001 From: Amy DeGregorio Date: Fri, 11 Jan 2019 13:28:10 -0500 Subject: [PATCH 060/190] BAEL-2499 Write to CSV in Java - Updated PR (#6122) * example code for Article How to Write to a CSV File in Java * Updated to use a Stream --- .../com/baeldung/csv/WriteCsvFileExample.java | 7 ++----- .../csv/WriteCsvFileExampleUnitTest.java | 20 +++++++------------ 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java b/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java index fd3678d2c5..e1237481b1 100644 --- a/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java +++ b/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java @@ -1,11 +1,8 @@ package com.baeldung.csv; -import java.io.BufferedWriter; -import java.io.IOException; - public class WriteCsvFileExample { - public void writeLine(BufferedWriter writer, String[] data) throws IOException { + public String convertToCSV(String[] data) { StringBuilder csvLine = new StringBuilder(); for (int i = 0; i < data.length; i++) { @@ -15,7 +12,7 @@ public class WriteCsvFileExample { csvLine.append(escapeSpecialCharacters(data[i])); } - writer.write(csvLine.toString()); + return csvLine.toString(); } public String escapeSpecialCharacters(String data) { diff --git a/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java b/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java index 4ac84f939d..e30ec0818c 100644 --- a/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java +++ b/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java @@ -3,12 +3,10 @@ package com.baeldung.csv; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.io.BufferedWriter; import java.io.File; -import java.io.FileWriter; -import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import org.junit.Before; @@ -73,15 +71,11 @@ public class WriteCsvFileExampleUnitTest { dataLines.add(new String[] { "Jane", "Doe, Jr.", "19", "She said \"I'm being quoted\"" }); File csvOutputFile = new File(CSV_FILE_NAME); - try (BufferedWriter writer = new BufferedWriter(new FileWriter(csvOutputFile))) { - for (Iterator dataIterator = dataLines.iterator(); dataIterator.hasNext();) { - csvExample.writeLine(writer, dataIterator.next()); - if (dataIterator.hasNext()) { - writer.newLine(); - } - } - writer.flush(); - } catch (IOException e) { + try (PrintWriter pw = new PrintWriter(csvOutputFile)) { + dataLines.stream() + .map(csvExample::convertToCSV) + .forEach(pw::println); + } catch (FileNotFoundException e) { LOG.error("IOException " + e.getMessage()); } From 39f2baab28db45f97309b7cb01e76dcf52227d60 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Fri, 11 Jan 2019 21:25:58 +0200 Subject: [PATCH 061/190] Update LoopScopeExample.java --- core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java b/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java index 2dd3be3333..04414067ad 100644 --- a/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java +++ b/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java @@ -12,7 +12,6 @@ public class LoopScopeExample { for (String name : listOfNames) { allNames = allNames + " " + name; } - } } From 4b47306e913180c1c4da86f6f507a3d1724b28f5 Mon Sep 17 00:00:00 2001 From: Emily Cheyne Date: Fri, 11 Jan 2019 12:48:28 -0700 Subject: [PATCH 062/190] BAEL-2535 --- java-strings/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java-strings/README.md b/java-strings/README.md index 08fbec35ab..b72a378d06 100644 --- a/java-strings/README.md +++ b/java-strings/README.md @@ -49,3 +49,4 @@ - [Add a Character to a String at a Given Position](https://www.baeldung.com/java-add-character-to-string) - [Remove Leading and Trailing Characters from a String](https://www.baeldung.com/java-remove-trailing-characters) - [Concatenating Strings In Java](https://www.baeldung.com/java-strings-concatenation) +- [Java toString() Method](https://www.baeldung.com/java-tostring) From 2cb4faddb0edf2f05edb8d2cc77560e6205396fc Mon Sep 17 00:00:00 2001 From: Loredana Date: Fri, 11 Jan 2019 23:03:38 +0200 Subject: [PATCH 063/190] fix core-java test and back to build --- core-java/pom.xml | 1 + .../src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java | 2 ++ pom.xml | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core-java/pom.xml b/core-java/pom.xml index 6c58653d5a..d21c624997 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -13,6 +13,7 @@ ../parent-java + commons-io diff --git a/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java b/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java index 9fb3d03838..e710eecc66 100644 --- a/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java +++ b/core-java/src/test/java/com/baeldung/leapyear/LeapYearUnitTest.java @@ -1,6 +1,8 @@ package com.baeldung.leapyear; +import java.time.LocalDate; import java.time.Year; +import java.time.format.DateTimeFormatter; import java.util.GregorianCalendar; import org.junit.Assert; diff --git a/pom.xml b/pom.xml index a9b4b3f119..1c0738cafb 100644 --- a/pom.xml +++ b/pom.xml @@ -391,6 +391,7 @@ core-java-networking core-java-perf core-java-sun + core-java core-scala couchbase custom-pmd @@ -996,8 +997,7 @@ parent-spring-5 parent-java parent-kotlin - - core-java + core-java-concurrency-advanced core-kotlin From 469e36f07a93156664dd05dfb7efee58a7689c6b Mon Sep 17 00:00:00 2001 From: Juan Moreno Date: Sat, 12 Jan 2019 15:59:25 -0300 Subject: [PATCH 064/190] BAEL-2444 Extra examples (#6087) --- .../com/baeldung/time/InstantUnitTest.java | 42 +++++++++++++++++ .../time/InstantWithJMockUnitTest.java | 47 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 core-java-8/src/test/java/com/baeldung/time/InstantUnitTest.java create mode 100644 core-java-8/src/test/java/com/baeldung/time/InstantWithJMockUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/time/InstantUnitTest.java b/core-java-8/src/test/java/com/baeldung/time/InstantUnitTest.java new file mode 100644 index 0000000000..8400748710 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/time/InstantUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.time; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; +import static org.powermock.api.mockito.PowerMockito.mockStatic; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ Instant.class }) +public class InstantUnitTest { + + @Test + public void givenInstantMock_whenNow_thenGetFixedInstant() { + String instantExpected = "2014-12-22T10:15:30Z"; + Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC")); + Instant instant = Instant.now(clock); + mockStatic(Instant.class); + when(Instant.now()).thenReturn(instant); + + Instant now = Instant.now(); + + assertThat(now.toString()).isEqualTo(instantExpected); + } + + @Test + public void givenFixedClock_whenNow_thenGetFixedInstant() { + String instantExpected = "2014-12-22T10:15:30Z"; + Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC")); + + Instant instant = Instant.now(clock); + + assertThat(instant.toString()).isEqualTo(instantExpected); + } +} diff --git a/core-java-8/src/test/java/com/baeldung/time/InstantWithJMockUnitTest.java b/core-java-8/src/test/java/com/baeldung/time/InstantWithJMockUnitTest.java new file mode 100644 index 0000000000..8f83b91101 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/time/InstantWithJMockUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.time; + +import mockit.Expectations; +import mockit.Mock; +import mockit.MockUp; +import org.junit.jupiter.api.Test; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; + +import static org.assertj.core.api.Assertions.assertThat; + +public class InstantWithJMockUnitTest { + + @Test + public void givenInstantWithJMock_whenNow_thenGetFixedInstant() { + String instantExpected = "2014-12-21T10:15:30Z"; + Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC")); + new MockUp() { + @Mock + public Instant now() { + return Instant.now(clock); + } + }; + + Instant now = Instant.now(); + + assertThat(now.toString()).isEqualTo(instantExpected); + } + + @Test + public void givenInstantWithExpectations_whenNow_thenGetFixedInstant() { + Clock clock = Clock.fixed(Instant.parse("2014-12-23T10:15:30.00Z"), ZoneId.of("UTC")); + Instant instantExpected = Instant.now(clock); + new Expectations(Instant.class) { + { + Instant.now(); + result = instantExpected; + } + }; + + Instant now = Instant.now(); + + assertThat(now).isEqualTo(instantExpected); + } +} From b395dc1d418f5077ffe76c17d7d59fda9328c2ac Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Sat, 12 Jan 2019 18:57:19 -0200 Subject: [PATCH 065/190] Now using Auth and Resource servers from Baeldung/spring-security-oauth (#6128) --- .../OauthClientApplication.java | 4 +-- .../web/ClientRestController.java | 2 +- ....java => OauthClientLoginApplication.java} | 8 ++--- .../web/ClientRestController.java | 2 +- .../ClientCredentialsOauthApplication.java | 4 +-- .../service/WebClientChonJob.java | 6 ++-- .../ManualRequestApplication.java | 5 ++-- .../web/ManualOauthRequestController.java | 20 ++++++++----- ...nt-auth-code-client-application.properties | 8 ++--- ...ent-auth-code-login-application.properties | 12 ++++---- ...t-credentials-oauth-application.properties | 6 ++-- ...anual-request-oauth-application.properties | 3 ++ .../OAuth2ClientCredentialsLiveTest.java | 6 ++-- .../OAuth2ManualRequestLiveTest.java | 5 ++-- .../AuthorizationServerApplication.java | 17 ----------- .../configuration/WebSecurityConfig.java | 26 ----------------- .../ResourceServerApplication.java | 17 ----------- .../configuration/AuthorizationConfigs.java | 29 ------------------- .../web/ResourceRestController.java | 23 --------------- ...lient-authorization-application.properties | 13 --------- ...webclient-resources-application.properties | 6 ---- 21 files changed, 48 insertions(+), 174 deletions(-) rename spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/{OauthClientApplication.java => OauthClientLoginApplication.java} (62%) create mode 100644 spring-5-reactive-oauth/src/main/resources/webclient-manual-request-oauth-application.properties delete mode 100644 spring-5-security-oauth/src/main/java/com/baeldung/webclient/authorizationserver/AuthorizationServerApplication.java delete mode 100644 spring-5-security-oauth/src/main/java/com/baeldung/webclient/authorizationserver/configuration/WebSecurityConfig.java delete mode 100644 spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/ResourceServerApplication.java delete mode 100644 spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/configuration/AuthorizationConfigs.java delete mode 100644 spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/web/ResourceRestController.java delete mode 100644 spring-5-security-oauth/src/main/resources/webclient-authorization-application.properties delete mode 100644 spring-5-security-oauth/src/main/resources/webclient-resources-application.properties diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/OauthClientApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/OauthClientApplication.java index 7bae78bb14..843d3f251f 100644 --- a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/OauthClientApplication.java +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/OauthClientApplication.java @@ -6,9 +6,9 @@ import org.springframework.context.annotation.PropertySource; /** * - * Note: This app is configured to use the authorization service and the resource service located in module spring-5-security-oauth + * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo * - * As we usually do with other well-known auth providers (github/facebook/...) we have to log-in using user credentials (bael-user/bael-password) and client configurations (bael-client-id/bael-secret) handled by the auth server + * As we usually do with other well-known auth providers (github/facebook/...) we have to log-in using user credentials (john/123) and client configurations handled by the auth server * * @author rozagerardo * diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/web/ClientRestController.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/web/ClientRestController.java index c36b7d1dea..9994a1255a 100644 --- a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/web/ClientRestController.java +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodeclient/web/ClientRestController.java @@ -15,7 +15,7 @@ import reactor.core.publisher.Mono; @RestController public class ClientRestController { - private static final String RESOURCE_URI = "http://localhost:8084/retrieve-resource"; + private static final String RESOURCE_URI = "http://localhost:8082/spring-security-oauth-resource/foos/1"; @Autowired WebClient webClient; diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientLoginApplication.java similarity index 62% rename from spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientApplication.java rename to spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientLoginApplication.java index 9dd6dd1bde..e71e549ea4 100644 --- a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientApplication.java +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/OauthClientLoginApplication.java @@ -6,19 +6,19 @@ import org.springframework.context.annotation.PropertySource; /** * - * Note: This app is configured to use the authorization service and the resource service located in module spring-5-security-oauth + * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo * - * As we usually do with other well-known auth providers (github/facebook/...) we have to log-in using user credentials (bael-user/bael-password) and client configurations (bael-client-id/bael-secret) handled by the auth server + * As we usually do with other well-known auth providers (github/facebook/...) we have to log-in using user credentials (john/123) and client configurations handled by the auth server * * @author rozagerardo * */ @PropertySource("classpath:webclient-auth-code-login-application.properties") @SpringBootApplication -public class OauthClientApplication { +public class OauthClientLoginApplication { public static void main(String[] args) { - SpringApplication.run(OauthClientApplication.class, args); + SpringApplication.run(OauthClientLoginApplication.class, args); } } diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/web/ClientRestController.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/web/ClientRestController.java index 55e0096525..24e5377f36 100644 --- a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/web/ClientRestController.java +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/authorizationcodelogin/web/ClientRestController.java @@ -16,7 +16,7 @@ import reactor.core.publisher.Mono; @RestController public class ClientRestController { - private static final String RESOURCE_URI = "http://localhost:8084/retrieve-resource"; + private static final String RESOURCE_URI = "http://localhost:8082/spring-security-oauth-resource/foos/1"; @Autowired WebClient webClient; diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/ClientCredentialsOauthApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/ClientCredentialsOauthApplication.java index d1b9f7f744..4356581819 100644 --- a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/ClientCredentialsOauthApplication.java +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/ClientCredentialsOauthApplication.java @@ -7,9 +7,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; /** * - * Note: This app is configured to use the authorization service and the resource service located in module spring-5-security-oauth - * - * As we usually do with other well-known auth providers (github/facebook/...) we have to log-in using credentials handled by the auth server (bael-user/bael-password) + * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo * * @author rozagerardo * diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/service/WebClientChonJob.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/service/WebClientChonJob.java index dc38ce3f9e..ef39222933 100644 --- a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/service/WebClientChonJob.java +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/clientcredentials/service/WebClientChonJob.java @@ -4,8 +4,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; -import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; @@ -14,12 +12,12 @@ public class WebClientChonJob { Logger logger = LoggerFactory.getLogger(WebClientChonJob.class); - private static final String RESOURCE_URI = "http://localhost:8084/retrieve-resource"; + private static final String RESOURCE_URI = "localhost:8082/spring-security-oauth-resource/foos/1"; @Autowired private WebClient webClient; - @Scheduled(fixedRate = 1000) + @Scheduled(fixedRate = 5000) public void logResourceServiceResponse() { webClient.get() diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/ManualRequestApplication.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/ManualRequestApplication.java index c2762ad559..59a63355f7 100644 --- a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/ManualRequestApplication.java +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/ManualRequestApplication.java @@ -6,13 +6,12 @@ import org.springframework.context.annotation.PropertySource; /** * - * Note: This app is configured to use the authorization service and the resource service located in module spring-5-security-oauth - * - * As we usually do with other well-known auth providers (github/facebook/...) we have to log-in using user credentials (bael-user/bael-password) and client configurations (bael-client-id/bael-secret) handled by the auth server + * Note: This app is configured to use the authorization service and the resource service located in Baeldung/spring-security-oauth repo * * @author rozagerardo * */ +@PropertySource("classpath:webclient-manual-request-oauth-application.properties") @SpringBootApplication public class ManualRequestApplication { diff --git a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java index 9f9d6d3167..d54d811032 100644 --- a/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java +++ b/spring-5-reactive-oauth/src/main/java/com/baeldung/webclient/manualrequest/web/ManualOauthRequestController.java @@ -3,8 +3,8 @@ package com.baeldung.webclient.manualrequest.web; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.util.Base64Utils; import org.springframework.web.bind.annotation.GetMapping; @@ -22,10 +22,16 @@ public class ManualOauthRequestController { private static Logger logger = LoggerFactory.getLogger(ManualOauthRequestController.class); - private static final String TOKEN_ENDPOINT = "localhost:8085/oauth/token"; - private static final String RESOURCE_ENDPOINT = "localhost:8084/retrieve-resource"; - private static final String CLIENT_ID = "bael-client-id"; - private static final String CLIENT_SECRET = "bael-secret"; + private static final String RESOURCE_ENDPOINT = "localhost:8082/spring-security-oauth-resource/foos/1"; + + @Value("${the.authorization.client-id}") + private String clientId; + + @Value("${the.authorization.client-secret}") + private String clientSecret; + + @Value("${the.authorization.token-uri}") + private String tokenUri; @Autowired WebClient client; @@ -34,8 +40,8 @@ public class ManualOauthRequestController { public Mono obtainSecuredResource() { logger.info("Creating web client..."); Mono resource = client.post() - .uri(TOKEN_ENDPOINT) - .header(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString((CLIENT_ID + ":" + CLIENT_SECRET).getBytes())) + .uri(tokenUri) + .header(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString((clientId + ":" + clientSecret).getBytes())) .body(BodyInserters.fromFormData(OAuth2ParameterNames.GRANT_TYPE, GrantType.CLIENT_CREDENTIALS.getValue())) .retrieve() .bodyToMono(JsonNode.class) diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-client-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-client-application.properties index 612777a06d..ac96aae6d6 100644 --- a/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-client-application.properties +++ b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-client-application.properties @@ -1,10 +1,10 @@ spring.security.oauth2.client.registration.bael.client-name=bael -spring.security.oauth2.client.registration.bael.client-id=bael-client-id -spring.security.oauth2.client.registration.bael.client-secret=bael-secret +spring.security.oauth2.client.registration.bael.client-id=fooClientIdPassword +spring.security.oauth2.client.registration.bael.client-secret=secret spring.security.oauth2.client.registration.bael.authorization-grant-type=authorization_code spring.security.oauth2.client.registration.bael.redirect-uri=http://localhost:8080/authorize/oauth2/code/bael -spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8085/oauth/token -spring.security.oauth2.client.provider.bael.authorization-uri=http://localhost:8085/oauth/authorize +spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token +spring.security.oauth2.client.provider.bael.authorization-uri=http://localhost:8081/spring-security-oauth-server/oauth/authorize spring.security.user.password=pass diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-login-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-login-application.properties index edd5b80b13..e4dd0a532d 100644 --- a/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-login-application.properties +++ b/spring-5-reactive-oauth/src/main/resources/webclient-auth-code-login-application.properties @@ -1,10 +1,10 @@ spring.security.oauth2.client.registration.bael.client-name=bael -spring.security.oauth2.client.registration.bael.client-id=bael-client-id -spring.security.oauth2.client.registration.bael.client-secret=bael-secret +spring.security.oauth2.client.registration.bael.client-id=fooClientIdPassword +spring.security.oauth2.client.registration.bael.client-secret=secret spring.security.oauth2.client.registration.bael.authorization-grant-type=authorization_code spring.security.oauth2.client.registration.bael.redirect-uri=http://localhost:8080/login/oauth2/code/bael -spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8085/oauth/token -spring.security.oauth2.client.provider.bael.authorization-uri=http://localhost:8085/oauth/authorize -spring.security.oauth2.client.provider.bael.user-info-uri=http://localhost:8084/user -spring.security.oauth2.client.provider.bael.user-name-attribute=name +spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token +spring.security.oauth2.client.provider.bael.authorization-uri=http://localhost:8081/spring-security-oauth-server/oauth/authorize +spring.security.oauth2.client.provider.bael.user-info-uri=http://localhost:8082/spring-security-oauth-resource/users/extra +spring.security.oauth2.client.provider.bael.user-name-attribute=user_name diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-client-credentials-oauth-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-client-credentials-oauth-application.properties index f82f74ec48..14c5b97605 100644 --- a/spring-5-reactive-oauth/src/main/resources/webclient-client-credentials-oauth-application.properties +++ b/spring-5-reactive-oauth/src/main/resources/webclient-client-credentials-oauth-application.properties @@ -1,4 +1,4 @@ spring.security.oauth2.client.registration.bael.authorization-grant-type=client_credentials -spring.security.oauth2.client.registration.bael.client-id=bael-client-id -spring.security.oauth2.client.registration.bael.client-secret=bael-secret -spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8085/oauth/token +spring.security.oauth2.client.registration.bael.client-id=fooClientIdPassword +spring.security.oauth2.client.registration.bael.client-secret=secret +spring.security.oauth2.client.provider.bael.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token diff --git a/spring-5-reactive-oauth/src/main/resources/webclient-manual-request-oauth-application.properties b/spring-5-reactive-oauth/src/main/resources/webclient-manual-request-oauth-application.properties new file mode 100644 index 0000000000..36ec3defd1 --- /dev/null +++ b/spring-5-reactive-oauth/src/main/resources/webclient-manual-request-oauth-application.properties @@ -0,0 +1,3 @@ +the.authorization.client-id=fooClientIdPassword +the.authorization.client-secret=secret +the.authorization.token-uri=http://localhost:8081/spring-security-oauth-server/oauth/token diff --git a/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/clientcredentials/OAuth2ClientCredentialsLiveTest.java b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/clientcredentials/OAuth2ClientCredentialsLiveTest.java index e31815c3f8..ef913ba055 100644 --- a/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/clientcredentials/OAuth2ClientCredentialsLiveTest.java +++ b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/clientcredentials/OAuth2ClientCredentialsLiveTest.java @@ -19,9 +19,9 @@ import ch.qos.logback.classic.spi.ILoggingEvent; /** * - * Note: this Live test requires the Authorization Service and the Resource service located in the spring-5-security-oauth module + * Note: this Live test requires the Authorization Service and the Resource service located in the Baeldung/spring-security-oauth repo * - * @author ger + * @author rozagerardo * */ @RunWith(SpringRunner.class) @@ -46,7 +46,7 @@ public class OAuth2ClientCredentialsLiveTest { .stream() .map(ILoggingEvent::getFormattedMessage) .collect(Collectors.toList()); - assertThat(allLoggedEntries).anyMatch(entry -> entry.contains("We retrieved the following resource using Client Credentials Grant Type: This is the resource!")); + assertThat(allLoggedEntries).anyMatch(entry -> entry.contains("We retrieved the following resource using Client Credentials Grant Type: {\"id\"")); } } diff --git a/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/manualrequest/OAuth2ManualRequestLiveTest.java b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/manualrequest/OAuth2ManualRequestLiveTest.java index 94aa580f0a..2381264926 100644 --- a/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/manualrequest/OAuth2ManualRequestLiveTest.java +++ b/spring-5-reactive-oauth/src/test/java/com/baeldung/webclient/manualrequest/OAuth2ManualRequestLiveTest.java @@ -1,5 +1,6 @@ package com.baeldung.webclient.manualrequest; +import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.springframework.test.web.reactive.server.WebTestClient; @@ -8,7 +9,7 @@ import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec; /** * * Note: this Live test requires not only the corresponding application running, - * but also the Authorization Service and the Resource service located in the spring-5-security-oauth module. + * but also the Authorization Service and the Resource service located in the Baeldung/spring-security-oauth repo * * * @author ger @@ -37,7 +38,7 @@ public class OAuth2ManualRequestLiveTest { response.expectStatus() .isOk() .expectBody(String.class) - .isEqualTo("Retrieved the resource using a manual approach: This is the resource!"); + .value(Matchers.containsString("Retrieved the resource using a manual approach: {\"id\"")); } } diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/webclient/authorizationserver/AuthorizationServerApplication.java b/spring-5-security-oauth/src/main/java/com/baeldung/webclient/authorizationserver/AuthorizationServerApplication.java deleted file mode 100644 index d72704386c..0000000000 --- a/spring-5-security-oauth/src/main/java/com/baeldung/webclient/authorizationserver/AuthorizationServerApplication.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.webclient.authorizationserver; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.PropertySource; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; - -@EnableAuthorizationServer -@PropertySource("classpath:webclient-authorization-application.properties") -@SpringBootApplication -public class AuthorizationServerApplication { - - public static void main(String[] args) { - SpringApplication.run(AuthorizationServerApplication.class, args); - } - -} diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/webclient/authorizationserver/configuration/WebSecurityConfig.java b/spring-5-security-oauth/src/main/java/com/baeldung/webclient/authorizationserver/configuration/WebSecurityConfig.java deleted file mode 100644 index 5dd15f1b8c..0000000000 --- a/spring-5-security-oauth/src/main/java/com/baeldung/webclient/authorizationserver/configuration/WebSecurityConfig.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.webclient.authorizationserver.configuration; - -import org.springframework.context.annotation.Configuration; -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; - -@EnableWebSecurity -@Configuration -public class WebSecurityConfig extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests() - .antMatchers("/login", "/user") - .permitAll() - .and() - .authorizeRequests() - .anyRequest() - .authenticated() - .and() - .formLogin() - .and() - .httpBasic(); - } -} diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/ResourceServerApplication.java b/spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/ResourceServerApplication.java deleted file mode 100644 index 50ad293ef8..0000000000 --- a/spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/ResourceServerApplication.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.webclient.resourceserver; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.PropertySource; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; - -@EnableResourceServer -@PropertySource("webclient-resources-application.properties") -@SpringBootApplication -public class ResourceServerApplication { - - public static void main(String[] args) { - SpringApplication.run(ResourceServerApplication.class, args); - } - -} diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/configuration/AuthorizationConfigs.java b/spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/configuration/AuthorizationConfigs.java deleted file mode 100644 index 5aea1983db..0000000000 --- a/spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/configuration/AuthorizationConfigs.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.webclient.resourceserver.configuration; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.oauth2.provider.token.RemoteTokenServices; -import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; - -@Configuration -public class AuthorizationConfigs { - - @Value("${oauth.authserver.client-id}") - String clientId; - - @Value("${oauth.authserver.client-secret}") - String clientSecret; - - @Value("${oauth.authserver.check-token-endpoint}") - String checkTokenEndpoint; - - @Bean - public ResourceServerTokenServices tokenSvc() { - RemoteTokenServices remoteService = new RemoteTokenServices(); - remoteService.setCheckTokenEndpointUrl(checkTokenEndpoint); - remoteService.setClientId(clientId); - remoteService.setClientSecret(clientSecret); - return remoteService; - } -} diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/web/ResourceRestController.java b/spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/web/ResourceRestController.java deleted file mode 100644 index aef0fb4d7d..0000000000 --- a/spring-5-security-oauth/src/main/java/com/baeldung/webclient/resourceserver/web/ResourceRestController.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.webclient.resourceserver.web; - -import java.security.Principal; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class ResourceRestController { - - @GetMapping("/retrieve-resource") - public String retrieveResource() { - return "This is the resource!"; - } - - @GetMapping("/user") - @ResponseBody - public Principal user(Principal user) { - return user; - } - -} diff --git a/spring-5-security-oauth/src/main/resources/webclient-authorization-application.properties b/spring-5-security-oauth/src/main/resources/webclient-authorization-application.properties deleted file mode 100644 index 9531045359..0000000000 --- a/spring-5-security-oauth/src/main/resources/webclient-authorization-application.properties +++ /dev/null @@ -1,13 +0,0 @@ -server.port=8085 - -security.oauth2.client.client-id=bael-client-id -security.oauth2.client.client-secret=bael-secret -security.oauth2.client.scope=read,write - -security.oauth2.authorization.check-token-access=isAuthenticated() - -spring.security.user.name=bael-user -spring.security.user.password=bael-password - -security.oauth2.client.registered-redirect-uri=http://localhost:8080/login/oauth2/code/bael, http://localhost:8080/authorize/oauth2/code/bael -security.oauth2.client.use-current-uri=false \ No newline at end of file diff --git a/spring-5-security-oauth/src/main/resources/webclient-resources-application.properties b/spring-5-security-oauth/src/main/resources/webclient-resources-application.properties deleted file mode 100644 index 1cfb9ca12d..0000000000 --- a/spring-5-security-oauth/src/main/resources/webclient-resources-application.properties +++ /dev/null @@ -1,6 +0,0 @@ -server.port=8084 - -#spring.security.oauth2.resourceserver.jwt.issuer-uri=localhost:8085 -oauth.authserver.client-id=bael-client-id -oauth.authserver.client-secret=bael-secret -oauth.authserver.check-token-endpoint=http://localhost:8085/oauth/check_token From dcc1cd3850cdb3dbbfa6df343604ac4b720cd424 Mon Sep 17 00:00:00 2001 From: chandra Date: Sat, 12 Jan 2019 16:52:52 -0500 Subject: [PATCH 066/190] BAEL-2088 Common Hibernate Exceptions Commin Hibernate Exceptions unit tests --- .../hibernate/exception/EntityWithNoId.java | 16 + .../hibernate/exception/HibernateUtil.java | 63 +++ .../baeldung/hibernate/exception/Product.java | 40 ++ .../exception/HibernateExceptionUnitTest.java | 425 ++++++++++++++++++ .../resources/hibernate-exception.properties | 16 + 5 files changed, 560 insertions(+) create mode 100644 persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/EntityWithNoId.java create mode 100644 persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/HibernateUtil.java create mode 100644 persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/Product.java create mode 100644 persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/exception/HibernateExceptionUnitTest.java create mode 100644 persistence-modules/hibernate5/src/test/resources/hibernate-exception.properties diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/EntityWithNoId.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/EntityWithNoId.java new file mode 100644 index 0000000000..989fa1281a --- /dev/null +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/EntityWithNoId.java @@ -0,0 +1,16 @@ +package com.baeldung.hibernate.exception; + +import javax.persistence.Entity; + +@Entity +public class EntityWithNoId { + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/HibernateUtil.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/HibernateUtil.java new file mode 100644 index 0000000000..ae5174ac9c --- /dev/null +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/HibernateUtil.java @@ -0,0 +1,63 @@ +package com.baeldung.hibernate.exception; + +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +import org.apache.commons.lang3.StringUtils; +import org.hibernate.SessionFactory; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.service.ServiceRegistry; + +public class HibernateUtil { + private static SessionFactory sessionFactory; + private static String PROPERTY_FILE_NAME; + + public static SessionFactory getSessionFactory() throws IOException { + return getSessionFactory(null); + } + + public static SessionFactory getSessionFactory(String propertyFileName) + throws IOException { + PROPERTY_FILE_NAME = propertyFileName; + if (sessionFactory == null) { + ServiceRegistry serviceRegistry = configureServiceRegistry(); + sessionFactory = makeSessionFactory(serviceRegistry); + } + return sessionFactory; + } + + private static SessionFactory makeSessionFactory( + ServiceRegistry serviceRegistry) { + MetadataSources metadataSources = new MetadataSources(serviceRegistry); + metadataSources.addAnnotatedClass(Product.class); + Metadata metadata = metadataSources.getMetadataBuilder() + .build(); + return metadata.getSessionFactoryBuilder() + .build(); + + } + + private static ServiceRegistry configureServiceRegistry() + throws IOException { + Properties properties = getProperties(); + return new StandardServiceRegistryBuilder().applySettings(properties) + .build(); + } + + private static Properties getProperties() throws IOException { + Properties properties = new Properties(); + URL propertiesURL = Thread.currentThread() + .getContextClassLoader() + .getResource(StringUtils.defaultString(PROPERTY_FILE_NAME, + "hibernate-exception.properties")); + try (FileInputStream inputStream = new FileInputStream( + propertiesURL.getFile())) { + properties.load(inputStream); + } + return properties; + } +} \ No newline at end of file diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/Product.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/Product.java new file mode 100644 index 0000000000..031fa38de0 --- /dev/null +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/exception/Product.java @@ -0,0 +1,40 @@ +package com.baeldung.hibernate.exception; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class Product { + + private int id; + + private String name; + private String description; + + @Id + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Column(nullable=false) + 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/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/exception/HibernateExceptionUnitTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/exception/HibernateExceptionUnitTest.java new file mode 100644 index 0000000000..3581c81daa --- /dev/null +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/exception/HibernateExceptionUnitTest.java @@ -0,0 +1,425 @@ +package com.baeldung.hibernate.exception; + +import static org.hamcrest.CoreMatchers.isA; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.util.List; + +import javax.persistence.OptimisticLockException; +import javax.persistence.PersistenceException; + +import org.hibernate.AnnotationException; +import org.hibernate.HibernateException; +import org.hibernate.MappingException; +import org.hibernate.NonUniqueObjectException; +import org.hibernate.PropertyValueException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.StaleObjectStateException; +import org.hibernate.StaleStateException; +import org.hibernate.Transaction; +import org.hibernate.TransactionException; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; +import org.hibernate.exception.ConstraintViolationException; +import org.hibernate.exception.DataException; +import org.hibernate.exception.SQLGrammarException; +import org.hibernate.query.NativeQuery; +import org.hibernate.tool.schema.spi.CommandAcceptanceException; +import org.hibernate.tool.schema.spi.SchemaManagementException; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HibernateExceptionUnitTest { + + private static final Logger logger = LoggerFactory + .getLogger(HibernateExceptionUnitTest.class); + private SessionFactory sessionFactory; + + @Before + public void setUp() throws IOException { + sessionFactory = HibernateUtil.getSessionFactory(); + } + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private Configuration getConfiguration() { + Configuration cfg = new Configuration(); + cfg.setProperty(AvailableSettings.DIALECT, + "org.hibernate.dialect.H2Dialect"); + cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "none"); + cfg.setProperty(AvailableSettings.DRIVER, "org.h2.Driver"); + cfg.setProperty(AvailableSettings.URL, + "jdbc:h2:mem:myexceptiondb2;DB_CLOSE_DELAY=-1"); + cfg.setProperty(AvailableSettings.USER, "sa"); + cfg.setProperty(AvailableSettings.PASS, ""); + return cfg; + } + + @Test + public void whenQueryExecutedWithUnmappedEntity_thenMappingException() { + thrown.expectCause(isA(MappingException.class)); + thrown.expectMessage("Unknown entity: java.lang.String"); + + Session session = sessionFactory.openSession(); + NativeQuery query = session + .createNativeQuery("select name from PRODUCT", String.class); + query.getResultList(); + } + + @Test + @SuppressWarnings("rawtypes") + public void whenQueryExecuted_thenOK() { + Session session = sessionFactory.openSession(); + NativeQuery query = session + .createNativeQuery("select name from PRODUCT"); + List results = query.getResultList(); + assertNotNull(results); + } + + @Test + public void givenEntityWithoutId_whenSessionFactoryCreated_thenAnnotationException() { + thrown.expect(AnnotationException.class); + thrown.expectMessage("No identifier specified for entity"); + + Configuration cfg = getConfiguration(); + cfg.addAnnotatedClass(EntityWithNoId.class); + cfg.buildSessionFactory(); + } + + @Test + public void givenMissingTable_whenSchemaValidated_thenSchemaManagementException() { + thrown.expect(SchemaManagementException.class); + thrown.expectMessage("Schema-validation: missing table"); + + Configuration cfg = getConfiguration(); + cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "validate"); + cfg.addAnnotatedClass(Product.class); + cfg.buildSessionFactory(); + } + + @Test + public void whenWrongDialectSpecified_thenCommandAcceptanceException() { + thrown.expect(SchemaManagementException.class); + thrown.expectCause(isA(CommandAcceptanceException.class)); + thrown.expectMessage("Halting on error : Error executing DDL"); + + Configuration cfg = getConfiguration(); + cfg.setProperty(AvailableSettings.DIALECT, + "org.hibernate.dialect.MySQLDialect"); + cfg.setProperty(AvailableSettings.HBM2DDL_AUTO, "update"); + + // This does not work due to hibernate bug + // cfg.setProperty(AvailableSettings.HBM2DDL_HALT_ON_ERROR,"true"); + cfg.getProperties() + .put(AvailableSettings.HBM2DDL_HALT_ON_ERROR, true); + + cfg.addAnnotatedClass(Product.class); + cfg.buildSessionFactory(); + } + + @Test + public void givenMissingTable_whenEntitySaved_thenSQLGrammarException() { + thrown.expect(isA(PersistenceException.class)); + thrown.expectCause(isA(SQLGrammarException.class)); + thrown + .expectMessage("SQLGrammarException: could not prepare statement"); + + Configuration cfg = getConfiguration(); + cfg.addAnnotatedClass(Product.class); + + SessionFactory sessionFactory = cfg.buildSessionFactory(); + Session session = null; + Transaction transaction = null; + try { + + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + Product product = new Product(); + product.setId(1); + product.setName("Product 1"); + session.save(product); + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + closeSessionFactoryQuietly(sessionFactory); + } + } + + @Test + public void givenMissingTable_whenQueryExecuted_thenSQLGrammarException() { + thrown.expect(isA(PersistenceException.class)); + thrown.expectCause(isA(SQLGrammarException.class)); + thrown + .expectMessage("SQLGrammarException: could not prepare statement"); + + Session session = sessionFactory.openSession(); + NativeQuery query = session.createNativeQuery( + "select * from NON_EXISTING_TABLE", Product.class); + query.getResultList(); + } + + @Test + public void whenDuplicateIdSaved_thenConstraintViolationException() { + thrown.expect(isA(PersistenceException.class)); + thrown.expectCause(isA(ConstraintViolationException.class)); + thrown.expectMessage( + "ConstraintViolationException: could not execute statement"); + + Session session = null; + Transaction transaction = null; + + for (int i = 1; i <= 2; i++) { + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + Product product = new Product(); + product.setId(1); + product.setName("Product " + i); + session.save(product); + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } + } + + @Test + public void givenNotNullPropertyNotSet_whenEntityIdSaved_thenPropertyValueException() { + thrown.expect(isA(PropertyValueException.class)); + thrown.expectMessage( + "not-null property references a null or transient value"); + + Session session = null; + Transaction transaction = null; + + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product = new Product(); + product.setId(1); + session.save(product); + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + + } + + @Test + public void givenQueryWithDataTypeMismatch_WhenQueryExecuted_thenDataException() { + thrown.expectCause(isA(DataException.class)); + thrown.expectMessage( + "org.hibernate.exception.DataException: could not prepare statement"); + + Session session = sessionFactory.openSession(); + NativeQuery query = session.createNativeQuery( + "select * from PRODUCT where id='wrongTypeId'", Product.class); + query.getResultList(); + } + + @Test + public void givenSessionContainingAnId_whenIdAssociatedAgain_thenNonUniqueObjectException() { + thrown.expect(isA(NonUniqueObjectException.class)); + thrown.expectMessage( + "A different object with the same identifier value was already associated with the session"); + + Session session = null; + Transaction transaction = null; + + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product1 = new Product(); + product1.setId(1); + product1.setName("Product 1"); + session.save(product1); + + Product product2 = new Product(); + product2.setId(1); + product2.setName("Product 2"); + session.save(product2); + + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } + + @Test + public void whenDeletingADeletedObject_thenOptimisticLockException() { + thrown.expect(isA(OptimisticLockException.class)); + thrown.expectMessage( + "Batch update returned unexpected row count from update"); + thrown.expectCause(isA(StaleStateException.class)); + + Session session = null; + Transaction transaction = null; + + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product1 = new Product(); + product1.setId(12); + product1.setName("Product 12"); + session.save(product1); + transaction.commit(); + session.close(); + + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + Product product2 = session.get(Product.class, 12); + session.createNativeQuery("delete from Product where id=12") + .executeUpdate(); + // We need to refresh to fix the error. + // session.refresh(product2); + session.delete(product2); + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } + + @Test + public void whenUpdatingNonExistingObject_thenStaleStateException() { + thrown.expect(isA(OptimisticLockException.class)); + thrown + .expectMessage("Row was updated or deleted by another transaction"); + thrown.expectCause(isA(StaleObjectStateException.class)); + + Session session = null; + Transaction transaction = null; + + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product1 = new Product(); + product1.setId(15); + product1.setName("Product1"); + session.update(product1); + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } + + @Test + public void givenTxnMarkedRollbackOnly_whenCommitted_thenTransactionException() { + thrown.expect(isA(TransactionException.class)); + + Session session = null; + Transaction transaction = null; + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product1 = new Product(); + product1.setId(15); + product1.setName("Product1"); + session.save(product1); + transaction.setRollbackOnly(); + + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } + + private void rollbackTransactionQuietly(Transaction transaction) { + if (transaction != null && transaction.isActive()) { + try { + transaction.rollback(); + } catch (Exception e) { + logger.error("Exception while rolling back transaction", e); + } + } + } + + private void closeSessionQuietly(Session session) { + if (session != null) { + try { + session.close(); + } catch (Exception e) { + logger.error("Exception while closing session", e); + } + } + } + + private void closeSessionFactoryQuietly(SessionFactory sessionFactory) { + if (sessionFactory != null) { + try { + sessionFactory.close(); + } catch (Exception e) { + logger.error("Exception while closing sessionFactory", e); + } + } + } + + @Test + public void givenExistingEntity_whenIdUpdated_thenHibernateException() { + thrown.expect(isA(PersistenceException.class)); + thrown.expectCause(isA(HibernateException.class)); + thrown.expectMessage( + "identifier of an instance of com.baeldung.hibernate.exception.Product was altered"); + + Session session = null; + Transaction transaction = null; + + try { + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product1 = new Product(); + product1.setId(222); + product1.setName("Product 222"); + session.save(product1); + transaction.commit(); + closeSessionQuietly(session); + + session = sessionFactory.openSession(); + transaction = session.beginTransaction(); + + Product product2 = session.get(Product.class, 222); + product2.setId(333); + session.save(product2); + + transaction.commit(); + } catch (Exception e) { + rollbackTransactionQuietly(transaction); + throw (e); + } finally { + closeSessionQuietly(session); + } + } +} diff --git a/persistence-modules/hibernate5/src/test/resources/hibernate-exception.properties b/persistence-modules/hibernate5/src/test/resources/hibernate-exception.properties new file mode 100644 index 0000000000..e08a23166d --- /dev/null +++ b/persistence-modules/hibernate5/src/test/resources/hibernate-exception.properties @@ -0,0 +1,16 @@ +hibernate.connection.driver_class=org.h2.Driver +hibernate.connection.url=jdbc:h2:mem:myexceptiondb1;DB_CLOSE_DELAY=-1 +hibernate.connection.username=sa +hibernate.connection.autocommit=true +jdbc.password= + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=true +hibernate.hbm2ddl.auto=create-drop + +hibernate.c3p0.min_size=5 +hibernate.c3p0.max_size=20 +hibernate.c3p0.acquire_increment=5 +hibernate.c3p0.timeout=1800 + +hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory From 16bed6f64b2a55fa36568119a92c3593345b00d1 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Sun, 13 Jan 2019 10:42:18 +0400 Subject: [PATCH 067/190] match words refactoring --- .../java/com/baeldung/string/MatchWords.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index f0b64c19cf..f4a52ae308 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -9,21 +9,21 @@ import java.util.regex.Pattern; public class MatchWords { public static void main(String[] args) { - String[] items = {"hello", "Baeldung"}; + String[] words = {"hello", "Baeldung"}; String inputString = "hello there, Baeldung"; - System.out.println(containsWords(inputString, items)); + containsWords(inputString, words); - System.out.println(java8(new ArrayList<>(Arrays.asList(inputString.split(" "))), new ArrayList<>(Arrays.asList(items)))); + containsWordsJava8(new ArrayList<>(Arrays.asList(inputString.split(" "))), new ArrayList<>(Arrays.asList(words))); - System.out.println(patternMatch(inputString)); + containsWordsPatternMatch(inputString, words); - ahoCorasick(); + containsWordsAhoCorasick(inputString, words); - indexOfWords(inputString, items); + containsWordsIndexOf(inputString, words); } - private static boolean indexOfWords(String inputString, String[] words) { + private static boolean containsWordsIndexOf(String inputString, String[] words) { boolean found = true; for (String word : words) { int index = inputString.indexOf(word); @@ -46,30 +46,31 @@ public class MatchWords { return found; } - private static void ahoCorasick() { + private static boolean containsWordsAhoCorasick(String inputString, String[] words) { Trie trie = Trie.builder() .onlyWholeWords() - .addKeyword("hello") - .addKeyword("Baeldung") + .addKeyword(words[0]) + .addKeyword(words[1]) .build(); - Collection emits = trie.parseText("hello there, Baeldung"); - emits.forEach(System.out::println); + Collection emits = trie.parseText(inputString); + + return emits.size() == words.length; } - private static boolean patternMatch(String inputString) { - Pattern pattern = Pattern.compile("(?=.*hello)(?=.*Baeldung)"); + private static boolean containsWordsPatternMatch(String inputString, String[] words) { + Pattern pattern = Pattern.compile("(?=.*words[0])(?=.*words[1])"); if (pattern.matcher(inputString).find()) { return true; } return false; } - private static boolean java8(ArrayList inputString, ArrayList items) { - return items.stream().allMatch(inputString::contains); + private static boolean containsWordsJava8(ArrayList inputString, ArrayList words) { + return words.stream().allMatch(inputString::contains); } - private static boolean array(ArrayList inputString, ArrayList items) { - return inputString.containsAll(items); + private static boolean containsWordsArray(ArrayList inputString, ArrayList words) { + return inputString.containsAll(words); } } From 06ffe3b5e42581d28e582d68ebf35f2403789954 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Sun, 13 Jan 2019 11:04:42 +0400 Subject: [PATCH 068/190] match words final refactor --- .../main/java/com/baeldung/string/MatchWords.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index f4a52ae308..675f4577c3 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -4,7 +4,10 @@ import org.ahocorasick.trie.Emit; import org.ahocorasick.trie.Trie; import java.util.*; +import java.util.function.Function; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class MatchWords { @@ -51,14 +54,17 @@ public class MatchWords { .onlyWholeWords() .addKeyword(words[0]) .addKeyword(words[1]) + .ignoreOverlaps() .build(); - Collection emits = trie.parseText(inputString); - + Collection emits = trie.parseText(inputString) + .stream() + .filter(e -> !Objects.equals(e.getKeyword(), e.getKeyword())) + .collect(Collectors.toList()); return emits.size() == words.length; } private static boolean containsWordsPatternMatch(String inputString, String[] words) { - Pattern pattern = Pattern.compile("(?=.*words[0])(?=.*words[1])"); + Pattern pattern = Pattern.compile("(?=.*hello)(?=.*Baeldung)"); if (pattern.matcher(inputString).find()) { return true; } From 04c6cd1215be367f43652a6e771f4bf8eba0032e Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Sun, 13 Jan 2019 11:35:54 +0400 Subject: [PATCH 069/190] replace hardcoded strings --- .../src/main/java/com/baeldung/string/MatchWords.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index 675f4577c3..0b803da0ae 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -56,15 +56,20 @@ public class MatchWords { .addKeyword(words[1]) .ignoreOverlaps() .build(); + Collection emits = trie.parseText(inputString) .stream() .filter(e -> !Objects.equals(e.getKeyword(), e.getKeyword())) .collect(Collectors.toList()); + + emits.forEach(System.out::println); + return emits.size() == words.length; } private static boolean containsWordsPatternMatch(String inputString, String[] words) { - Pattern pattern = Pattern.compile("(?=.*hello)(?=.*Baeldung)"); + + Pattern pattern = Pattern.compile("(?=.*" + words[0] + ")(?=.*" + words[1] + ")"); if (pattern.matcher(inputString).find()) { return true; } From 4f103eeb278324ad943e8b5ad17542fc04902ea5 Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 13 Jan 2019 10:32:02 +0200 Subject: [PATCH 070/190] move instanceof code --- .../src/main/java/com/baeldung/keyword/Circle.java | 0 .../src/main/java/com/baeldung/keyword/Ring.java | 0 .../src/main/java/com/baeldung/keyword/Round.java | 0 .../src/main/java/com/baeldung/keyword/Shape.java | 0 .../src/main/java/com/baeldung/keyword/Triangle.java | 0 .../test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {core-java => core-java-lang-syntax}/src/main/java/com/baeldung/keyword/Circle.java (100%) rename {core-java => core-java-lang-syntax}/src/main/java/com/baeldung/keyword/Ring.java (100%) rename {core-java => core-java-lang-syntax}/src/main/java/com/baeldung/keyword/Round.java (100%) rename {core-java => core-java-lang-syntax}/src/main/java/com/baeldung/keyword/Shape.java (100%) rename {core-java => core-java-lang-syntax}/src/main/java/com/baeldung/keyword/Triangle.java (100%) rename {core-java => core-java-lang-syntax}/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java (100%) diff --git a/core-java/src/main/java/com/baeldung/keyword/Circle.java b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Circle.java similarity index 100% rename from core-java/src/main/java/com/baeldung/keyword/Circle.java rename to core-java-lang-syntax/src/main/java/com/baeldung/keyword/Circle.java diff --git a/core-java/src/main/java/com/baeldung/keyword/Ring.java b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Ring.java similarity index 100% rename from core-java/src/main/java/com/baeldung/keyword/Ring.java rename to core-java-lang-syntax/src/main/java/com/baeldung/keyword/Ring.java diff --git a/core-java/src/main/java/com/baeldung/keyword/Round.java b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Round.java similarity index 100% rename from core-java/src/main/java/com/baeldung/keyword/Round.java rename to core-java-lang-syntax/src/main/java/com/baeldung/keyword/Round.java diff --git a/core-java/src/main/java/com/baeldung/keyword/Shape.java b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Shape.java similarity index 100% rename from core-java/src/main/java/com/baeldung/keyword/Shape.java rename to core-java-lang-syntax/src/main/java/com/baeldung/keyword/Shape.java diff --git a/core-java/src/main/java/com/baeldung/keyword/Triangle.java b/core-java-lang-syntax/src/main/java/com/baeldung/keyword/Triangle.java similarity index 100% rename from core-java/src/main/java/com/baeldung/keyword/Triangle.java rename to core-java-lang-syntax/src/main/java/com/baeldung/keyword/Triangle.java diff --git a/core-java/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java rename to core-java-lang-syntax/src/test/java/com/baeldung/keyword/test/InstanceOfUnitTest.java From 9c0363e221aba40d44323fd57eecf4e78edd3243 Mon Sep 17 00:00:00 2001 From: jose Date: Sun, 13 Jan 2019 15:12:40 -0300 Subject: [PATCH 071/190] BAEL-2472 changes after editor-review --- .../com/baeldung/scope/BracketScopeExample.java | 14 ++++++++++++++ .../java/com/baeldung/scope/ClassScopeExample.java | 5 ++--- .../java/com/baeldung/scope/LoopScopeExample.java | 6 +++--- .../com/baeldung/scope/MethodScopeExample.java | 9 +++------ .../com/baeldung/scope/NestedScopesExample.java | 3 +-- .../java/com/baeldung/scope/OutOfScopeExample.java | 14 -------------- 6 files changed, 23 insertions(+), 28 deletions(-) create mode 100644 core-java/src/main/java/com/baeldung/scope/BracketScopeExample.java delete mode 100644 core-java/src/main/java/com/baeldung/scope/OutOfScopeExample.java diff --git a/core-java/src/main/java/com/baeldung/scope/BracketScopeExample.java b/core-java/src/main/java/com/baeldung/scope/BracketScopeExample.java new file mode 100644 index 0000000000..37ae211dcb --- /dev/null +++ b/core-java/src/main/java/com/baeldung/scope/BracketScopeExample.java @@ -0,0 +1,14 @@ +package org.baeldung.variable.scope.examples; + +public class BracketScopeExample { + + public void mathOperationExample() { + Integer sum = 0; + { + Integer number = 2; + sum = sum + number; + } + // compiler error, number cannot be solved as a variable + // number++; + } +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java b/core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java index 17ca1e01eb..241c6b466e 100644 --- a/core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java +++ b/core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java @@ -9,7 +9,6 @@ public class ClassScopeExample { } public void anotherExampleMethod() { - amount--; + Integer anotherAmount = amount + 4; } - -} +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java b/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java index 2dd3be3333..8049a49c4d 100644 --- a/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java +++ b/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java @@ -12,7 +12,7 @@ public class LoopScopeExample { for (String name : listOfNames) { allNames = allNames + " " + name; } - + // compiler error, name cannot be resolved to a variable + // String lastNameUsed = name; } - -} +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java b/core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java index 122d12e2fc..e62c6a2a1c 100644 --- a/core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java +++ b/core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java @@ -2,15 +2,12 @@ package org.baeldung.variable.scope.examples; public class MethodScopeExample { - Integer size = 2; - public void methodA() { Integer area = 2; - area = area + size; } public void methodB() { - size = size + 5; + // compiler error, area cannot be resolved to a variable + // area = area + 2; } - -} +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java b/core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java index 9bd2268e52..fcd23e5ae0 100644 --- a/core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java +++ b/core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java @@ -9,5 +9,4 @@ public class NestedScopesExample { String title = "John Doe"; System.out.println(title); } - -} +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/scope/OutOfScopeExample.java b/core-java/src/main/java/com/baeldung/scope/OutOfScopeExample.java deleted file mode 100644 index 774095228c..0000000000 --- a/core-java/src/main/java/com/baeldung/scope/OutOfScopeExample.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.baeldung.variable.scope.examples; - -public class OutOfScopeExample { - - public void methodWithAVariableDeclaredInside() { - String name = "John Doe"; - System.out.println(name); - } - - public void methodWithoutVariables() { - System.out.println("Pattrick"); - } - -} From d16167ea63a6cbef5e665248e94f20decbea4027 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Mon, 14 Jan 2019 00:37:51 +0530 Subject: [PATCH 072/190] [BAEL-10781] - Added code for spring data rest pagination --- .../java/com/baeldung/config/DbConfig.java | 8 ++-- .../java/com/baeldung/models/Subject.java | 37 +++++++++++++++++++ .../repositories/SubjectRepository.java | 15 ++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 spring-data-rest/src/main/java/com/baeldung/models/Subject.java create mode 100644 spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java diff --git a/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java b/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java index 26d882d6a0..05fa27bbff 100644 --- a/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java +++ b/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java @@ -64,22 +64,22 @@ public class DbConfig { @Configuration @Profile("h2") -@PropertySource("persistence-h2.properties") +@PropertySource("classpath:persistence-h2.properties") class H2Config {} @Configuration @Profile("hsqldb") -@PropertySource("persistence-hsqldb.properties") +@PropertySource("classpath:persistence-hsqldb.properties") class HsqldbConfig {} @Configuration @Profile("derby") -@PropertySource("persistence-derby.properties") +@PropertySource("classpath:persistence-derby.properties") class DerbyConfig {} @Configuration @Profile("sqlite") -@PropertySource("persistence-sqlite.properties") +@PropertySource("classpath:persistence-sqlite.properties") class SqliteConfig {} diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Subject.java b/spring-data-rest/src/main/java/com/baeldung/models/Subject.java new file mode 100644 index 0000000000..b3b9a5b0a0 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/models/Subject.java @@ -0,0 +1,37 @@ +package com.baeldung.models; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Subject { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private long id; + + @Column(nullable = false) + private String name; + + public Subject() { + } + + 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; + } +} \ No newline at end of file diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java new file mode 100644 index 0000000000..a91ae2d505 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java @@ -0,0 +1,15 @@ +package com.baeldung.repositories; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.data.rest.core.annotation.RestResource; +import com.baeldung.models.Subject; + +public interface SubjectRepository extends PagingAndSortingRepository { + + @RestResource(path = "nameContains") + public Page findByNameContaining(@Param("name") String name, Pageable p); + +} \ No newline at end of file From e7412182a9e7f8d5e5ab13760b23580aad940d24 Mon Sep 17 00:00:00 2001 From: fanatixan Date: Sun, 13 Jan 2019 22:27:07 +0100 Subject: [PATCH 073/190] bael-2508 - Stream.peek() examples (#6132) * bael-2508 - Stream.peek() examples * beal-2508 additional example * bael-2508 moving examples --- .../com/baeldung/stream/PeekUnitTest.java | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 java-streams/src/test/java/com/baeldung/stream/PeekUnitTest.java diff --git a/java-streams/src/test/java/com/baeldung/stream/PeekUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/PeekUnitTest.java new file mode 100644 index 0000000000..a3a2816e9c --- /dev/null +++ b/java-streams/src/test/java/com/baeldung/stream/PeekUnitTest.java @@ -0,0 +1,118 @@ +package com.baeldung.stream; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.StringWriter; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class PeekUnitTest { + + private StringWriter out; + + @BeforeEach + void setup() { + out = new StringWriter(); + } + + @Test + void givenStringStream_whenCallingPeekOnly_thenNoElementProcessed() { + // given + Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); + + // when + nameStream.peek(out::append); + + // then + assertThat(out.toString()).isEmpty(); + } + + @Test + void givenStringStream_whenCallingForEachOnly_thenElementsProcessed() { + // given + Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); + + // when + nameStream.forEach(out::append); + + // then + assertThat(out.toString()).isEqualTo("AliceBobChuck"); + } + + @Test + void givenStringStream_whenCallingPeekAndNoopForEach_thenElementsProcessed() { + // given + Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); + + // when + nameStream.peek(out::append) + .forEach(this::noop); + + // then + assertThat(out.toString()).isEqualTo("AliceBobChuck"); + } + + @Test + void givenStringStream_whenCallingPeekAndCollect_thenElementsProcessed() { + // given + Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); + + // when + nameStream.peek(out::append) + .collect(Collectors.toList()); + + // then + assertThat(out.toString()).isEqualTo("AliceBobChuck"); + } + + @Test + void givenStringStream_whenCallingPeekAndForEach_thenElementsProcessedTwice() { + // given + Stream nameStream = Stream.of("Alice", "Bob", "Chuck"); + + // when + nameStream.peek(out::append) + .forEach(out::append); + + // then + assertThat(out.toString()).isEqualTo("AliceAliceBobBobChuckChuck"); + } + + @Test + void givenStringStream_whenCallingPeek_thenElementsProcessedTwice() { + // given + Stream userStream = Stream.of(new User("Alice"), new User("Bob"), new User("Chuck")); + + // when + userStream.peek(u -> u.setName(u.getName().toLowerCase())) + .map(User::getName) + .forEach(out::append); + + // then + assertThat(out.toString()).isEqualTo("alicebobchuck"); + } + + private static class User { + private String name; + + public User(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + private void noop(String s) { + } + +} From c9275edf90db9fc2c8d22ce7dd6f1f7780401605 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Mon, 14 Jan 2019 11:53:53 +0400 Subject: [PATCH 074/190] matching for all keywords --- .../java/com/baeldung/string/MatchWords.java | 51 +++++++++++++------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index 0b803da0ae..9374ef84a2 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -1,6 +1,7 @@ package com.baeldung.string; import org.ahocorasick.trie.Emit; +import org.ahocorasick.trie.Token; import org.ahocorasick.trie.Trie; import java.util.*; @@ -17,7 +18,7 @@ public class MatchWords { containsWords(inputString, words); - containsWordsJava8(new ArrayList<>(Arrays.asList(inputString.split(" "))), new ArrayList<>(Arrays.asList(words))); + containsWordsJava8(inputString, words); containsWordsPatternMatch(inputString, words); @@ -52,36 +53,56 @@ public class MatchWords { private static boolean containsWordsAhoCorasick(String inputString, String[] words) { Trie trie = Trie.builder() .onlyWholeWords() - .addKeyword(words[0]) - .addKeyword(words[1]) - .ignoreOverlaps() + .addKeywords(words) .build(); - Collection emits = trie.parseText(inputString) - .stream() - .filter(e -> !Objects.equals(e.getKeyword(), e.getKeyword())) - .collect(Collectors.toList()); - + Collection emits = trie.parseText(inputString); emits.forEach(System.out::println); - return emits.size() == words.length; + boolean found = true; + for(String word : words) { + boolean contains = Arrays.toString(emits.toArray()).contains(word); + if (!contains) { + found = false; + break; + } + } + + return found; } private static boolean containsWordsPatternMatch(String inputString, String[] words) { - Pattern pattern = Pattern.compile("(?=.*" + words[0] + ")(?=.*" + words[1] + ")"); + StringBuilder regexp = new StringBuilder(); + for (String word : words) { + regexp.append("(?=.*").append(word).append(")"); + } + Pattern pattern = Pattern.compile(regexp.toString()); if (pattern.matcher(inputString).find()) { return true; } return false; } - private static boolean containsWordsJava8(ArrayList inputString, ArrayList words) { - return words.stream().allMatch(inputString::contains); + private static boolean containsWordsJava8(String inputString, String[] words) { + ArrayList inputStringList = new ArrayList<>(Arrays.asList(inputString.split(" "))); + ArrayList wordsList = new ArrayList<>(Arrays.asList(words)); + + return wordsList.stream().allMatch(inputStringList::contains); } - private static boolean containsWordsArray(ArrayList inputString, ArrayList words) { - return inputString.containsAll(words); + private static boolean containsWordsArray(String inputString, String[] words) { + ArrayList inputStringList = new ArrayList<>(Arrays.asList(inputString.split(" "))); + ArrayList wordsList = new ArrayList<>(Arrays.asList(words)); + + return inputStringList.containsAll(wordsList); + } + + private static boolean containsAnyWord(String inputString, String[] words) { + ArrayList inputStringList = new ArrayList<>(Arrays.asList(inputString.split(" "))); + ArrayList wordsList = new ArrayList<>(Arrays.asList(words)); + + return inputStringList.contains(wordsList); } } From aa125c6c6b4820fd5c2e058071ab169e345e533e Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Mon, 14 Jan 2019 11:58:31 +0400 Subject: [PATCH 075/190] remove unnecessary method --- .../src/main/java/com/baeldung/string/MatchWords.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index 9374ef84a2..647b60af9a 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -77,6 +77,7 @@ public class MatchWords { for (String word : words) { regexp.append("(?=.*").append(word).append(")"); } + Pattern pattern = Pattern.compile(regexp.toString()); if (pattern.matcher(inputString).find()) { return true; @@ -97,12 +98,4 @@ public class MatchWords { return inputStringList.containsAll(wordsList); } - - private static boolean containsAnyWord(String inputString, String[] words) { - ArrayList inputStringList = new ArrayList<>(Arrays.asList(inputString.split(" "))); - ArrayList wordsList = new ArrayList<>(Arrays.asList(words)); - - return inputStringList.contains(wordsList); - } - } From a480f7b8d326b794e8003d54b0543380da2c4a64 Mon Sep 17 00:00:00 2001 From: Tom Hombergs Date: Mon, 14 Jan 2019 20:48:58 +0100 Subject: [PATCH 076/190] added link --- core-java-concurrency-basic/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core-java-concurrency-basic/README.md b/core-java-concurrency-basic/README.md index 1c43149d03..ad3de4a758 100644 --- a/core-java-concurrency-basic/README.md +++ b/core-java-concurrency-basic/README.md @@ -14,4 +14,5 @@ - [ExecutorService - Waiting for Threads to Finish](http://www.baeldung.com/java-executor-wait-for-threads) - [wait and notify() Methods in Java](http://www.baeldung.com/java-wait-notify) - [Life Cycle of a Thread in Java](http://www.baeldung.com/java-thread-lifecycle) -- [Runnable vs. Callable in Java](http://www.baeldung.com/java-runnable-callable) \ No newline at end of file +- [Runnable vs. Callable in Java](http://www.baeldung.com/java-runnable-callable) +- [What is Thread-Safety and How to Achieve it](https://www.baeldung.com/java-thread-safety) From d7bfa764629815684c6588ade9dc32eca58280f3 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Mon, 14 Jan 2019 22:21:27 +0200 Subject: [PATCH 077/190] Update README.md --- libraries-data/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries-data/README.md b/libraries-data/README.md index 69856af66b..077961f887 100644 --- a/libraries-data/README.md +++ b/libraries-data/README.md @@ -15,3 +15,4 @@ - [Intro to Apache Storm](https://www.baeldung.com/apache-storm) - [Guide to Ebean ORM](https://www.baeldung.com/ebean-orm) - [Introduction to Kafka Connectors](https://www.baeldung.com/kafka-connectors-guide) +- [Kafka Connect Example with MQTT and MongoDB](https://www.baeldung.com/kafka-connect-mqtt-mongodb) From 18e1a3067d660556d3c6e1b78debc64f525266d8 Mon Sep 17 00:00:00 2001 From: freddyaott Date: Tue, 15 Jan 2019 04:04:54 +0100 Subject: [PATCH 078/190] [BAEL-2270] Guide to XMPP Smack Client (#5959) Smack Library - Simple chat client --- libraries/log4j.properties | 4 + libraries/pom.xml | 25 ++++++ .../java/com/baeldung/smack/StanzaThread.java | 40 +++++++++ .../baeldung/smack/SmackIntegrationTest.java | 85 +++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 libraries/src/main/java/com/baeldung/smack/StanzaThread.java create mode 100644 libraries/src/test/java/com/baeldung/smack/SmackIntegrationTest.java diff --git a/libraries/log4j.properties b/libraries/log4j.properties index 2173c5d96f..ed367509d1 100644 --- a/libraries/log4j.properties +++ b/libraries/log4j.properties @@ -1 +1,5 @@ log4j.rootLogger=INFO, stdout +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 \ No newline at end of file diff --git a/libraries/pom.xml b/libraries/pom.xml index c7ef64bc59..301fa86c8d 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -675,6 +675,30 @@ ${mockftpserver.version} test + + + org.igniterealtime.smack + smack-tcp + ${smack.version} + + + + org.igniterealtime.smack + smack-im + ${smack.version} + + + + org.igniterealtime.smack + smack-extensions + ${smack.version} + + + + org.igniterealtime.smack + smack-java7 + ${smack.version} + @@ -896,6 +920,7 @@ 1.1.0 2.7.1 3.6 + 4.3.1 diff --git a/libraries/src/main/java/com/baeldung/smack/StanzaThread.java b/libraries/src/main/java/com/baeldung/smack/StanzaThread.java new file mode 100644 index 0000000000..72db258164 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/smack/StanzaThread.java @@ -0,0 +1,40 @@ +package com.baeldung.smack; + +import org.jivesoftware.smack.AbstractXMPPConnection; +import org.jivesoftware.smack.chat2.Chat; +import org.jivesoftware.smack.chat2.ChatManager; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; +import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; +import org.jxmpp.jid.impl.JidCreate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class StanzaThread implements Runnable { + + private Logger logger = LoggerFactory.getLogger(StanzaThread.class); + + @Override + public void run() { + XMPPTCPConnectionConfiguration config = null; + try { + config = XMPPTCPConnectionConfiguration.builder() + .setUsernameAndPassword("baeldung2","baeldung2") + .setXmppDomain("jabb3r.org") + .setHost("jabb3r.org") + .build(); + + AbstractXMPPConnection connection = new XMPPTCPConnection(config); + connection.connect(); + connection.login(); + + ChatManager chatManager = ChatManager.getInstanceFor(connection); + + Chat chat = chatManager.chatWith(JidCreate.from("baeldung@jabb3r.org").asEntityBareJidOrThrow()); + + chat.send("Hello!"); + + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } +} diff --git a/libraries/src/test/java/com/baeldung/smack/SmackIntegrationTest.java b/libraries/src/test/java/com/baeldung/smack/SmackIntegrationTest.java new file mode 100644 index 0000000000..1e5e36ce24 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/smack/SmackIntegrationTest.java @@ -0,0 +1,85 @@ +package com.baeldung.smack; + +import org.jivesoftware.smack.AbstractXMPPConnection; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.chat2.ChatManager; +import org.jivesoftware.smack.filter.StanzaTypeFilter; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; +import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.jxmpp.stringprep.XmppStringprepException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.concurrent.CountDownLatch; + +public class SmackIntegrationTest { + + private static AbstractXMPPConnection connection; + private Logger logger = LoggerFactory.getLogger(SmackIntegrationTest.class); + + @BeforeClass + public static void setup() throws IOException, InterruptedException, XMPPException, SmackException { + + XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() + .setUsernameAndPassword("baeldung","baeldung") + .setXmppDomain("jabb3r.org") + .setHost("jabb3r.org") + .build(); + + XMPPTCPConnectionConfiguration config2 = XMPPTCPConnectionConfiguration.builder() + .setUsernameAndPassword("baeldung2","baeldung2") + .setXmppDomain("jabb3r.org") + .setHost("jabb3r.org") + .build(); + + connection = new XMPPTCPConnection(config); + connection.connect(); + connection.login(); + + } + + @Test + public void whenSendMessageWithChat_thenReceiveMessage() throws XmppStringprepException, InterruptedException { + + CountDownLatch latch = new CountDownLatch(1); + ChatManager chatManager = ChatManager.getInstanceFor(connection); + final String[] expected = {null}; + + new StanzaThread().run(); + + chatManager.addIncomingListener((entityBareJid, message, chat) -> { + logger.info("Message arrived: " + message.getBody()); + expected[0] = message.getBody(); + latch.countDown(); + }); + + latch.await(); + Assert.assertEquals("Hello!", expected[0]); + } + + @Test + public void whenSendMessage_thenReceiveMessageWithFilter() throws XmppStringprepException, InterruptedException { + + CountDownLatch latch = new CountDownLatch(1); + final String[] expected = {null}; + + new StanzaThread().run(); + + connection.addAsyncStanzaListener(stanza -> { + if (stanza instanceof Message) { + Message message = (Message) stanza; + expected[0] = message.getBody(); + latch.countDown(); + } + }, StanzaTypeFilter.MESSAGE); + + latch.await(); + Assert.assertEquals("Hello!", expected[0]); + } +} From e7301029c346147df75c1b256a7ee8b50fc273b3 Mon Sep 17 00:00:00 2001 From: soufiane-cheouati <46105138+soufiane-cheouati@users.noreply.github.com> Date: Tue, 15 Jan 2019 16:37:38 +0000 Subject: [PATCH 079/190] Adding new methods for calculating the sum (#6088) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Creating new module Creating new module for Hexagonal Architecture * Adding Java classes Adding Java classes used in the example * Adding the pom.xml file Adding the pom.xml file. * Update the pom.xml file Update the pom.xml file * BAEL-2498: Creating new folder Creating new folder for Java 8 sum with Streams examples * BAEL-2498: Uploading java Classes Adding the Java classes containing examples of different methods to calculate the sum using Java 8 Streams * BAEL-2498: Creating new folder Creating new folder for sum unit tests * BAEL-2498: Adding the unit tests Adding the unit tests for the methods that calculate the sum using the Java Streams * Add files via Upload - Adding a method for calculating the sum of a map´s values - Adding a method for calculating the sum of numbers within a String object * Add files via upload - Adding a method for calculating the sum of a map´s values - Adding a method for calculating the sum of numbers within a String object * Delete . ... * Delete pom.xml * Delete User.java * Delete UserControler.java * Delete UserDataBaseAdapter.java * Delete UserInterfaceAdapter.java * Delete UserDataBasePort.java * Delete UserInterfacePort.java * Delete UserService.java --- .../main/java/com/baeldung/stream/sum/. .. | 1 + .../baeldung/stream/sum/ArithmeticUtils.java | 8 ++ .../java/com/baeldung/stream/sum/Item.java | 31 ++++ .../stream/sum/StreamSumCalculator.java | 59 ++++++++ .../sum/StreamSumCalculatorWithObject.java | 38 +++++ .../test/java/com/baeldung/stream/sum/. .. | 1 + .../stream/sum/StreamSumUnitTest.java | 136 ++++++++++++++++++ 7 files changed, 274 insertions(+) create mode 100644 java-streams/src/main/java/com/baeldung/stream/sum/. .. create mode 100644 java-streams/src/main/java/com/baeldung/stream/sum/ArithmeticUtils.java create mode 100644 java-streams/src/main/java/com/baeldung/stream/sum/Item.java create mode 100644 java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculator.java create mode 100644 java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculatorWithObject.java create mode 100644 java-streams/src/test/java/com/baeldung/stream/sum/. .. create mode 100644 java-streams/src/test/java/com/baeldung/stream/sum/StreamSumUnitTest.java diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/. .. b/java-streams/src/main/java/com/baeldung/stream/sum/. .. new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/stream/sum/. .. @@ -0,0 +1 @@ + diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/ArithmeticUtils.java b/java-streams/src/main/java/com/baeldung/stream/sum/ArithmeticUtils.java new file mode 100644 index 0000000000..3170b1fb31 --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/stream/sum/ArithmeticUtils.java @@ -0,0 +1,8 @@ +package com.baeldung.stream.sum; + +public class ArithmeticUtils { + + public static int add(int a, int b) { + return a + b; + } +} diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/Item.java b/java-streams/src/main/java/com/baeldung/stream/sum/Item.java new file mode 100644 index 0000000000..2f162d6eda --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/stream/sum/Item.java @@ -0,0 +1,31 @@ +package com.baeldung.stream.sum; + +public class Item { + + private int id; + private Integer price; + + public Item(int id, Integer price) { + super(); + this.id = id; + this.price = price; + } + + // Standard getters and setters + public long getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Integer getPrice() { + return price; + } + + public void setPrice(Integer price) { + this.price = price; + } + +} diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculator.java b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculator.java new file mode 100644 index 0000000000..2f63cf8629 --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculator.java @@ -0,0 +1,59 @@ +package com.baeldung.stream.sum; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class StreamSumCalculator { + + public static Integer getSumUsingCustomizedAccumulator(List integers) { + return integers.stream() + .reduce(0, ArithmeticUtils::add); + + } + + public static Integer getSumUsingJavaAccumulator(List integers) { + return integers.stream() + .reduce(0, Integer::sum); + + } + + public static Integer getSumUsingReduce(List integers) { + return integers.stream() + .reduce(0, (a, b) -> a + b); + + } + + public static Integer getSumUsingCollect(List integers) { + + return integers.stream() + .collect(Collectors.summingInt(Integer::intValue)); + + } + + public static Integer getSumUsingSum(List integers) { + + return integers.stream() + .mapToInt(Integer::intValue) + .sum(); + } + + public static Integer getSumOfMapValues(Map map) { + + return map.values() + .stream() + .mapToInt(Integer::valueOf) + .sum(); + } + + public static Integer getSumIntegersFromString(String str) { + + Integer sum = Arrays.stream(str.split(" ")) + .filter((s) -> s.matches("\\d+")) + .mapToInt(Integer::valueOf) + .sum(); + + return sum; + } +} diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculatorWithObject.java b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculatorWithObject.java new file mode 100644 index 0000000000..b83616928e --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/stream/sum/StreamSumCalculatorWithObject.java @@ -0,0 +1,38 @@ +package com.baeldung.stream.sum; + +import java.util.List; +import java.util.stream.Collectors; + +public class StreamSumCalculatorWithObject { + + public static Integer getSumUsingCustomizedAccumulator(List items) { + return items.stream() + .map(x -> x.getPrice()) + .reduce(0, ArithmeticUtils::add); + } + + public static Integer getSumUsingJavaAccumulator(List items) { + return items.stream() + .map(x -> x.getPrice()) + .reduce(0, Integer::sum); + } + + public static Integer getSumUsingReduce(List items) { + return items.stream() + .map(item -> item.getPrice()) + .reduce(0, (a, b) -> a + b); + } + + public static Integer getSumUsingCollect(List items) { + return items.stream() + .map(x -> x.getPrice()) + .collect(Collectors.summingInt(Integer::intValue)); + } + + public static Integer getSumUsingSum(List items) { + return items.stream() + .mapToInt(x -> x.getPrice()) + .sum(); + } + +} diff --git a/java-streams/src/test/java/com/baeldung/stream/sum/. .. b/java-streams/src/test/java/com/baeldung/stream/sum/. .. new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/java-streams/src/test/java/com/baeldung/stream/sum/. .. @@ -0,0 +1 @@ + diff --git a/java-streams/src/test/java/com/baeldung/stream/sum/StreamSumUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/sum/StreamSumUnitTest.java new file mode 100644 index 0000000000..46e1af9a4a --- /dev/null +++ b/java-streams/src/test/java/com/baeldung/stream/sum/StreamSumUnitTest.java @@ -0,0 +1,136 @@ +package com.baeldung.stream.sum; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +public class StreamSumUnitTest { + + @Test + public void givenListOfIntegersWhenSummingUsingCustomizedAccumulatorThenCorrectValueReturned() { + List integers = Arrays.asList(1, 2, 3, 4, 5); + Integer sum = StreamSumCalculator.getSumUsingCustomizedAccumulator(integers); + assertEquals(15, sum.intValue()); + + } + + @Test + public void givenListOfIntegersWhenSummingUsingJavaAccumulatorThenCorrectValueReturned() { + List integers = Arrays.asList(1, 2, 3, 4, 5); + Integer sum = StreamSumCalculator.getSumUsingJavaAccumulator(integers); + assertEquals(15, sum.intValue()); + } + + @Test + public void givenListOfIntegersWhenSummingUsingReduceThenCorrectValueReturned() { + List integers = Arrays.asList(1, 2, 3, 4, 5); + Integer sum = StreamSumCalculator.getSumUsingReduce(integers); + assertEquals(15, sum.intValue()); + } + + @Test + public void givenListOfIntegersWhenSummingUsingCollectThenCorrectValueReturned() { + List integers = Arrays.asList(1, 2, 3, 4, 5); + Integer sum = StreamSumCalculator.getSumUsingCollect(integers); + assertEquals(15, sum.intValue()); + } + + @Test + public void givenListOfIntegersWhenSummingUsingSumThenCorrectValueReturned() { + List integers = Arrays.asList(1, 2, 3, 4, 5); + Integer sum = StreamSumCalculator.getSumUsingSum(integers); + assertEquals(15, sum.intValue()); + } + + @Test + public void givenListOfItemsWhenSummingUsingCustomizedAccumulatorThenCorrectValueReturned() { + Item item1 = new Item(1, 10); + Item item2 = new Item(2, 15); + Item item3 = new Item(3, 25); + Item item4 = new Item(4, 40); + + List items = Arrays.asList(item1, item2, item3, item4); + + Integer sum = StreamSumCalculatorWithObject.getSumUsingCustomizedAccumulator(items); + assertEquals(90, sum.intValue()); + + } + + @Test + public void givenListOfItemsWhenSummingUsingJavaAccumulatorThenCorrectValueReturned() { + Item item1 = new Item(1, 10); + Item item2 = new Item(2, 15); + Item item3 = new Item(3, 25); + Item item4 = new Item(4, 40); + + List items = Arrays.asList(item1, item2, item3, item4); + + Integer sum = StreamSumCalculatorWithObject.getSumUsingJavaAccumulator(items); + assertEquals(90, sum.intValue()); + } + + @Test + public void givenListOfItemsWhenSummingUsingReduceThenCorrectValueReturned() { + Item item1 = new Item(1, 10); + Item item2 = new Item(2, 15); + Item item3 = new Item(3, 25); + Item item4 = new Item(4, 40); + + List items = Arrays.asList(item1, item2, item3, item4); + + Integer sum = StreamSumCalculatorWithObject.getSumUsingReduce(items); + assertEquals(90, sum.intValue()); + } + + @Test + public void givenListOfItemsWhenSummingUsingCollectThenCorrectValueReturned() { + Item item1 = new Item(1, 10); + Item item2 = new Item(2, 15); + Item item3 = new Item(3, 25); + Item item4 = new Item(4, 40); + + List items = Arrays.asList(item1, item2, item3, item4); + + Integer sum = StreamSumCalculatorWithObject.getSumUsingCollect(items); + assertEquals(90, sum.intValue()); + } + + @Test + public void givenListOfItemsWhenSummingUsingSumThenCorrectValueReturned() { + Item item1 = new Item(1, 10); + Item item2 = new Item(2, 15); + Item item3 = new Item(3, 25); + Item item4 = new Item(4, 40); + + List items = Arrays.asList(item1, item2, item3, item4); + + Integer sum = StreamSumCalculatorWithObject.getSumUsingSum(items); + assertEquals(90, sum.intValue()); + } + + @Test + public void givenMapWhenSummingThenCorrectValueReturned() { + Map map = new HashMap(); + map.put(1, 10); + map.put(2, 15); + map.put(3, 25); + map.put(4, 40); + + Integer sum = StreamSumCalculator.getSumOfMapValues(map); + assertEquals(90, sum.intValue()); + } + + @Test + public void givenStringWhenSummingThenCorrectValueReturned() { + String string = "Item1 10 Item2 25 Item3 30 Item4 45"; + + Integer sum = StreamSumCalculator.getSumIntegersFromString(string); + assertEquals(110, sum.intValue()); + } + +} From 0bfa50825bad3bd4bdb98712c7ff6e419f95d9dd Mon Sep 17 00:00:00 2001 From: Amy DeGregorio Date: Tue, 15 Jan 2019 15:31:37 -0500 Subject: [PATCH 080/190] BAEL-2499 Write to CSV in Java - updated (#6135) * example code for Article How to Write to a CSV File in Java * Updated to use a Stream * Updated to use Streams in convertToCSV for BAEL-2499 --- .../com/baeldung/csv/WriteCsvFileExample.java | 16 ++++++---------- .../csv/WriteCsvFileExampleUnitTest.java | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java b/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java index e1237481b1..f409d05b06 100644 --- a/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java +++ b/core-java-io/src/main/java/com/baeldung/csv/WriteCsvFileExample.java @@ -1,18 +1,14 @@ package com.baeldung.csv; +import java.util.stream.Collectors; +import java.util.stream.Stream; + public class WriteCsvFileExample { public String convertToCSV(String[] data) { - StringBuilder csvLine = new StringBuilder(); - - for (int i = 0; i < data.length; i++) { - if (i > 0) { - csvLine.append(","); - } - csvLine.append(escapeSpecialCharacters(data[i])); - } - - return csvLine.toString(); + return Stream.of(data) + .map(this::escapeSpecialCharacters) + .collect(Collectors.joining(",")); } public String escapeSpecialCharacters(String data) { diff --git a/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java b/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java index e30ec0818c..0658ec6101 100644 --- a/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java +++ b/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java @@ -65,7 +65,7 @@ public class WriteCsvFileExampleUnitTest { } @Test - public void givenBufferedWriter_whenWriteLine_thenOutputCreated() { + public void givenDataArray_whenConvertToCSV_thenOutputCreated() { List dataLines = new ArrayList(); dataLines.add(new String[] { "John", "Doe", "38", "Comment Data\nAnother line of comment data" }); dataLines.add(new String[] { "Jane", "Doe, Jr.", "19", "She said \"I'm being quoted\"" }); From 4c9ea991cc5edacd714fc566ce572a417181ce0c Mon Sep 17 00:00:00 2001 From: PRIFTI Date: Tue, 15 Jan 2019 21:38:40 +0100 Subject: [PATCH 081/190] BAEL-2441: Providing example for Implementing simple State Machine with Java Enums. --- .../enumstatemachine/LeaveRequestState.java | 46 +++++++++++++++++++ .../LeaveRequestStateTest.java | 41 +++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestState.java create mode 100644 algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestState.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestState.java new file mode 100644 index 0000000000..5153c2e18e --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestState.java @@ -0,0 +1,46 @@ +package com.baeldung.algorithms.enumstatemachine; + +public enum LeaveRequestState { + + Submitted { + @Override + public LeaveRequestState nextState() { + System.out.println("Starting the Leave Request and sending to Team Leader for approval."); + return Escalated; + } + + @Override + public String responsiblePerson() { + return "Employee"; + } + }, + Escalated { + @Override + public LeaveRequestState nextState() { + System.out.println("Reviewing the Leave Request and escalating to Department Manager."); + return Approved; + } + + @Override + public String responsiblePerson() { + return "Team Leader"; + } + }, + Approved { + @Override + public LeaveRequestState nextState() { + System.out.println("Approving the Leave Request."); + return this; + } + + @Override + public String responsiblePerson() { + return "Department Manager"; + } + }; + + public abstract String responsiblePerson(); + + public abstract LeaveRequestState nextState(); + +} diff --git a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java b/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java new file mode 100644 index 0000000000..b209dcb2fb --- /dev/null +++ b/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java @@ -0,0 +1,41 @@ +package com.baeldung.algorithms.enumstatemachine; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class LeaveRequestStateTest { + + @Test + public void givenLeaveRequest_whenStateEscalated_thenResponsibleIsTeamLeader() { + LeaveRequestState state = LeaveRequestState.Escalated; + + String responsible = state.responsiblePerson(); + + assertEquals(responsible, "Team Leader"); + } + + + @Test + public void givenLeaveRequest_whenStateApproved_thenResponsibleIsDepartmentManager() { + LeaveRequestState state = LeaveRequestState.Approved; + + String responsible = state.responsiblePerson(); + + assertEquals(responsible, "Department Manager"); + } + + @Test + public void givenLeaveRequest_whenNextStateIsCalled_thenStateIsChanged() { + LeaveRequestState state = LeaveRequestState.Submitted; + + state = state.nextState(); + assertEquals(state, LeaveRequestState.Escalated); + + state = state.nextState(); + assertEquals(state, LeaveRequestState.Approved); + + state = state.nextState(); + assertEquals(state, LeaveRequestState.Approved); + } +} From 22e98e06eafae25dbbf7a9eaaf7e858d4b11d519 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Tue, 15 Jan 2019 18:45:36 -0200 Subject: [PATCH 082/190] Removed most exception handlers from spring-rest-full (except the ones used in other articles) and moved them to spring-boot-rest --- .../RestResponseEntityExceptionHandler.java | 86 +++++++++++++++++++ .../web/exception/MyDataAccessException.java | 21 +++++ .../MyDataIntegrityViolationException.java | 21 +++++ .../MyResourceNotFoundException.java | 21 +++++ spring-rest-full/.attach_pid28499 | 0 spring-rest-full/pom.xml | 43 ---------- .../RestResponseEntityExceptionHandler.java | 61 +------------ ...{TestSuite.java => TestSuiteLiveTest.java} | 6 +- ...tSuite.java => LiveTestSuiteLiveTest.java} | 2 +- 9 files changed, 154 insertions(+), 107 deletions(-) create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataAccessException.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataIntegrityViolationException.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java create mode 100644 spring-rest-full/.attach_pid28499 rename spring-rest-full/src/test/java/org/baeldung/{TestSuite.java => TestSuiteLiveTest.java} (68%) rename spring-rest-full/src/test/java/org/baeldung/web/{LiveTestSuite.java => LiveTestSuiteLiveTest.java} (87%) diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java new file mode 100644 index 0000000000..fe0465156d --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java @@ -0,0 +1,86 @@ +package com.baeldung.web.error; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +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; + +import com.baeldung.web.exception.MyDataAccessException; +import com.baeldung.web.exception.MyDataIntegrityViolationException; +import com.baeldung.web.exception.MyResourceNotFoundException; + +@ControllerAdvice +public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { + + public RestResponseEntityExceptionHandler() { + super(); + } + + // API + + // 400 + /* + * Some examples of exceptions that we could retrieve as 400 (BAD_REQUEST) responses: + * Hibernate's ConstraintViolationException + * Spring's DataIntegrityViolationException + */ + @ExceptionHandler({ MyDataIntegrityViolationException.class }) + public ResponseEntity handleBadRequest(final MyDataIntegrityViolationException ex, final WebRequest request) { + final String bodyOfResponse = "This should be application specific"; + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); + } + + @Override + protected ResponseEntity handleHttpMessageNotReadable(final HttpMessageNotReadableException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + final String bodyOfResponse = "This should be application specific"; + // ex.getCause() instanceof JsonMappingException, JsonParseException // for additional information later on + return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request); + } + + @Override + protected ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + final String bodyOfResponse = "This should be application specific"; + return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request); + } + + + // 404 + /* + * Some examples of exceptions that we could retrieve as 404 (NOT_FOUND) responses: + * Java Persistence's EntityNotFoundException + */ + @ExceptionHandler(value = { MyResourceNotFoundException.class }) + protected ResponseEntity handleNotFound(final RuntimeException ex, final WebRequest request) { + final String bodyOfResponse = "This should be application specific"; + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request); + } + + // 409 + /* + * Some examples of exceptions that we could retrieve as 409 (CONFLICT) responses: + * Spring's InvalidDataAccessApiUsageException + * Spring's DataAccessException + */ + @ExceptionHandler({ MyDataAccessException.class}) + protected ResponseEntity handleConflict(final RuntimeException ex, final WebRequest request) { + final String bodyOfResponse = "This should be application specific"; + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request); + } + + // 412 + + // 500 + + @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class }) + /*500*/public ResponseEntity handleInternal(final RuntimeException ex, final WebRequest request) { + logger.error("500 Status Code", ex); + final String bodyOfResponse = "This should be application specific"; + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request); + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataAccessException.java b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataAccessException.java new file mode 100644 index 0000000000..8fc9a3a0ea --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataAccessException.java @@ -0,0 +1,21 @@ +package com.baeldung.web.exception; + +public final class MyDataAccessException extends RuntimeException { + + public MyDataAccessException() { + super(); + } + + public MyDataAccessException(final String message, final Throwable cause) { + super(message, cause); + } + + public MyDataAccessException(final String message) { + super(message); + } + + public MyDataAccessException(final Throwable cause) { + super(cause); + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataIntegrityViolationException.java b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataIntegrityViolationException.java new file mode 100644 index 0000000000..50adb09c09 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataIntegrityViolationException.java @@ -0,0 +1,21 @@ +package com.baeldung.web.exception; + +public final class MyDataIntegrityViolationException extends RuntimeException { + + public MyDataIntegrityViolationException() { + super(); + } + + public MyDataIntegrityViolationException(final String message, final Throwable cause) { + super(message, cause); + } + + public MyDataIntegrityViolationException(final String message) { + super(message); + } + + public MyDataIntegrityViolationException(final Throwable cause) { + super(cause); + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java new file mode 100644 index 0000000000..fd002efc28 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java @@ -0,0 +1,21 @@ +package com.baeldung.web.exception; + +public final class MyResourceNotFoundException extends RuntimeException { + + 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-full/.attach_pid28499 b/spring-rest-full/.attach_pid28499 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-rest-full/pom.xml b/spring-rest-full/pom.xml index 81c938a289..ddc7e042b5 100644 --- a/spring-rest-full/pom.xml +++ b/spring-rest-full/pom.xml @@ -212,23 +212,6 @@ org.apache.maven.plugins maven-war-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - - 3 - true - - **/*IntegrationTest.java - **/*IntTest.java - **/*LongRunningUnitTest.java - **/*ManualTest.java - **/*LiveTest.java - **/*TestSuite.java - - - org.codehaus.cargo cargo-maven2-plugin @@ -274,32 +257,6 @@ live - - org.apache.maven.plugins - maven-surefire-plugin - - - integration-test - - test - - - - **/*IntegrationTest.java - **/*IntTest.java - - - **/*LiveTest.java - - - - - - - json - - - org.codehaus.cargo cargo-maven2-plugin diff --git a/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java index b593116c4a..c0639acef4 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java +++ b/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java @@ -1,17 +1,9 @@ package org.baeldung.web.error; -import javax.persistence.EntityNotFoundException; - import org.baeldung.web.exception.MyResourceNotFoundException; -import org.hibernate.exception.ConstraintViolationException; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageNotReadableException; -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; @@ -24,61 +16,10 @@ public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionH super(); } - // API - - // 400 - - @ExceptionHandler({ ConstraintViolationException.class }) - public ResponseEntity handleBadRequest(final ConstraintViolationException ex, final WebRequest request) { - final String bodyOfResponse = "This should be application specific"; - return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); - } - - @ExceptionHandler({ DataIntegrityViolationException.class }) - public ResponseEntity handleBadRequest(final DataIntegrityViolationException ex, final WebRequest request) { - final String bodyOfResponse = "This should be application specific"; - return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); - } - - @Override - protected ResponseEntity handleHttpMessageNotReadable(final HttpMessageNotReadableException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { - final String bodyOfResponse = "This should be application specific"; - // ex.getCause() instanceof JsonMappingException, JsonParseException // for additional information later on - return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request); - } - - @Override - protected ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { - final String bodyOfResponse = "This should be application specific"; - return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request); - } - - - // 404 - - @ExceptionHandler(value = { EntityNotFoundException.class, MyResourceNotFoundException.class }) + @ExceptionHandler(value = { MyResourceNotFoundException.class }) protected ResponseEntity handleNotFound(final RuntimeException ex, final WebRequest request) { final String bodyOfResponse = "This should be application specific"; return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request); } - // 409 - - @ExceptionHandler({ InvalidDataAccessApiUsageException.class, DataAccessException.class }) - protected ResponseEntity handleConflict(final RuntimeException ex, final WebRequest request) { - final String bodyOfResponse = "This should be application specific"; - return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request); - } - - // 412 - - // 500 - - @ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class }) - /*500*/public ResponseEntity handleInternal(final RuntimeException ex, final WebRequest request) { - logger.error("500 Status Code", ex); - final String bodyOfResponse = "This should be application specific"; - return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request); - } - } diff --git a/spring-rest-full/src/test/java/org/baeldung/TestSuite.java b/spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java similarity index 68% rename from spring-rest-full/src/test/java/org/baeldung/TestSuite.java rename to spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java index cd5fa4661f..76215bb6e3 100644 --- a/spring-rest-full/src/test/java/org/baeldung/TestSuite.java +++ b/spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java @@ -1,7 +1,7 @@ package org.baeldung; import org.baeldung.persistence.PersistenceTestSuite; -import org.baeldung.web.LiveTestSuite; +import org.baeldung.web.LiveTestSuiteLiveTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; @@ -9,8 +9,8 @@ import org.junit.runners.Suite; @Suite.SuiteClasses({ // @formatter:off PersistenceTestSuite.class - ,LiveTestSuite.class + ,LiveTestSuiteLiveTest.class }) // -public class TestSuite { +public class TestSuiteLiveTest { } diff --git a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuite.java b/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java similarity index 87% rename from spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuite.java rename to spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java index 6d5b94a686..71a61ed338 100644 --- a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuite.java +++ b/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java @@ -10,6 +10,6 @@ import org.junit.runners.Suite; ,FooLiveTest.class ,FooPageableLiveTest.class }) // -public class LiveTestSuite { +public class LiveTestSuiteLiveTest { } From 9f798d483d03f07d179dd5542101af8eaa1fd9ef Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Wed, 16 Jan 2019 13:18:04 +0400 Subject: [PATCH 083/190] test the methods with Unit test --- .../java/com/baeldung/string/MatchWords.java | 27 ++------- .../baeldung/string/MatchWordsUnitTest.java | 59 +++++++++++++++++++ 2 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index 647b60af9a..d322d192fa 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -12,22 +12,7 @@ import java.util.stream.Stream; public class MatchWords { - public static void main(String[] args) { - String[] words = {"hello", "Baeldung"}; - String inputString = "hello there, Baeldung"; - - containsWords(inputString, words); - - containsWordsJava8(inputString, words); - - containsWordsPatternMatch(inputString, words); - - containsWordsAhoCorasick(inputString, words); - - containsWordsIndexOf(inputString, words); - } - - private static boolean containsWordsIndexOf(String inputString, String[] words) { + public static boolean containsWordsIndexOf(String inputString, String[] words) { boolean found = true; for (String word : words) { int index = inputString.indexOf(word); @@ -39,7 +24,7 @@ public class MatchWords { return found; } - private static boolean containsWords(String inputString, String[] items) { + public static boolean containsWords(String inputString, String[] items) { boolean found = true; for (String item : items) { if (!inputString.contains(item)) { @@ -50,7 +35,7 @@ public class MatchWords { return found; } - private static boolean containsWordsAhoCorasick(String inputString, String[] words) { + public static boolean containsWordsAhoCorasick(String inputString, String[] words) { Trie trie = Trie.builder() .onlyWholeWords() .addKeywords(words) @@ -71,7 +56,7 @@ public class MatchWords { return found; } - private static boolean containsWordsPatternMatch(String inputString, String[] words) { + public static boolean containsWordsPatternMatch(String inputString, String[] words) { StringBuilder regexp = new StringBuilder(); for (String word : words) { @@ -85,14 +70,14 @@ public class MatchWords { return false; } - private static boolean containsWordsJava8(String inputString, String[] words) { + public static boolean containsWordsJava8(String inputString, String[] words) { ArrayList inputStringList = new ArrayList<>(Arrays.asList(inputString.split(" "))); ArrayList wordsList = new ArrayList<>(Arrays.asList(words)); return wordsList.stream().allMatch(inputStringList::contains); } - private static boolean containsWordsArray(String inputString, String[] words) { + public static boolean containsWordsArray(String inputString, String[] words) { ArrayList inputStringList = new ArrayList<>(Arrays.asList(inputString.split(" "))); ArrayList wordsList = new ArrayList<>(Arrays.asList(words)); diff --git a/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java b/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java new file mode 100644 index 0000000000..0b25a265b3 --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java @@ -0,0 +1,59 @@ +package com.baeldung.string; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MatchWordsUnitTest { + + private final String[] words = {"hello", "Baeldung"}; + private final String inputString = "hello there, Baeldung"; + + @Test + public void givenText_whenCallingStringContains_shouldMatchWords() { + + final boolean result = MatchWords.containsWords(inputString, words); + + assertThat(result).isEqualTo(true); + } + + @Test + public void givenText_whenCallingJava8_shouldMatchWords() { + + final boolean result = MatchWords.containsWordsJava8(inputString, words); + + assertThat(result).isEqualTo(true); + } + + @Test + public void givenText_whenCallingPattern_shouldMatchWords() { + + final boolean result = MatchWords.containsWordsPatternMatch(inputString, words); + + assertThat(result).isEqualTo(true); + } + + @Test + public void givenText_whenCallingAhoCorasick_shouldMatchWords() { + + final boolean result = MatchWords.containsWordsAhoCorasick(inputString, words); + + assertThat(result).isEqualTo(true); + } + + @Test + public void givenText_whenCallingIndexOf_shouldMatchWords() { + + final boolean result = MatchWords.containsWordsIndexOf(inputString, words); + + assertThat(result).isEqualTo(true); + } + + @Test + public void givenText_whenCallingArrayList_shouldMatchWords() { + + final boolean result = MatchWords.containsWordsArray(inputString, words); + + assertThat(result).isEqualTo(true); + } +} From 438ff48c275d1d1dd92bbf3e210b300b422c19d7 Mon Sep 17 00:00:00 2001 From: cror Date: Wed, 16 Jan 2019 17:09:44 +0100 Subject: [PATCH 084/190] BAEL-2546: added Stream.count examples --- .../stream/filter/StreamCountUnitTest.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java diff --git a/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java new file mode 100644 index 0000000000..1cad710e14 --- /dev/null +++ b/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.stream.filter; + +import org.junit.Test; +import org.junit.Before; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class StreamCountUnitTest { + + private List customers; + + @Before + public void setUp() { + Customer john = new Customer("John P.", 15, "https://images.unsplash.com/photo-1543320485-d0d5a49c2b2e"); + Customer sarah = new Customer("Sarah M.", 200); + Customer charles = new Customer("Charles B.", 150); + Customer mary = new Customer("Mary T.", 1, "https://images.unsplash.com/photo-1543297057-25167dfc180e"); + customers = Arrays.asList(john, sarah, charles, mary); + } + + @Test + public void givenListOfCustomers_whenCount_thenGetListSize() { + long count = customers + .stream() + .count(); + + assertThat(count).isEqualTo(4L); + } + + @Test + public void givenListOfCustomers_whenFilterByPointsOver100AndCount_thenGetTwo() { + long countBigCustomers = customers + .stream() + .filter(c -> c.getPoints() > 100) + .count(); + + assertThat(countBigCustomers).isEqualTo(2L); + } + + @Test + public void givenListOfCustomers_whenFilterByPointsAndNameAndCount_thenGetOne() { + long count = customers + .stream() + .filter(c -> c.getPoints() > 10 && c.getName().startsWith("Charles")) + .count(); + + assertThat(count).isEqualTo(1L); + } + + @Test + public void givenListOfCustomers_whenNoneMatchesFilterAndCount_thenGetZero() { + long count = customers + .stream() + .filter(c -> c.getPoints() > 500) + .count(); + + assertThat(count).isEqualTo(0L); + } + + @Test + public void givenListOfCustomers_whenUsingMethodOverHundredPointsAndCount_thenGetTwo() { + long count = customers + .stream() + .filter(Customer::hasOverThousandPoints) + .count(); + + assertThat(count).isEqualTo(2L); + } +} From 2b7e66a3989bebd92e76d4d116f74b72db2edcc4 Mon Sep 17 00:00:00 2001 From: cror Date: Wed, 16 Jan 2019 17:14:35 +0100 Subject: [PATCH 085/190] renaming method according to content: thousand -> hundred --- .../src/main/java/com/baeldung/stream/filter/Customer.java | 2 +- .../java/com/baeldung/stream/filter/StreamCountUnitTest.java | 2 +- .../java/com/baeldung/stream/filter/StreamFilterUnitTest.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java b/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java index 49da6e7175..fd4f6021ff 100644 --- a/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java +++ b/java-streams/src/main/java/com/baeldung/stream/filter/Customer.java @@ -32,7 +32,7 @@ public class Customer { return this.points > points; } - public boolean hasOverThousandPoints() { + public boolean hasOverHundredPoints() { return this.points > 100; } diff --git a/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java index 1cad710e14..742e5aedc9 100644 --- a/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java +++ b/java-streams/src/test/java/com/baeldung/stream/filter/StreamCountUnitTest.java @@ -64,7 +64,7 @@ public class StreamCountUnitTest { public void givenListOfCustomers_whenUsingMethodOverHundredPointsAndCount_thenGetTwo() { long count = customers .stream() - .filter(Customer::hasOverThousandPoints) + .filter(Customer::hasOverHundredPoints) .count(); assertThat(count).isEqualTo(2L); diff --git a/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java index cf82802940..29190f7298 100644 --- a/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java +++ b/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java @@ -62,7 +62,7 @@ public class StreamFilterUnitTest { List customersWithMoreThan100Points = customers .stream() - .filter(Customer::hasOverThousandPoints) + .filter(Customer::hasOverHundredPoints) .collect(Collectors.toList()); assertThat(customersWithMoreThan100Points).hasSize(2); @@ -81,7 +81,7 @@ public class StreamFilterUnitTest { .flatMap(c -> c .map(Stream::of) .orElseGet(Stream::empty)) - .filter(Customer::hasOverThousandPoints) + .filter(Customer::hasOverHundredPoints) .collect(Collectors.toList()); assertThat(customersWithMoreThan100Points).hasSize(2); From 212ea5d83b68a5b053a3cda462bed2d3b9b1086b Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Thu, 17 Jan 2019 00:30:52 +0530 Subject: [PATCH 086/190] BAEL-2129 Added Unit test for Void Type in Kotlin article (#5944) --- .../baeldung/voidtypes/VoidTypesUnitTest.kt | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt new file mode 100644 index 0000000000..5c285c3135 --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt @@ -0,0 +1,51 @@ +package com.baeldung.voidtypes + +import org.junit.jupiter.api.Test +import kotlin.test.assertNull +import kotlin.test.assertTrue + +class VoidTypesUnitTest { + + fun returnTypeAsVoid(): Void? { + println("Function can have Void as return type") + return null + } + + fun unitReturnTypeForNonMeaningfulReturns(): Unit { + println("No meaningful return") + } + + fun unitReturnTypeIsImplicit() { + println("Unit Return type is implicit") + } + + fun alwaysThrowException(): Nothing { + throw IllegalArgumentException() + } + + fun invokeANothingOnlyFunction() { + alwaysThrowException() + + var name = "Tom" + } + + @Test + fun givenJavaVoidFunction_thenMappedToKotlinUnit() { + assertTrue(System.out.println() is Unit) + } + + @Test + fun givenVoidReturnType_thenReturnsNullOnly() { + assertNull(returnTypeAsVoid()) + } + + @Test + fun givenUnitReturnTypeDeclared_thenReturnsOfTypeUnit() { + assertTrue(unitReturnTypeForNonMeaningfulReturns() is Unit) + } + + @Test + fun givenUnitReturnTypeNotDeclared_thenReturnsOfTypeUnit() { + assertTrue(unitReturnTypeIsImplicit() is Unit) + } +} \ No newline at end of file From e6e0c065d509357f6a04bef853ad0f52c4c9e420 Mon Sep 17 00:00:00 2001 From: Rajesh Bhojwani Date: Thu, 17 Jan 2019 15:17:09 +0530 Subject: [PATCH 087/190] Added test file to demo the deletion of file content --- .../file/FilesClearDataManualTest.java | 98 +++++++++++++++++++ .../src/test/resources/fileexample.txt | 1 + 2 files changed, 99 insertions(+) create mode 100644 core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java create mode 100644 core-java-io/src/test/resources/fileexample.txt diff --git a/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java b/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java new file mode 100644 index 0000000000..8a4b3a7380 --- /dev/null +++ b/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java @@ -0,0 +1,98 @@ +package com.baeldung.file; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; + +import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.util.StreamUtils; + +public class FilesClearDataManualTest { + + public static final String FILE_PATH = "src/test/resources/fileexample.txt"; + + @Before + @After + public void setup() throws IOException { + PrintWriter writer = new PrintWriter(FILE_PATH); + writer.print("This example shows how we can delete the file contents without deleting the file"); + writer.close(); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingPrintWritter_thenEmptyFile() throws IOException { + PrintWriter writer = new PrintWriter(FILE_PATH); + writer.print(""); + writer.close(); + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingPrintWritterWithougObject_thenEmptyFile() throws IOException { + new PrintWriter(FILE_PATH).close(); + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + + @Test + public void givenExistingFile_whenDeleteContentUsingFileWriter_thenEmptyFile() throws IOException { + new FileWriter(FILE_PATH, false).close(); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingFileOutputStream_thenEmptyFile() throws IOException { + new FileOutputStream(FILE_PATH).close(); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingFileUtils_thenEmptyFile() throws IOException { + FileUtils.write(new File(FILE_PATH), "", Charset.defaultCharset()); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingNIOFiles_thenEmptyFile() throws IOException { + BufferedWriter writer = Files.newBufferedWriter(Paths.get(FILE_PATH)); + writer.write(""); + writer.flush(); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingNIOFileChannel_thenEmptyFile() throws IOException { + FileChannel.open(Paths.get(FILE_PATH), StandardOpenOption.WRITE).truncate(0).close(); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + + @Test + public void givenExistingFile_whenDeleteContentUsingGuava_thenEmptyFile() throws IOException { + File file = new File(FILE_PATH); + byte[] empty = new byte[0]; + com.google.common.io.Files.write(empty, file); + + assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); + } + +} diff --git a/core-java-io/src/test/resources/fileexample.txt b/core-java-io/src/test/resources/fileexample.txt new file mode 100644 index 0000000000..ee48fdfb84 --- /dev/null +++ b/core-java-io/src/test/resources/fileexample.txt @@ -0,0 +1 @@ +This example shows how we can delete the file contents without deleting the file \ No newline at end of file From 273c569b88de74d048a1b7989021c686c9764dbf Mon Sep 17 00:00:00 2001 From: Rajesh Bhojwani Date: Thu, 17 Jan 2019 15:20:25 +0530 Subject: [PATCH 088/190] remove space --- .../test/java/com/baeldung/file/FilesClearDataManualTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java b/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java index 8a4b3a7380..c00290168c 100644 --- a/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java +++ b/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java @@ -47,7 +47,6 @@ public class FilesClearDataManualTest { new PrintWriter(FILE_PATH).close(); assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); } - @Test public void givenExistingFile_whenDeleteContentUsingFileWriter_thenEmptyFile() throws IOException { From b47140fdd2607b6565df0c49bda7933ab2300252 Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Thu, 17 Jan 2019 15:44:27 +0100 Subject: [PATCH 089/190] Delete . .. --- java-streams/src/main/java/com/baeldung/stream/sum/. .. | 1 - 1 file changed, 1 deletion(-) delete mode 100644 java-streams/src/main/java/com/baeldung/stream/sum/. .. diff --git a/java-streams/src/main/java/com/baeldung/stream/sum/. .. b/java-streams/src/main/java/com/baeldung/stream/sum/. .. deleted file mode 100644 index 8b13789179..0000000000 --- a/java-streams/src/main/java/com/baeldung/stream/sum/. .. +++ /dev/null @@ -1 +0,0 @@ - From af1636fe23675e77fbb914d11c4f745978ed1a4e Mon Sep 17 00:00:00 2001 From: "Erick Audet M.Sc" Date: Thu, 17 Jan 2019 12:21:30 -0500 Subject: [PATCH 090/190] BAEL-2509 * New section in InputStream to byte array article and recreating branch. * Minor typo * Code reformat using intellij formatter. * Code reformat using intellij formatter. * guava implementation to be completed * guava implementation * Added assert to guava test * Fix formatting * Formatting using Baeldung format * Based on Josh comments, I removed some code BAEL-2509 * Removed all references to File * Update fork from upstream * Update fork from upstream * Merhe Upstream * Remove all references to FileInputStream (Josh Comments) * Delete CustomBaeldungQueueUnitTest.java --- .../io/InputStreamToByteBufferUnitTest.java | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java b/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java index fedadde04b..37f52fefea 100644 --- a/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java +++ b/core-java-io/src/test/java/org/baeldung/java/io/InputStreamToByteBufferUnitTest.java @@ -1,60 +1,56 @@ package org.baeldung.java.io; - +import com.google.common.io.ByteSource; import com.google.common.io.ByteStreams; import org.apache.commons.io.IOUtils; -import org.junit.jupiter.api.Test; +import org.junit.Test; -import java.io.File; -import java.io.FileInputStream; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static java.nio.channels.Channels.newChannel; +import static org.junit.Assert.assertEquals; -class InputStreamToByteBufferUnitTest { +public class InputStreamToByteBufferUnitTest { @Test - public void givenUsingCoreClasses_whenWritingAFileIntoAByteBuffer_thenBytesLengthMustMatch() throws IOException { - File inputFile = getFile(); - ByteBuffer bufferByte = ByteBuffer.allocate((int) inputFile.length()); - FileInputStream in = new FileInputStream(inputFile); - in.getChannel().read(bufferByte); + public void givenUsingCoreClasses_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { + byte[] input = new byte[] { 0, 1, 2 }; + InputStream initialStream = new ByteArrayInputStream(input); + ByteBuffer byteBuffer = ByteBuffer.allocate(3); + while (initialStream.available() > 0) { + byteBuffer.put((byte) initialStream.read()); + } - assertEquals(bufferByte.position(), inputFile.length()); + assertEquals(byteBuffer.position(), input.length); } @Test - public void givenUsingCommonsIo_whenWritingAFileIntoAByteBuffer_thenBytesLengthMustMatch() throws IOException { - File inputFile = getFile(); - ByteBuffer bufferByte = ByteBuffer.allocateDirect((int) inputFile.length()); - ReadableByteChannel readableByteChannel = new FileInputStream(inputFile).getChannel(); - IOUtils.readFully(readableByteChannel, bufferByte); - - assertEquals(bufferByte.position(), inputFile.length()); - } - - @Test - public void givenUsingGuava_whenWritingAFileIntoAByteBuffer_thenBytesLengthMustMatch() throws IOException { - File inputFile = getFile(); - FileInputStream in = new FileInputStream(inputFile); - byte[] targetArray = ByteStreams.toByteArray(in); + public void givenUsingGuava__whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { + InputStream initialStream = ByteSource + .wrap(new byte[] { 0, 1, 2 }) + .openStream(); + byte[] targetArray = ByteStreams.toByteArray(initialStream); ByteBuffer bufferByte = ByteBuffer.wrap(targetArray); - bufferByte.rewind(); while (bufferByte.hasRemaining()) { bufferByte.get(); } - - assertEquals(bufferByte.position(), inputFile.length()); + + assertEquals(bufferByte.position(), targetArray.length); } - private File getFile() { - ClassLoader classLoader = new InputStreamToByteBufferUnitTest().getClass().getClassLoader(); + @Test + public void givenUsingCommonsIo_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { + byte[] input = new byte[] { 0, 1, 2 }; + InputStream initialStream = new ByteArrayInputStream(input); + ByteBuffer byteBuffer = ByteBuffer.allocate(3); + ReadableByteChannel channel = newChannel(initialStream); + IOUtils.readFully(channel, byteBuffer); - String fileName = "frontenac-2257154_960_720.jpg"; - - return new File(classLoader.getResource(fileName).getFile()); + assertEquals(byteBuffer.position(), input.length); } } From 684ee6040e4fad45a30da1d7d46b86ce49913b34 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Thu, 17 Jan 2019 17:44:49 -0200 Subject: [PATCH 091/190] Added example for spring boot exception handling --- spring-boot-rest/README.md | 1 + spring-boot-rest/pom.xml | 11 ++++ .../boot/ErrorHandlingBootApplication.java | 15 +++++ .../MyCustomErrorAttributes.java | 23 +++++++ .../configurations/MyErrorController.java | 31 +++++++++ .../boot/web/FaultyRestController.java | 15 +++++ .../web/SpringBootRestApplication.java | 2 +- .../errorhandling-application.properties | 3 + .../boot/ErrorHandlingLiveTest.java | 65 +++++++++++++++++++ .../web/SpringContextIntegrationTest.java | 2 +- spring-rest-full/README.md | 1 - 11 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/ErrorHandlingBootApplication.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyCustomErrorAttributes.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyErrorController.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/web/FaultyRestController.java create mode 100644 spring-boot-rest/src/main/resources/errorhandling-application.properties create mode 100644 spring-boot-rest/src/test/java/com/baeldung/errorhandling/boot/ErrorHandlingLiveTest.java diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index 0a8d13cf76..2b955ddc5b 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -1,3 +1,4 @@ Module for the articles that are part of the Spring REST E-book: 1. [Bootstrap a Web Application with Spring 5](https://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) +2. [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring) diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index baf9d35a09..3b8cf7e39e 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -20,12 +20,22 @@ org.springframework.boot spring-boot-starter-web + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + org.springframework.boot spring-boot-starter-test test + + net.sourceforge.htmlunit + htmlunit + ${htmlunit.version} + test + @@ -39,5 +49,6 @@ com.baeldung.SpringBootRestApplication + 2.32 diff --git a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/ErrorHandlingBootApplication.java b/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/ErrorHandlingBootApplication.java new file mode 100644 index 0000000000..0885ecbbf7 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/ErrorHandlingBootApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.errorhandling.boot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication +@PropertySource("errorhandling-application.properties") +public class ErrorHandlingBootApplication { + + public static void main(String[] args) { + SpringApplication.run(ErrorHandlingBootApplication.class, args); + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyCustomErrorAttributes.java b/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyCustomErrorAttributes.java new file mode 100644 index 0000000000..e2c62cb907 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyCustomErrorAttributes.java @@ -0,0 +1,23 @@ +package com.baeldung.errorhandling.boot.configurations; + +import java.util.Map; + +import org.springframework.boot.web.servlet.error.DefaultErrorAttributes; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.WebRequest; + +@Component +public class MyCustomErrorAttributes extends DefaultErrorAttributes { + + @Override + public Map getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) { + Map errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace); + errorAttributes.put("locale", webRequest.getLocale() + .toString()); + errorAttributes.remove("error"); + errorAttributes.put("cause", errorAttributes.get("message")); + errorAttributes.remove("message"); + errorAttributes.put("status", String.valueOf(errorAttributes.get("status"))); + return errorAttributes; + } +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyErrorController.java b/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyErrorController.java new file mode 100644 index 0000000000..427a0b43d7 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyErrorController.java @@ -0,0 +1,31 @@ +package com.baeldung.errorhandling.boot.configurations; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.boot.autoconfigure.web.ErrorProperties; +import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; +import org.springframework.boot.web.servlet.error.ErrorAttributes; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestMapping; + +@Component +public class MyErrorController extends BasicErrorController { + + public MyErrorController(ErrorAttributes errorAttributes) { + super(errorAttributes, new ErrorProperties()); + } + + @RequestMapping(produces = MediaType.APPLICATION_XML_VALUE) + public ResponseEntity> xmlError(HttpServletRequest request) { + Map body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.APPLICATION_XML)); + body.put("xmlkey", "the XML response is different!"); + HttpStatus status = getStatus(request); + return new ResponseEntity<>(body, status); + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/web/FaultyRestController.java b/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/web/FaultyRestController.java new file mode 100644 index 0000000000..e56e395754 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/web/FaultyRestController.java @@ -0,0 +1,15 @@ +package com.baeldung.errorhandling.boot.web; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class FaultyRestController { + + @GetMapping("/exception") + public ResponseEntity requestWithException() { + throw new NullPointerException("Error in the faulty controller!"); + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java b/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java index 62aae7619d..c945b20aa1 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.web; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-boot-rest/src/main/resources/errorhandling-application.properties b/spring-boot-rest/src/main/resources/errorhandling-application.properties new file mode 100644 index 0000000000..994c517163 --- /dev/null +++ b/spring-boot-rest/src/main/resources/errorhandling-application.properties @@ -0,0 +1,3 @@ + +#server.error.whitelabel.enabled=false +#server.error.include-stacktrace=always \ No newline at end of file diff --git a/spring-boot-rest/src/test/java/com/baeldung/errorhandling/boot/ErrorHandlingLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/errorhandling/boot/ErrorHandlingLiveTest.java new file mode 100644 index 0000000000..e587b67fcf --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/errorhandling/boot/ErrorHandlingLiveTest.java @@ -0,0 +1,65 @@ +package com.baeldung.errorhandling.boot; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isA; +import static org.hamcrest.Matchers.not; + +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.html.HtmlPage; + +public class ErrorHandlingLiveTest { + + private static final String BASE_URL = "http://localhost:8080"; + private static final String EXCEPTION_ENDPOINT = "/exception"; + + private static final String ERROR_RESPONSE_KEY_PATH = "error"; + private static final String XML_RESPONSE_KEY_PATH = "xmlkey"; + private static final String LOCALE_RESPONSE_KEY_PATH = "locale"; + private static final String CAUSE_RESPONSE_KEY_PATH = "cause"; + private static final String RESPONSE_XML_ROOT = "Map"; + private static final String XML_RESPONSE_KEY_XML_PATH = RESPONSE_XML_ROOT + "." + XML_RESPONSE_KEY_PATH; + private static final String LOCALE_RESPONSE_KEY_XML_PATH = RESPONSE_XML_ROOT + "." + LOCALE_RESPONSE_KEY_PATH; + private static final String CAUSE_RESPONSE_KEY_XML_PATH = RESPONSE_XML_ROOT + "." + CAUSE_RESPONSE_KEY_PATH; + private static final String CAUSE_RESPONSE_VALUE = "Error in the faulty controller!"; + private static final String XML_RESPONSE_VALUE = "the XML response is different!"; + + @Test + public void whenRequestingFaultyEndpointAsJson_thenReceiveDefaultResponseWithConfiguredAttrs() { + given().header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE) + .get(EXCEPTION_ENDPOINT) + .then() + .body("$", hasKey(LOCALE_RESPONSE_KEY_PATH)) + .body(CAUSE_RESPONSE_KEY_PATH, is(CAUSE_RESPONSE_VALUE)) + .body("$", not(hasKey(ERROR_RESPONSE_KEY_PATH))) + .body("$", not(hasKey(XML_RESPONSE_KEY_PATH))); + } + + @Test + public void whenRequestingFaultyEndpointAsXml_thenReceiveXmlResponseWithConfiguredAttrs() { + given().header(HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_VALUE) + .get(EXCEPTION_ENDPOINT) + .then() + .body(LOCALE_RESPONSE_KEY_XML_PATH, isA(String.class)) + .body(CAUSE_RESPONSE_KEY_XML_PATH, is(CAUSE_RESPONSE_VALUE)) + .body(RESPONSE_XML_ROOT, not(hasKey(ERROR_RESPONSE_KEY_PATH))) + .body(XML_RESPONSE_KEY_XML_PATH, is(XML_RESPONSE_VALUE)); + } + + @Test + public void whenRequestingFaultyEndpointAsHtml_thenReceiveWhitelabelPageResponse() throws Exception { + try (WebClient webClient = new WebClient()) { + webClient.getOptions() + .setThrowExceptionOnFailingStatusCode(false); + HtmlPage page = webClient.getPage(BASE_URL + EXCEPTION_ENDPOINT); + assertThat(page.getBody() + .asText()).contains("Whitelabel Error Page"); + } + } +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java index 0c1fdf372b..1e49df2909 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.boot.rest; +package com.baeldung.web; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md index d429e17671..3a8d0a727a 100644 --- a/spring-rest-full/README.md +++ b/spring-rest-full/README.md @@ -18,7 +18,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics) - [Bootstrap a Web Application with Spring 4](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) - [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration) -- [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring) - [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic) From 85eab12c0356015c763a97ba9f3deb5bf1b53d42 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 17 Jan 2019 23:22:05 +0200 Subject: [PATCH 092/190] Update and rename LeaveRequestStateTest.java to LeaveRequestStateUnitTest.java --- ...eaveRequestStateTest.java => LeaveRequestStateUnitTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/{LeaveRequestStateTest.java => LeaveRequestStateUnitTest.java} (96%) diff --git a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java b/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateUnitTest.java similarity index 96% rename from algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java rename to algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateUnitTest.java index b209dcb2fb..796998907d 100644 --- a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java +++ b/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateUnitTest.java @@ -4,7 +4,7 @@ import static org.junit.Assert.assertEquals; import org.junit.Test; -public class LeaveRequestStateTest { +public class LeaveRequestStateUnitTest { @Test public void givenLeaveRequest_whenStateEscalated_thenResponsibleIsTeamLeader() { From 735b0a10b28a9868baeab71807e6ff5ab7e57119 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 17 Jan 2019 23:25:26 +0200 Subject: [PATCH 093/190] Update StreamFilterUnitTest.java --- .../java/com/baeldung/stream/filter/StreamFilterUnitTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java b/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java index 29190f7298..5ad875f61e 100644 --- a/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java +++ b/java-streams/src/test/java/com/baeldung/stream/filter/StreamFilterUnitTest.java @@ -156,4 +156,5 @@ public class StreamFilterUnitTest { }) .collect(Collectors.toList())).isInstanceOf(RuntimeException.class); } + } From 8510b07a5642e261eceb76711c3739e4379d359b Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Thu, 17 Jan 2019 23:27:50 +0200 Subject: [PATCH 094/190] Update FilesClearDataManualTest.java --- .../test/java/com/baeldung/file/FilesClearDataManualTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java b/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java index c00290168c..6abe677acf 100644 --- a/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java +++ b/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java @@ -93,5 +93,4 @@ public class FilesClearDataManualTest { assertEquals(0, StreamUtils.getStringFromInputStream(new FileInputStream(FILE_PATH)).length()); } - } From 98c9d22151efa5f098ee46d09511d436ec1e661f Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Thu, 17 Jan 2019 20:06:22 -0600 Subject: [PATCH 095/190] BAEL-2335 and BAEL-2413 README updates (#6152) * BAEL-2246: add link back to article * BAEL-2174: rename core-java-net module to core-java-networking * BAEL-2174: add link back to article * BAEL-2363 BAEL-2337 BAEL-1996 BAEL-2277 add links back to articles * BAEL-2367: add link back to article * BAEL-2335: add link back to article * BAEL-2413: add link back to article * Update README.MD --- core-java-collections-list/README.md | 1 + persistence-modules/spring-boot-persistence/README.MD | 2 ++ 2 files changed, 3 insertions(+) diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md index a35e714006..d1112047ba 100644 --- a/core-java-collections-list/README.md +++ b/core-java-collections-list/README.md @@ -26,3 +26,4 @@ - [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist) - [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections) - [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection) +- [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) diff --git a/persistence-modules/spring-boot-persistence/README.MD b/persistence-modules/spring-boot-persistence/README.MD index 8988fb4ebd..cab6be1ec8 100644 --- a/persistence-modules/spring-boot-persistence/README.MD +++ b/persistence-modules/spring-boot-persistence/README.MD @@ -5,3 +5,5 @@ - [Quick Guide on data.sql and schema.sql Files in Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql) - [Configuring a Tomcat Connection Pool in Spring Boot](https://www.baeldung.com/spring-boot-tomcat-connection-pool) - [Hibernate Field Naming with Spring Boot](https://www.baeldung.com/hibernate-field-naming-spring-boot) +- [Integrating Spring Boot with HSQLDB](https://www.baeldung.com/spring-boot-hsqldb) + From af9a60bddfa284ceecc9a9396f5350be084186d3 Mon Sep 17 00:00:00 2001 From: Maiklins Date: Fri, 18 Jan 2019 04:31:13 +0100 Subject: [PATCH 096/190] BAEL-2217 forEach within forEach (#6166) --- .../kotlin/com/baeldung/forEach/forEach.kt | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt b/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt new file mode 100644 index 0000000000..ef56009c71 --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt @@ -0,0 +1,61 @@ +package com.baeldung.forEach + + +class Country(val name : String, val cities : List) + +class City(val name : String, val streets : List) + +class World { + + private val streetsOfAmsterdam = listOf("Herengracht", "Prinsengracht") + private val streetsOfBerlin = listOf("Unter den Linden","Tiergarten") + private val streetsOfMaastricht = listOf("Grote Gracht", "Vrijthof") + private val countries = listOf( + Country("Netherlands", listOf(City("Maastricht", streetsOfMaastricht), + City("Amsterdam", streetsOfAmsterdam))), + Country("Germany", listOf(City("Berlin", streetsOfBerlin)))) + + fun allCountriesIt() { + countries.forEach { println(it.name) } + } + + fun allCountriesItExplicit() { + countries.forEach { it -> println(it.name) } + } + + //here we cannot refer to 'it' anymore inside the forEach + fun allCountriesExplicit() { + countries.forEach { c -> println(c.name) } + } + + fun allNested() { + countries.forEach { + println(it.name) + it.cities.forEach { + println(" ${it.name}") + it.streets.forEach { println(" $it") } + } + } + } + + fun allTable() { + countries.forEach { c -> + c.cities.forEach { p -> + p.streets.forEach { println("${c.name} ${p.name} $it") } + } + } + } +} + +fun main(args : Array) { + + val world = World() + + world.allCountriesExplicit() + + world.allNested() + + world.allTable() +} + + From d83101854c35218ea54bbaa5f6ce6747d16d44bf Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Fri, 18 Jan 2019 11:05:26 +0400 Subject: [PATCH 097/190] primitive collections libraries added --- core-java-arrays/pom.xml | 16 ++++ .../baeldung/array/PrimitiveCollections.java | 34 ++++++++ .../array/PrimitivesListPerformance.java | 77 +++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java create mode 100644 core-java-arrays/src/main/java/com/baeldung/array/PrimitivesListPerformance.java diff --git a/core-java-arrays/pom.xml b/core-java-arrays/pom.xml index d2d0453e87..6d4109804e 100644 --- a/core-java-arrays/pom.xml +++ b/core-java-arrays/pom.xml @@ -52,6 +52,22 @@ spring-web ${springframework.spring-web.version} + + + net.sf.trove4j + trove4j + 3.0.2 + + + it.unimi.dsi + fastutil + 8.1.0 + + + colt + colt + 1.2.0 + diff --git a/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java b/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java new file mode 100644 index 0000000000..115c5fe5c3 --- /dev/null +++ b/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java @@ -0,0 +1,34 @@ +package com.baeldung.array; + +import com.google.common.primitives.ImmutableIntArray; +import com.google.common.primitives.Ints; +import gnu.trove.list.array.TIntArrayList; + +import java.util.Arrays; +import java.util.List; + +public class PrimitiveCollections { + + public static void main(String[] args) { + + int[] primitives = new int[] {5, 10, 0, 2}; + + guavaPrimitives(primitives); + + trovePrimitives(primitives); + } + + private static void trovePrimitives(int[] primitives) { + TIntArrayList list = new TIntArrayList(primitives); + } + + private static void guavaPrimitives(int[] primitives) { + + ImmutableIntArray list = ImmutableIntArray.builder().addAll(primitives).build(); + + List integers = Ints.asList(primitives); + + int[] primitive = Ints.toArray(Arrays.asList(1, 2, 3, 4, 5)); + System.out.println(Arrays.toString(primitive)); + } +} diff --git a/core-java-arrays/src/main/java/com/baeldung/array/PrimitivesListPerformance.java b/core-java-arrays/src/main/java/com/baeldung/array/PrimitivesListPerformance.java new file mode 100644 index 0000000000..9db3a75574 --- /dev/null +++ b/core-java-arrays/src/main/java/com/baeldung/array/PrimitivesListPerformance.java @@ -0,0 +1,77 @@ +package com.baeldung.array; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import gnu.trove.list.array.TIntArrayList; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Warmup(iterations = 10) +public class PrimitivesListPerformance { + + @State(Scope.Thread) + public static class Initialize { + + List arrayList = new ArrayList<>(); + TIntArrayList tList = new TIntArrayList(); + cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList(); + IntArrayList fastUtilList = new IntArrayList(); + + int getValue = 10; + + final int iterations = 100000; + + @Setup(Level.Trial) + public void setUp() { + + for (int i = 0; i < iterations; i++) { + arrayList.add(i); + tList.add(i); + coltList.add(i); + fastUtilList.add(i); + } + + arrayList.add(getValue); + tList.add(getValue); + coltList.add(getValue); + fastUtilList.add(getValue); + } + } + + @Benchmark + public boolean containsArrayList(PrimitivesListPerformance.Initialize state) { + return state.arrayList.contains(state.getValue); + } + + @Benchmark + public boolean containsTIntList(PrimitivesListPerformance.Initialize state) { + return state.tList.contains(state.getValue); + } + + @Benchmark + public boolean containsColtIntList(PrimitivesListPerformance.Initialize state) { + return state.coltList.contains(state.getValue); + } + + @Benchmark + public boolean containsFastUtilIntList(PrimitivesListPerformance.Initialize state) { + return state.fastUtilList.contains(state.getValue); + } + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder() + .include(PrimitivesListPerformance.class.getSimpleName()).threads(1) + .forks(1).shouldFailOnError(true) + .shouldDoGC(true) + .jvmArgs("-server").build(); + new Runner(options).run(); + } +} From 97273bab7e5d1d615b5c9d3aae044ca2e7043510 Mon Sep 17 00:00:00 2001 From: PRIFTI Date: Fri, 18 Jan 2019 13:17:52 +0100 Subject: [PATCH 098/190] BAEL-2441: Removed the responsible variable. --- .../enumstatemachine/LeaveRequestStateTest.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java b/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java index b209dcb2fb..c246c16912 100644 --- a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java +++ b/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateTest.java @@ -10,9 +10,7 @@ public class LeaveRequestStateTest { public void givenLeaveRequest_whenStateEscalated_thenResponsibleIsTeamLeader() { LeaveRequestState state = LeaveRequestState.Escalated; - String responsible = state.responsiblePerson(); - - assertEquals(responsible, "Team Leader"); + assertEquals(state.responsiblePerson(), "Team Leader"); } @@ -20,9 +18,7 @@ public class LeaveRequestStateTest { public void givenLeaveRequest_whenStateApproved_thenResponsibleIsDepartmentManager() { LeaveRequestState state = LeaveRequestState.Approved; - String responsible = state.responsiblePerson(); - - assertEquals(responsible, "Department Manager"); + assertEquals(state.responsiblePerson(), "Department Manager"); } @Test From eb7cde988bceac9c5eb6f160d6dd186cdd254705 Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Sat, 19 Jan 2019 05:38:13 +0330 Subject: [PATCH 099/190] JUnit 5 parameterized tests Issue: BAEL-1665 --- testing-modules/junit-5/pom.xml | 5 + .../BlankStringsArgumentsProvider.java | 19 +++ .../baeldung/parameterized/EnumsUnitTest.java | 50 ++++++++ .../parameterized/LocalDateUnitTest.java | 18 +++ .../com/baeldung/parameterized/Numbers.java | 8 ++ .../parameterized/NumbersUnitTest.java | 15 +++ .../com/baeldung/parameterized/Person.java | 20 ++++ .../parameterized/PersonAggregator.java | 15 +++ .../parameterized/PersonUnitTest.java | 31 +++++ .../parameterized/SlashyDateConverter.java | 27 +++++ .../baeldung/parameterized/StringParams.java | 10 ++ .../com/baeldung/parameterized/Strings.java | 8 ++ .../parameterized/StringsUnitTest.java | 108 ++++++++++++++++++ .../VariableArgumentsProvider.java | 45 ++++++++ .../parameterized/VariableSource.java | 19 +++ .../junit-5/src/test/resources/data.csv | 4 + 16 files changed, 402 insertions(+) create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java create mode 100644 testing-modules/junit-5/src/test/resources/data.csv diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml index b7600267d9..a5a1ddaf0b 100644 --- a/testing-modules/junit-5/pom.xml +++ b/testing-modules/junit-5/pom.xml @@ -21,6 +21,11 @@ junit-platform-engine ${junit.platform.version} + + org.junit.jupiter + junit-jupiter-params + ${junit.jupiter.version} + org.junit.platform junit-platform-runner diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java new file mode 100644 index 0000000000..1d2c76d37b --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/BlankStringsArgumentsProvider.java @@ -0,0 +1,19 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; + +import java.util.stream.Stream; + +class BlankStringsArgumentsProvider implements ArgumentsProvider { + + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.of( + Arguments.of((String) null), + Arguments.of(""), + Arguments.of(" ") + ); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java new file mode 100644 index 0000000000..0b2068dbf1 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/EnumsUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.EnumSource; + +import java.time.Month; +import java.util.EnumSet; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class EnumsUnitTest { + + @ParameterizedTest + @EnumSource(Month.class) + void getValueForAMonth_IsAlwaysBetweenOneAndTwelve(Month month) { + int monthNumber = month.getValue(); + assertTrue(monthNumber >= 1 && monthNumber <= 12); + } + + @ParameterizedTest(name = "{index} {0} is 30 days long") + @EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"}) + void someMonths_Are30DaysLong(Month month) { + final boolean isALeapYear = false; + assertEquals(30, month.length(isALeapYear)); + } + + @ParameterizedTest + @EnumSource(value = Month.class, names = {"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER", "FEBRUARY"}, mode = EnumSource.Mode.EXCLUDE) + void exceptFourMonths_OthersAre31DaysLong(Month month) { + final boolean isALeapYear = false; + assertEquals(31, month.length(isALeapYear)); + } + + @ParameterizedTest + @EnumSource(value = Month.class, names = ".+BER", mode = EnumSource.Mode.MATCH_ANY) + void fourMonths_AreEndingWithBer(Month month) { + EnumSet months = EnumSet.of(Month.SEPTEMBER, Month.OCTOBER, Month.NOVEMBER, Month.DECEMBER); + assertTrue(months.contains(month)); + } + + @ParameterizedTest + @CsvSource({"APRIL", "JUNE", "SEPTEMBER", "NOVEMBER"}) + void someMonths_Are30DaysLongCsv(Month month) { + final boolean isALeapYear = false; + assertEquals(30, month.length(isALeapYear)); + } + +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java new file mode 100644 index 0000000000..95487705f5 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/LocalDateUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.provider.CsvSource; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class LocalDateUnitTest { + + @ParameterizedTest + @CsvSource({"2018/12/25,2018", "2019/02/11,2019"}) + void getYear_ShouldWorkAsExpected(@ConvertWith(SlashyDateConverter.class) LocalDate date, int expected) { + assertEquals(expected, date.getYear()); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java new file mode 100644 index 0000000000..8a9b229aac --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Numbers.java @@ -0,0 +1,8 @@ +package com.baeldung.parameterized; + +public class Numbers { + + public static boolean isOdd(int number) { + return number % 2 != 0; + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java new file mode 100644 index 0000000000..b3a3371bb2 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/NumbersUnitTest.java @@ -0,0 +1,15 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class NumbersUnitTest { + + @ParameterizedTest + @ValueSource(ints = {1, 3, 5, -3, 15, Integer.MAX_VALUE}) + void isOdd_ShouldReturnTrueForOddNumbers(int number) { + assertTrue(Numbers.isOdd(number)); + } +} \ No newline at end of file diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java new file mode 100644 index 0000000000..225f11ba29 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Person.java @@ -0,0 +1,20 @@ +package com.baeldung.parameterized; + +class Person { + + private final String firstName; + private final String middleName; + private final String lastName; + + public Person(String firstName, String middleName, String lastName) { + this.firstName = firstName; + this.middleName = middleName; + this.lastName = lastName; + } + + public String fullName() { + if (middleName == null || middleName.trim().isEmpty()) return String.format("%s %s", firstName, lastName); + + return String.format("%s %s %s", firstName, middleName, lastName); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java new file mode 100644 index 0000000000..df2ddc9e66 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonAggregator.java @@ -0,0 +1,15 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.aggregator.ArgumentsAccessor; +import org.junit.jupiter.params.aggregator.ArgumentsAggregationException; +import org.junit.jupiter.params.aggregator.ArgumentsAggregator; + +class PersonAggregator implements ArgumentsAggregator { + + @Override + public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) + throws ArgumentsAggregationException { + return new Person(accessor.getString(1), accessor.getString(2), accessor.getString(3)); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java new file mode 100644 index 0000000000..b30ecc748e --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/PersonUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.aggregator.AggregateWith; +import org.junit.jupiter.params.aggregator.ArgumentsAccessor; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PersonUnitTest { + + @ParameterizedTest + @CsvSource({"Isaac,,Newton, Isaac Newton", "Charles,Robert,Darwin,Charles Robert Darwin"}) + void fullName_ShouldGenerateTheExpectedFullName(ArgumentsAccessor argumentsAccessor) { + String firstName = argumentsAccessor.getString(0); + String middleName = (String) argumentsAccessor.get(1); + String lastName = argumentsAccessor.get(2, String.class); + String expectedFullName = argumentsAccessor.getString(3); + + Person person = new Person(firstName, middleName, lastName); + assertEquals(expectedFullName, person.fullName()); + } + + @ParameterizedTest + @CsvSource({"Isaac Newton,Isaac,,Newton", "Charles Robert Darwin,Charles,Robert,Darwin"}) + void fullName_ShouldGenerateTheExpectedFullName(String expectedFullName, + @AggregateWith(PersonAggregator.class) Person person) { + + assertEquals(expectedFullName, person.fullName()); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java new file mode 100644 index 0000000000..40773d29a9 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/SlashyDateConverter.java @@ -0,0 +1,27 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.converter.ArgumentConversionException; +import org.junit.jupiter.params.converter.ArgumentConverter; + +import java.time.LocalDate; + +class SlashyDateConverter implements ArgumentConverter { + + @Override + public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + if (!(source instanceof String)) + throw new IllegalArgumentException("The argument should be a string: " + source); + + try { + String[] parts = ((String) source).split("/"); + int year = Integer.parseInt(parts[0]); + int month = Integer.parseInt(parts[1]); + int day = Integer.parseInt(parts[2]); + + return LocalDate.of(year, month, day); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to convert", e); + } + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java new file mode 100644 index 0000000000..bc9f881bd4 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringParams.java @@ -0,0 +1,10 @@ +package com.baeldung.parameterized; + +import java.util.stream.Stream; + +public class StringParams { + + static Stream blankStrings() { + return Stream.of(null, "", " "); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java new file mode 100644 index 0000000000..f8e29f6b7f --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/Strings.java @@ -0,0 +1,8 @@ +package com.baeldung.parameterized; + +class Strings { + + static boolean isBlank(String input) { + return input == null || input.trim().isEmpty(); + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java new file mode 100644 index 0000000000..7d02a5a74b --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/StringsUnitTest.java @@ -0,0 +1,108 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.*; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class StringsUnitTest { + + static Stream arguments = Stream.of( + Arguments.of(null, true), // null strings should be considered blank + Arguments.of("", true), + Arguments.of(" ", true), + Arguments.of("not blank", false) + ); + + @ParameterizedTest + @VariableSource("arguments") + void isBlank_ShouldReturnTrueForNullOrBlankStringsVariableSource(String input, boolean expected) { + assertEquals(expected, Strings.isBlank(input)); + } + + @ParameterizedTest + @ValueSource(strings = {"", " "}) + void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input) { + assertTrue(Strings.isBlank(input)); + } + + @ParameterizedTest + @MethodSource("provideStringsForIsBlank") + void isBlank_ShouldReturnTrueForNullOrBlankStrings(String input, boolean expected) { + assertEquals(expected, Strings.isBlank(input)); + } + + @ParameterizedTest + @MethodSource // Please note method name is not provided + void isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument(String input) { + assertTrue(Strings.isBlank(input)); + } + + @ParameterizedTest + @MethodSource("com.baeldung.parameterized.StringParams#blankStrings") + void isBlank_ShouldReturnTrueForNullOrBlankStringsExternalSource(String input) { + assertTrue(Strings.isBlank(input)); + } + + @ParameterizedTest + @ArgumentsSource(BlankStringsArgumentsProvider.class) + void isBlank_ShouldReturnTrueForNullOrBlankStringsArgProvider(String input) { + assertTrue(Strings.isBlank(input)); + } + + private static Stream isBlank_ShouldReturnTrueForNullOrBlankStringsOneArgument() { + return Stream.of(null, "", " "); + } + + @ParameterizedTest + @MethodSource("provideStringsForIsBlankList") + void isBlank_ShouldReturnTrueForNullOrBlankStringsList(String input, boolean expected) { + assertEquals(expected, Strings.isBlank(input)); + } + + @ParameterizedTest + @CsvSource({"test,TEST", "tEst,TEST", "Java,JAVA"}) // Passing a CSV pair per test execution + void toUpperCase_ShouldGenerateTheExpectedUppercaseValue(String input, String expected) { + String actualValue = input.toUpperCase(); + assertEquals(expected, actualValue); + } + + @ParameterizedTest + @CsvSource(value = {"test:test", "tEst:test", "Java:java"}, delimiter =':') // Using : as the column separator. + void toLowerCase_ShouldGenerateTheExpectedLowercaseValue(String input, String expected) { + String actualValue = input.toLowerCase(); + assertEquals(expected, actualValue); + } + + @ParameterizedTest + @CsvFileSource(resources = "/data.csv", numLinesToSkip = 1) + void toUpperCase_ShouldGenerateTheExpectedUppercaseValueCSVFile(String input, String expected) { + String actualValue = input.toUpperCase(); + assertEquals(expected, actualValue); + } + + + + private static Stream provideStringsForIsBlank() { + return Stream.of( + Arguments.of(null, true), // null strings should be considered blank + Arguments.of("", true), + Arguments.of(" ", true), + Arguments.of("not blank", false) + ); + } + + private static List provideStringsForIsBlankList() { + return Arrays.asList( + Arguments.of(null, true), // null strings should be considered blank + Arguments.of("", true), + Arguments.of(" ", true), + Arguments.of("not blank", false) + ); + } +} \ No newline at end of file diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java new file mode 100644 index 0000000000..a96d01e854 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableArgumentsProvider.java @@ -0,0 +1,45 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.support.AnnotationConsumer; + +import java.lang.reflect.Field; +import java.util.stream.Stream; + +class VariableArgumentsProvider implements ArgumentsProvider, AnnotationConsumer { + + private String variableName; + + @Override + public Stream provideArguments(ExtensionContext context) { + return context.getTestClass() + .map(this::getField) + .map(this::getValue) + .orElseThrow(() -> new IllegalArgumentException("Failed to load test arguments")); + } + + @Override + public void accept(VariableSource variableSource) { + variableName = variableSource.value(); + } + + private Field getField(Class clazz) { + try { + return clazz.getDeclaredField(variableName); + } catch (Exception e) { + return null; + } + } + + @SuppressWarnings("unchecked") + private Stream getValue(Field field) { + Object value = null; + try { + value = field.get(null); + } catch (Exception ignored) {} + + return value == null ? null : (Stream) value; + } +} diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java new file mode 100644 index 0000000000..9c1d07c1be --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/parameterized/VariableSource.java @@ -0,0 +1,19 @@ +package com.baeldung.parameterized; + +import org.junit.jupiter.params.provider.ArgumentsSource; + +import java.lang.annotation.*; + +@Documented +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@ArgumentsSource(VariableArgumentsProvider.class) +public @interface VariableSource { + + /** + * Represents the name of the static variable to load the test arguments from. + * + * @return Static variable name. + */ + String value(); +} diff --git a/testing-modules/junit-5/src/test/resources/data.csv b/testing-modules/junit-5/src/test/resources/data.csv new file mode 100644 index 0000000000..321554cc23 --- /dev/null +++ b/testing-modules/junit-5/src/test/resources/data.csv @@ -0,0 +1,4 @@ +input,expected +test,TEST +tEst,TEST +Java,JAVA \ No newline at end of file From 8a307c1aba5b8d186f893e68273733ce67cbd882 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Sat, 19 Jan 2019 09:32:54 -0200 Subject: [PATCH 100/190] moved new package to existing one --- .../boot/ErrorHandlingBootApplication.java | 15 --------------- .../config}/MyCustomErrorAttributes.java | 2 +- .../config}/MyErrorController.java | 2 +- .../controller}/FaultyRestController.java | 4 ++-- .../src/main/resources/application.properties | 3 +++ .../errorhandling-application.properties | 3 --- .../boot => web/error}/ErrorHandlingLiveTest.java | 2 +- 7 files changed, 8 insertions(+), 23 deletions(-) delete mode 100644 spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/ErrorHandlingBootApplication.java rename spring-boot-rest/src/main/java/com/baeldung/{errorhandling/boot/configurations => web/config}/MyCustomErrorAttributes.java (93%) rename spring-boot-rest/src/main/java/com/baeldung/{errorhandling/boot/configurations => web/config}/MyErrorController.java (95%) rename spring-boot-rest/src/main/java/com/baeldung/{errorhandling/boot/web => web/controller}/FaultyRestController.java (73%) delete mode 100644 spring-boot-rest/src/main/resources/errorhandling-application.properties rename spring-boot-rest/src/test/java/com/baeldung/{errorhandling/boot => web/error}/ErrorHandlingLiveTest.java (98%) diff --git a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/ErrorHandlingBootApplication.java b/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/ErrorHandlingBootApplication.java deleted file mode 100644 index 0885ecbbf7..0000000000 --- a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/ErrorHandlingBootApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.errorhandling.boot; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.PropertySource; - -@SpringBootApplication -@PropertySource("errorhandling-application.properties") -public class ErrorHandlingBootApplication { - - public static void main(String[] args) { - SpringApplication.run(ErrorHandlingBootApplication.class, args); - } - -} diff --git a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyCustomErrorAttributes.java b/spring-boot-rest/src/main/java/com/baeldung/web/config/MyCustomErrorAttributes.java similarity index 93% rename from spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyCustomErrorAttributes.java rename to spring-boot-rest/src/main/java/com/baeldung/web/config/MyCustomErrorAttributes.java index e2c62cb907..1948d5552f 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyCustomErrorAttributes.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/config/MyCustomErrorAttributes.java @@ -1,4 +1,4 @@ -package com.baeldung.errorhandling.boot.configurations; +package com.baeldung.web.config; import java.util.Map; diff --git a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyErrorController.java b/spring-boot-rest/src/main/java/com/baeldung/web/config/MyErrorController.java similarity index 95% rename from spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyErrorController.java rename to spring-boot-rest/src/main/java/com/baeldung/web/config/MyErrorController.java index 427a0b43d7..e3716ec113 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/configurations/MyErrorController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/config/MyErrorController.java @@ -1,4 +1,4 @@ -package com.baeldung.errorhandling.boot.configurations; +package com.baeldung.web.config; import java.util.Map; diff --git a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/web/FaultyRestController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FaultyRestController.java similarity index 73% rename from spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/web/FaultyRestController.java rename to spring-boot-rest/src/main/java/com/baeldung/web/controller/FaultyRestController.java index e56e395754..bf7b7a5f99 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/errorhandling/boot/web/FaultyRestController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FaultyRestController.java @@ -1,4 +1,4 @@ -package com.baeldung.errorhandling.boot.web; +package com.baeldung.web.controller; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -9,7 +9,7 @@ public class FaultyRestController { @GetMapping("/exception") public ResponseEntity requestWithException() { - throw new NullPointerException("Error in the faulty controller!"); + throw new RuntimeException("Error in the faulty controller!"); } } diff --git a/spring-boot-rest/src/main/resources/application.properties b/spring-boot-rest/src/main/resources/application.properties index e69de29bb2..e65440e2b9 100644 --- a/spring-boot-rest/src/main/resources/application.properties +++ b/spring-boot-rest/src/main/resources/application.properties @@ -0,0 +1,3 @@ +### Spring Boot default error handling configurations +#server.error.whitelabel.enabled=false +#server.error.include-stacktrace=always \ No newline at end of file diff --git a/spring-boot-rest/src/main/resources/errorhandling-application.properties b/spring-boot-rest/src/main/resources/errorhandling-application.properties deleted file mode 100644 index 994c517163..0000000000 --- a/spring-boot-rest/src/main/resources/errorhandling-application.properties +++ /dev/null @@ -1,3 +0,0 @@ - -#server.error.whitelabel.enabled=false -#server.error.include-stacktrace=always \ No newline at end of file diff --git a/spring-boot-rest/src/test/java/com/baeldung/errorhandling/boot/ErrorHandlingLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/error/ErrorHandlingLiveTest.java similarity index 98% rename from spring-boot-rest/src/test/java/com/baeldung/errorhandling/boot/ErrorHandlingLiveTest.java rename to spring-boot-rest/src/test/java/com/baeldung/web/error/ErrorHandlingLiveTest.java index e587b67fcf..ea1b6ab227 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/errorhandling/boot/ErrorHandlingLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/error/ErrorHandlingLiveTest.java @@ -1,4 +1,4 @@ -package com.baeldung.errorhandling.boot; +package com.baeldung.web.error; import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; From dea88da77728edb77c12475ca551045ac2960503 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Sat, 19 Jan 2019 17:00:30 -0200 Subject: [PATCH 101/190] Adding dao dependencies and exception handling of original classes --- spring-boot-rest/pom.xml | 8 ++++ .../RestResponseEntityExceptionHandler.java | 41 +++++++++---------- .../web/exception/MyDataAccessException.java | 21 ---------- .../MyDataIntegrityViolationException.java | 21 ---------- 4 files changed, 28 insertions(+), 63 deletions(-) delete mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataAccessException.java delete mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataIntegrityViolationException.java diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index 3b8cf7e39e..f05d242072 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -24,6 +24,14 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml + + org.hibernate + hibernate-entitymanager + + + org.springframework + spring-jdbc + org.springframework.boot diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java index fe0465156d..2e2672f510 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java @@ -1,5 +1,11 @@ package com.baeldung.web.error; +import javax.persistence.EntityNotFoundException; + +import org.hibernate.exception.ConstraintViolationException; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -10,8 +16,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; -import com.baeldung.web.exception.MyDataAccessException; -import com.baeldung.web.exception.MyDataIntegrityViolationException; import com.baeldung.web.exception.MyResourceNotFoundException; @ControllerAdvice @@ -24,13 +28,15 @@ public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionH // API // 400 - /* - * Some examples of exceptions that we could retrieve as 400 (BAD_REQUEST) responses: - * Hibernate's ConstraintViolationException - * Spring's DataIntegrityViolationException - */ - @ExceptionHandler({ MyDataIntegrityViolationException.class }) - public ResponseEntity handleBadRequest(final MyDataIntegrityViolationException ex, final WebRequest request) { + + @ExceptionHandler({ ConstraintViolationException.class }) + public ResponseEntity handleBadRequest(final ConstraintViolationException ex, final WebRequest request) { + final String bodyOfResponse = "This should be application specific"; + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); + } + + @ExceptionHandler({ DataIntegrityViolationException.class }) + public ResponseEntity handleBadRequest(final DataIntegrityViolationException ex, final WebRequest request) { final String bodyOfResponse = "This should be application specific"; return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); } @@ -50,23 +56,16 @@ public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionH // 404 - /* - * Some examples of exceptions that we could retrieve as 404 (NOT_FOUND) responses: - * Java Persistence's EntityNotFoundException - */ - @ExceptionHandler(value = { MyResourceNotFoundException.class }) + + @ExceptionHandler(value = { EntityNotFoundException.class, MyResourceNotFoundException.class }) protected ResponseEntity handleNotFound(final RuntimeException ex, final WebRequest request) { final String bodyOfResponse = "This should be application specific"; return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request); } // 409 - /* - * Some examples of exceptions that we could retrieve as 409 (CONFLICT) responses: - * Spring's InvalidDataAccessApiUsageException - * Spring's DataAccessException - */ - @ExceptionHandler({ MyDataAccessException.class}) + + @ExceptionHandler({ InvalidDataAccessApiUsageException.class, DataAccessException.class }) protected ResponseEntity handleConflict(final RuntimeException ex, final WebRequest request) { final String bodyOfResponse = "This should be application specific"; return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request); @@ -83,4 +82,4 @@ public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionH return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request); } -} +} \ No newline at end of file diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataAccessException.java b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataAccessException.java deleted file mode 100644 index 8fc9a3a0ea..0000000000 --- a/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataAccessException.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.web.exception; - -public final class MyDataAccessException extends RuntimeException { - - public MyDataAccessException() { - super(); - } - - public MyDataAccessException(final String message, final Throwable cause) { - super(message, cause); - } - - public MyDataAccessException(final String message) { - super(message); - } - - public MyDataAccessException(final Throwable cause) { - super(cause); - } - -} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataIntegrityViolationException.java b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataIntegrityViolationException.java deleted file mode 100644 index 50adb09c09..0000000000 --- a/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyDataIntegrityViolationException.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.web.exception; - -public final class MyDataIntegrityViolationException extends RuntimeException { - - public MyDataIntegrityViolationException() { - super(); - } - - public MyDataIntegrityViolationException(final String message, final Throwable cause) { - super(message, cause); - } - - public MyDataIntegrityViolationException(final String message) { - super(message); - } - - public MyDataIntegrityViolationException(final Throwable cause) { - super(cause); - } - -} From e03c0871ae561caf0a9b25695cf971c2bab0a921 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Sat, 19 Jan 2019 23:14:25 +0100 Subject: [PATCH 102/190] [REORG-2531] Updated a test to illustrate use of File.separator --- .../java/com/baeldung/directories/NewDirectoryUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java b/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java index e0111c2702..d645782955 100644 --- a/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java +++ b/core-java-io/src/test/java/com/baeldung/directories/NewDirectoryUnitTest.java @@ -62,7 +62,7 @@ public class NewDirectoryUnitTest { @Test public void givenUnexistingNestedDirectories_whenMkdirs_thenTrue() { - File newDirectory = new File(TEMP_DIRECTORY, "new_directory"); + File newDirectory = new File(System.getProperty("java.io.tmpdir") + File.separator + "new_directory"); File nestedDirectory = new File(newDirectory, "nested_directory"); assertFalse(newDirectory.exists()); assertFalse(nestedDirectory.exists()); From 5408ed78fe23ace31fbb09317721ba5fa04746d2 Mon Sep 17 00:00:00 2001 From: Eric Martin Date: Sat, 19 Jan 2019 18:15:26 -0600 Subject: [PATCH 103/190] Delete . .. --- java-streams/src/test/java/com/baeldung/stream/sum/. .. | 1 - 1 file changed, 1 deletion(-) delete mode 100644 java-streams/src/test/java/com/baeldung/stream/sum/. .. diff --git a/java-streams/src/test/java/com/baeldung/stream/sum/. .. b/java-streams/src/test/java/com/baeldung/stream/sum/. .. deleted file mode 100644 index 8b13789179..0000000000 --- a/java-streams/src/test/java/com/baeldung/stream/sum/. .. +++ /dev/null @@ -1 +0,0 @@ - From c19558f42077593bf03445b8b4294603f1dc335b Mon Sep 17 00:00:00 2001 From: eric-martin Date: Sat, 19 Jan 2019 18:38:13 -0600 Subject: [PATCH 104/190] BAEL-2521: Moving LocalDateConverter to java-jpa --- .../src/main/java/com/baeldung/util/LocalDateConverter.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename persistence-modules/{spring-boot-persistence => java-jpa}/src/main/java/com/baeldung/util/LocalDateConverter.java (100%) diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/util/LocalDateConverter.java similarity index 100% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java rename to persistence-modules/java-jpa/src/main/java/com/baeldung/util/LocalDateConverter.java From e2d10d45dbd5000879eb3598cd2a3ddd261480b7 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 20 Jan 2019 17:21:45 +0200 Subject: [PATCH 105/190] Update pom.xml --- lombok/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lombok/pom.xml b/lombok/pom.xml index 7ad2e3dc83..72bff8828a 100644 --- a/lombok/pom.xml +++ b/lombok/pom.xml @@ -80,7 +80,7 @@ 1.0.0.Final - 1.16.10.0 + 1.18.4.0 3.8.0 From c22af13c21fd2ce158e0177e82c7fd0dacc5ae1c Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 20 Jan 2019 17:26:27 +0200 Subject: [PATCH 106/190] Update pom.xml --- lombok/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lombok/pom.xml b/lombok/pom.xml index 72bff8828a..2acf9e240d 100644 --- a/lombok/pom.xml +++ b/lombok/pom.xml @@ -76,7 +76,7 @@ - 1.16.18 + 1.18.4 1.0.0.Final From c7a8627f1005c462b1bc213ed141612323ec9ca3 Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Sun, 20 Jan 2019 13:52:39 -0300 Subject: [PATCH 107/190] BAEL-2545 - Configuring a DataSource Programatically in Spring Boot (#6139) * Initial Commit * Update UserRepositoryIntegrationTest.java * Update UserRepositoryIntegrationTest --- .../application/Application.java | 27 +++++++++++ .../datasources/DataSourceBean.java | 20 ++++++++ .../application/entities/User.java | 46 +++++++++++++++++++ .../repositories/UserRepository.java | 8 ++++ .../tests/UserRepositoryIntegrationTest.java | 28 +++++++++++ 5 files changed, 129 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/Application.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/datasources/DataSourceBean.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/repositories/UserRepository.java create mode 100644 persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/tests/UserRepositoryIntegrationTest.java diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/Application.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/Application.java new file mode 100644 index 0000000000..e1f67c0185 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/Application.java @@ -0,0 +1,27 @@ +package com.baeldung.springbootdatasourceconfig.application; + +import com.baeldung.springbootdatasourceconfig.application.entities.User; +import com.baeldung.springbootdatasourceconfig.application.repositories.UserRepository; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + public CommandLineRunner run(UserRepository userRepository) throws Exception { + return (String[] args) -> { + User user1 = new User("John", "john@domain.com"); + User user2 = new User("Julie", "julie@domain.com"); + userRepository.save(user1); + userRepository.save(user2); + userRepository.findAll().forEach(user -> System.out.println(user.getName())); + }; + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/datasources/DataSourceBean.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/datasources/DataSourceBean.java new file mode 100644 index 0000000000..9ef9b77aed --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/datasources/DataSourceBean.java @@ -0,0 +1,20 @@ +package com.baeldung.springbootdatasourceconfig.application.datasources; + +import javax.sql.DataSource; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class DataSourceBean { + + @Bean + public DataSource getDataSource() { + DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); + dataSourceBuilder.driverClassName("org.h2.Driver"); + dataSourceBuilder.url("jdbc:h2:mem:test"); + dataSourceBuilder.username("SA"); + dataSourceBuilder.password(""); + return dataSourceBuilder.build(); + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java new file mode 100644 index 0000000000..518a11701f --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/entities/User.java @@ -0,0 +1,46 @@ +package com.baeldung.springbootdatasourceconfig.application.entities; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "users") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + private String name; + private String email; + + public User(){} + + public User(String name, String email) { + this.name = name; + this.email = email; + } + + 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; + } + + @Override + public String toString() { + return "User{" + "id=" + id + ", name=" + name + ", email=" + email + '}'; + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/repositories/UserRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/repositories/UserRepository.java new file mode 100644 index 0000000000..27929ead44 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springbootdatasourceconfig/application/repositories/UserRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.springbootdatasourceconfig.application.repositories; + +import com.baeldung.springbootdatasourceconfig.application.entities.User; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends CrudRepository {} diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/tests/UserRepositoryIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/tests/UserRepositoryIntegrationTest.java new file mode 100644 index 0000000000..f27681021e --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/tests/UserRepositoryIntegrationTest.java @@ -0,0 +1,28 @@ +package com.baeldung.springbootdatasourceconfig.tests; + +import com.baeldung.springbootdatasourceconfig.application.entities.User; +import com.baeldung.springbootdatasourceconfig.application.repositories.UserRepository; +import java.util.List; +import java.util.Optional; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@DataJpaTest +public class UserRepositoryIntegrationTest { + + @Autowired + private UserRepository userRepository; + + @Test + public void whenCalledSave_thenCorrectNumberOfUsers() { + userRepository.save(new User("Bob", "bob@domain.com")); + List users = (List) userRepository.findAll(); + + assertThat(users.size()).isEqualTo(1); + } +} From 0fb2adfe99fdbbb5d313c41c3d04e5cb9478425c Mon Sep 17 00:00:00 2001 From: Philippe M Date: Sun, 20 Jan 2019 19:38:14 +0100 Subject: [PATCH 108/190] Fix performance issues of JMeter Test Plan (#5979) --- .../resources/scripts/JMeter/Test Plan.jmx | 289 +++++++++--------- 1 file changed, 142 insertions(+), 147 deletions(-) diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx b/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx index da32a13a22..97640dfac7 100644 --- a/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx +++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx @@ -1,5 +1,5 @@ - + @@ -25,80 +25,116 @@ - - true - 1 - - - - - - Content-Type - application/json + + + + Content-Type + application/json + + + + + + true + + + + false + {"customerRewardsId":null,"customerId":${random},"transactionDate":null} + = - + + localhost + 8080 + http + + /transactions/add + POST + true + false + true + false + + + + + + + txnId + $.id + 1 + all + foo + - + + txnDate + $.transactionDate + 1 + Never + + + + custId + $.customerId + 1 + all + bob + + + + + + + + localhost + 8080 + + + /rewards/find/${custId} + GET + true + false + true + false + + + + + + + rwdId + $.id + 1 + 0 + all + + + + + ${__jexl3(${rwdId} == 0,)} + true + true + + + true false - {"customerRewardsId":null,"customerId":${random},"transactionDate":null} + {"customerId":${custId}} = localhost 8080 - http - - /transactions/add - POST - true - false - true - false - - - - - - - txnId - $.id - 1 - all - foo - - - - txnDate - $.transactionDate - 1 - Never - - - - custId - $.customerId - 1 - all - bob - - - - - - - - localhost - 8080 - /rewards/find/${custId} - GET + /rewards/add + POST true false true @@ -112,98 +148,57 @@ rwdId $.id 1 - 0 + bar all - - ${rwdId} == 0 - true - - - - true - - - - false - {"customerId":${custId}} - = - - - - localhost - 8080 - - - /rewards/add - POST - true - false - true - false - - - - - - - rwdId - $.id - 1 - bar - all - - - - - - true - - - - false - {"id":${txnId},"customerRewardsId":${rwdId},"customerId":${custId},"transactionDate":"${txnDate}"} - = - - - - localhost - 8080 - - - /transactions/add - POST - true - false - true - false - - - - - - - - - - localhost - 8080 - - - /transactions/findAll/${rwdId} - GET - true - false - true - false - - - - - + + true + + + + false + {"id":${txnId},"customerRewardsId":${rwdId},"customerId":${custId},"transactionDate":"${txnDate}"} + = + + + + localhost + 8080 + + + /transactions/add + POST + true + false + true + false + + + + + + + + + + localhost + 8080 + + + /transactions/findAll/${rwdId} + GET + true + false + true + false + + + + + 10000 1 @@ -213,7 +208,7 @@ random - + false saveConfig From 89ff253342752027c17b8088b8940df972a5d17f Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 20 Jan 2019 21:56:30 +0200 Subject: [PATCH 109/190] Update TaskScheduler.java --- .../java/com/baeldung/scheduling/shedlock/TaskScheduler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java b/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java index b1b1ad921f..060afe660e 100644 --- a/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java +++ b/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/TaskScheduler.java @@ -7,9 +7,9 @@ import org.springframework.stereotype.Component; @Component class TaskScheduler { - @Scheduled(cron = "*/15 * * * * *") + @Scheduled(cron = "*/15 * * * *") @SchedulerLock(name = "TaskScheduler_scheduledTask", lockAtLeastForString = "PT5M", lockAtMostForString = "PT14M") public void scheduledTask() { System.out.println("Running ShedLock task"); } -} \ No newline at end of file +} From 08b8c427bd1784f0dc0de4f43f7638a0aabcdfc3 Mon Sep 17 00:00:00 2001 From: Rajesh Bhojwani Date: Mon, 21 Jan 2019 08:15:38 +0530 Subject: [PATCH 110/190] rename file --- ...ilesClearDataManualTest.java => FilesClearDataUnitTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename core-java-io/src/test/java/com/baeldung/file/{FilesClearDataManualTest.java => FilesClearDataUnitTest.java} (98%) diff --git a/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java b/core-java-io/src/test/java/com/baeldung/file/FilesClearDataUnitTest.java similarity index 98% rename from core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java rename to core-java-io/src/test/java/com/baeldung/file/FilesClearDataUnitTest.java index c00290168c..653c4320c0 100644 --- a/core-java-io/src/test/java/com/baeldung/file/FilesClearDataManualTest.java +++ b/core-java-io/src/test/java/com/baeldung/file/FilesClearDataUnitTest.java @@ -22,7 +22,7 @@ import org.junit.Test; import com.baeldung.util.StreamUtils; -public class FilesClearDataManualTest { +public class FilesClearDataUnitTest { public static final String FILE_PATH = "src/test/resources/fileexample.txt"; From c713ddee6da9f3b3efc13a0b1935582c2581fee0 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Mon, 21 Jan 2019 09:26:47 +0400 Subject: [PATCH 111/190] trove list --- .../java/com/baeldung/array/PrimitiveCollections.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java b/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java index 115c5fe5c3..b991dcb598 100644 --- a/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java +++ b/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java @@ -2,6 +2,7 @@ package com.baeldung.array; import com.google.common.primitives.ImmutableIntArray; import com.google.common.primitives.Ints; +import gnu.trove.list.TIntList; import gnu.trove.list.array.TIntArrayList; import java.util.Arrays; @@ -13,13 +14,16 @@ public class PrimitiveCollections { int[] primitives = new int[] {5, 10, 0, 2}; - guavaPrimitives(primitives); + //guavaPrimitives(primitives); trovePrimitives(primitives); } private static void trovePrimitives(int[] primitives) { - TIntArrayList list = new TIntArrayList(primitives); + TIntList tList = new TIntArrayList(primitives); + tList.reverse(); + System.out.println(tList); + System.out.println(tList.size()); } private static void guavaPrimitives(int[] primitives) { From 3aff027b7a7e47a4700604b0b44ae45f48fa3c9b Mon Sep 17 00:00:00 2001 From: Urvy Agrawal Date: Mon, 21 Jan 2019 11:23:24 +0530 Subject: [PATCH 112/190] Adding file for BAEL-2558 --- .../BitwiseOperatorExample.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/bitwiseoperator/BitwiseOperatorExample.java diff --git a/core-java/src/main/java/com/baeldung/bitwiseoperator/BitwiseOperatorExample.java b/core-java/src/main/java/com/baeldung/bitwiseoperator/BitwiseOperatorExample.java new file mode 100644 index 0000000000..4fef92102a --- /dev/null +++ b/core-java/src/main/java/com/baeldung/bitwiseoperator/BitwiseOperatorExample.java @@ -0,0 +1,56 @@ +package com.baeldung.bitwiseoperator; + +public class BitwiseOperatorExample { + + public static void main(String[] args) { + + int value1 = 6; + int value2 = 5; + + // Bitwise AND Operator + int result = value1 & value2; + System.out.println("result : " + result); + + // Bitwise OR Operator + result = value1 | value2; + System.out.println("result : " + result); + + // Bitwise Exclusive OR Operator + result = value1 ^ value2; + System.out.println("result : " + result); + + // Bitwise NOT operator + result = ~value1; + System.out.println("result : " + result); + + // Right Shift Operator with positive number + int value = 12; + int rightShift = value >> 2; + System.out.println("rightShift result with positive number : " + rightShift); + + // Right Shift Operator with negative number + value = -12; + rightShift = value >> 2; + System.out.println("rightShift result with negative number : " + rightShift); + + // Left Shift Operator with positive number + value = 1; + int leftShift = value << 1; + System.out.println("leftShift result with positive number : " + leftShift); + + // Left Shift Operator with negative number + value = -12; + leftShift = value << 2; + System.out.println("leftShift result with negative number : " + leftShift); + + // Unsigned Right Shift Operator with positive number + value = 12; + int unsignedRightShift = value >>> 2; + System.out.println("unsignedRightShift result with positive number : " + unsignedRightShift); + + // Unsigned Right Shift Operator with negative number + value = -12; + unsignedRightShift = value >>> 2; + System.out.println("unsignedRightShift result with negative number : " + unsignedRightShift); + } +} From 5c1a0a06292115d99e24493ca1d69e32414e09b6 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Mon, 21 Jan 2019 09:57:15 +0400 Subject: [PATCH 113/190] change the ArrayList into List --- .../src/main/java/com/baeldung/string/MatchWords.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index d322d192fa..4baaa49227 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -71,15 +71,15 @@ public class MatchWords { } public static boolean containsWordsJava8(String inputString, String[] words) { - ArrayList inputStringList = new ArrayList<>(Arrays.asList(inputString.split(" "))); - ArrayList wordsList = new ArrayList<>(Arrays.asList(words)); + List inputStringList = Arrays.asList(inputString.split(" ")); + List wordsList = Arrays.asList(words); return wordsList.stream().allMatch(inputStringList::contains); } public static boolean containsWordsArray(String inputString, String[] words) { - ArrayList inputStringList = new ArrayList<>(Arrays.asList(inputString.split(" "))); - ArrayList wordsList = new ArrayList<>(Arrays.asList(words)); + List inputStringList = Arrays.asList(inputString.split(" ")); + List wordsList = Arrays.asList(words); return inputStringList.containsAll(wordsList); } From 369655aa02adf178b3d813edbc97ee603a963ffc Mon Sep 17 00:00:00 2001 From: pcoates33 Date: Mon, 21 Jan 2019 08:14:06 +0000 Subject: [PATCH 114/190] spring-boot ehcache example added (#6136) --- .../cachetest/config/CacheConfig.java | 49 +------------------ .../cachetest/config/CacheEventLogger.java | 11 ++--- .../cachetest/rest/NumberController.java | 16 +++--- .../cachetest/service/NumberService.java | 15 +++--- .../src/main/resources/application.properties | 1 + spring-ehcache/src/main/resources/ehcache.xml | 31 ++++++++++++ 6 files changed, 54 insertions(+), 69 deletions(-) create mode 100644 spring-ehcache/src/main/resources/application.properties create mode 100644 spring-ehcache/src/main/resources/ehcache.xml diff --git a/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheConfig.java b/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheConfig.java index 3cf2309cb9..5e72b5dcfc 100644 --- a/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheConfig.java +++ b/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheConfig.java @@ -1,57 +1,10 @@ package com.baeldung.cachetest.config; -import java.math.BigDecimal; -import java.time.Duration; - -import javax.cache.CacheManager; - -import org.ehcache.config.CacheConfiguration; -import org.ehcache.config.ResourcePools; -import org.ehcache.config.builders.CacheConfigurationBuilder; -import org.ehcache.config.builders.CacheEventListenerConfigurationBuilder; -import org.ehcache.config.builders.ExpiryPolicyBuilder; -import org.ehcache.config.builders.ResourcePoolsBuilder; -import org.ehcache.config.units.EntryUnit; -import org.ehcache.config.units.MemoryUnit; -import org.ehcache.event.EventType; -import org.ehcache.jsr107.Eh107Configuration; -import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer; import org.springframework.cache.annotation.EnableCaching; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableCaching public class CacheConfig { - - private static final int ON_HEAP_CACHE_SIZE_ENTRIES = 2; - private static final int OFF_HEAP_CACHE_SIZE_MB = 10; - private static final int CACHE_EXPIRY_SECONDS = 30; - - @Bean - public JCacheManagerCustomizer jcacheManagerCustomizer() { - return new JCacheManagerCustomizer() { - - @Override - public void customize(CacheManager cacheManager) { - ResourcePools resourcePools = ResourcePoolsBuilder.newResourcePoolsBuilder() - .heap(ON_HEAP_CACHE_SIZE_ENTRIES, EntryUnit.ENTRIES) - .offheap(OFF_HEAP_CACHE_SIZE_MB, MemoryUnit.MB).build(); - - CacheEventListenerConfigurationBuilder eventLoggerConfig = CacheEventListenerConfigurationBuilder - .newEventListenerConfiguration(new CacheEventLogger(), EventType.CREATED, EventType.EXPIRED) - .unordered().asynchronous(); - - CacheConfiguration cacheConfiguration = CacheConfigurationBuilder - .newCacheConfigurationBuilder(Long.class, BigDecimal.class, resourcePools) - .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(CACHE_EXPIRY_SECONDS))) - .add(eventLoggerConfig).build(); - - cacheManager.createCache("squareCache", - Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfiguration)); - - } - }; - } - + } diff --git a/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java b/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java index c8ead85f1e..dcaec57010 100644 --- a/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java +++ b/spring-ehcache/src/main/java/com/baeldung/cachetest/config/CacheEventLogger.java @@ -7,12 +7,11 @@ import org.slf4j.LoggerFactory; public class CacheEventLogger implements CacheEventListener { - private static final Logger log = LoggerFactory.getLogger(CacheEventLogger.class); + private static final Logger log = LoggerFactory.getLogger(CacheEventLogger.class); - @Override - public void onEvent(CacheEvent cacheEvent) { - log.info("Cache event {} for item with key {}. Old value = {}, New value = {}", cacheEvent.getType(), - cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue()); - } + @Override + public void onEvent(CacheEvent cacheEvent) { + log.info("Cache event {} for item with key {}. Old value = {}, New value = {}", cacheEvent.getType(), cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue()); + } } diff --git a/spring-ehcache/src/main/java/com/baeldung/cachetest/rest/NumberController.java b/spring-ehcache/src/main/java/com/baeldung/cachetest/rest/NumberController.java index 4115c34cc4..15b5c93dfe 100644 --- a/spring-ehcache/src/main/java/com/baeldung/cachetest/rest/NumberController.java +++ b/spring-ehcache/src/main/java/com/baeldung/cachetest/rest/NumberController.java @@ -15,15 +15,15 @@ import com.baeldung.cachetest.service.NumberService; @RequestMapping(path = "/number", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public class NumberController { - private final static Logger log = LoggerFactory.getLogger(NumberController.class); + private final static Logger log = LoggerFactory.getLogger(NumberController.class); - @Autowired - private NumberService numberService; + @Autowired + private NumberService numberService; - @GetMapping(path = "/square/{number}") - public String getThing(@PathVariable Long number) { - log.info("call numberService to square {}", number); - return String.format("{\"square\": %s}", numberService.square(number)); - } + @GetMapping(path = "/square/{number}") + public String getThing(@PathVariable Long number) { + log.info("call numberService to square {}", number); + return String.format("{\"square\": %s}", numberService.square(number)); + } } diff --git a/spring-ehcache/src/main/java/com/baeldung/cachetest/service/NumberService.java b/spring-ehcache/src/main/java/com/baeldung/cachetest/service/NumberService.java index bcd930f5e1..45fb841867 100644 --- a/spring-ehcache/src/main/java/com/baeldung/cachetest/service/NumberService.java +++ b/spring-ehcache/src/main/java/com/baeldung/cachetest/service/NumberService.java @@ -10,13 +10,14 @@ import org.springframework.stereotype.Service; @Service public class NumberService { - private final static Logger log = LoggerFactory.getLogger(NumberService.class); + private final static Logger log = LoggerFactory.getLogger(NumberService.class); - @Cacheable(value = "squareCache", key = "#number", condition = "#number>10") - public BigDecimal square(Long number) { - BigDecimal square = BigDecimal.valueOf(number).multiply(BigDecimal.valueOf(number)); - log.info("square of {} is {}", number, square); - return square; - } + @Cacheable(value = "squareCache", key = "#number", condition = "#number>10") + public BigDecimal square(Long number) { + BigDecimal square = BigDecimal.valueOf(number) + .multiply(BigDecimal.valueOf(number)); + log.info("square of {} is {}", number, square); + return square; + } } diff --git a/spring-ehcache/src/main/resources/application.properties b/spring-ehcache/src/main/resources/application.properties new file mode 100644 index 0000000000..a5c2964d32 --- /dev/null +++ b/spring-ehcache/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.cache.jcache.config=classpath:ehcache.xml \ No newline at end of file diff --git a/spring-ehcache/src/main/resources/ehcache.xml b/spring-ehcache/src/main/resources/ehcache.xml new file mode 100644 index 0000000000..caba0f2cc4 --- /dev/null +++ b/spring-ehcache/src/main/resources/ehcache.xml @@ -0,0 +1,31 @@ + + + + java.lang.Long + java.math.BigDecimal + + 30 + + + + + com.baeldung.cachetest.config.CacheEventLogger + ASYNCHRONOUS + UNORDERED + CREATED + EXPIRED + + + + + 2 + 10 + + + + \ No newline at end of file From 81f23992cb19ef7860cc4faa57df167a5d6d8ecd Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Mon, 21 Jan 2019 13:08:09 +0400 Subject: [PATCH 115/190] primitive collections --- .../baeldung/array/PrimitiveCollections.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java b/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java index b991dcb598..85f4dd2498 100644 --- a/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java +++ b/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java @@ -2,8 +2,6 @@ package com.baeldung.array; import com.google.common.primitives.ImmutableIntArray; import com.google.common.primitives.Ints; -import gnu.trove.list.TIntList; -import gnu.trove.list.array.TIntArrayList; import java.util.Arrays; import java.util.List; @@ -14,25 +12,21 @@ public class PrimitiveCollections { int[] primitives = new int[] {5, 10, 0, 2}; - //guavaPrimitives(primitives); - - trovePrimitives(primitives); + guavaPrimitives(primitives); } - private static void trovePrimitives(int[] primitives) { - TIntList tList = new TIntArrayList(primitives); - tList.reverse(); - System.out.println(tList); - System.out.println(tList.size()); - } private static void guavaPrimitives(int[] primitives) { - ImmutableIntArray list = ImmutableIntArray.builder().addAll(primitives).build(); + ImmutableIntArray immutableIntArray = ImmutableIntArray.builder().addAll(primitives).build(); + System.out.println(immutableIntArray); - List integers = Ints.asList(primitives); + List list = Ints.asList(primitives); - int[] primitive = Ints.toArray(Arrays.asList(1, 2, 3, 4, 5)); - System.out.println(Arrays.toString(primitive)); + int[] primitiveArray = Ints.toArray(list); + + int[] concatenated = Ints.concat(primitiveArray, primitives); + + System.out.println(Arrays.toString(concatenated)); } } From a608d7cd1553ae67508054446c30a44b54b9c5c8 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 21 Jan 2019 15:12:25 +0000 Subject: [PATCH 116/190] BAEL-2491: Conditionally enable spring scheduled jobs --- spring-scheduling/.gitignore | 25 ++ .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 48337 bytes .../.mvn/wrapper/maven-wrapper.properties | 1 + spring-scheduling/mvnw | 286 ++++++++++++++++++ spring-scheduling/mvnw.cmd | 161 ++++++++++ spring-scheduling/pom.xml | 42 +++ .../scheduling/ScheduleJobsByProfile.java | 20 ++ .../com/baeldung/scheduling/ScheduledJob.java | 21 ++ .../scheduling/ScheduledJobsWithBoolean.java | 28 ++ .../ScheduledJobsWithConditional.java | 20 ++ .../ScheduledJobsWithExpression.java | 23 ++ .../scheduling/SchedulingApplication.java | 16 + .../src/main/resources/application.properties | 0 .../SchedulingApplicationTests.java | 17 ++ 14 files changed, 660 insertions(+) create mode 100644 spring-scheduling/.gitignore create mode 100644 spring-scheduling/.mvn/wrapper/maven-wrapper.jar create mode 100644 spring-scheduling/.mvn/wrapper/maven-wrapper.properties create mode 100755 spring-scheduling/mvnw create mode 100644 spring-scheduling/mvnw.cmd create mode 100644 spring-scheduling/pom.xml create mode 100644 spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java create mode 100644 spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJob.java create mode 100644 spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java create mode 100644 spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java create mode 100644 spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java create mode 100644 spring-scheduling/src/main/java/com/baeldung/scheduling/SchedulingApplication.java create mode 100644 spring-scheduling/src/main/resources/application.properties create mode 100644 spring-scheduling/src/test/java/com/baeldung/scheduling/SchedulingApplicationTests.java diff --git a/spring-scheduling/.gitignore b/spring-scheduling/.gitignore new file mode 100644 index 0000000000..82eca336e3 --- /dev/null +++ b/spring-scheduling/.gitignore @@ -0,0 +1,25 @@ +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file diff --git a/spring-scheduling/.mvn/wrapper/maven-wrapper.jar b/spring-scheduling/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..01e67997377a393fd672c7dcde9dccbedf0cb1e9 GIT binary patch literal 48337 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 \(.*\)$'` + 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 Mingw, 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 + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + wget "$jarUrl" -O "$wrapperJarPath" + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + curl -o "$wrapperJarPath" "$jarUrl" + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# 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"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +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} $MAVEN_CONFIG "$@" diff --git a/spring-scheduling/mvnw.cmd b/spring-scheduling/mvnw.cmd new file mode 100644 index 0000000000..e5cfb0ae9e --- /dev/null +++ b/spring-scheduling/mvnw.cmd @@ -0,0 +1,161 @@ +@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 set title of command window +title %0 +@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 + +@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="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" +FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + echo Found %WRAPPER_JAR% +) else ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" + echo Finished downloading %WRAPPER_JAR% +) +@REM End of extension + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +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% diff --git a/spring-scheduling/pom.xml b/spring-scheduling/pom.xml new file mode 100644 index 0000000000..d739985f7c --- /dev/null +++ b/spring-scheduling/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.2.RELEASE + + + com.baeldung + scheduling + 0.0.1-SNAPSHOT + scheduling + Example of conditionally enabling spring scheduled jobs + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java b/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java new file mode 100644 index 0000000000..33cd44331f --- /dev/null +++ b/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java @@ -0,0 +1,20 @@ +package com.baeldung.scheduling; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Configuration +public class ScheduleJobsByProfile { + + private final static Logger LOG = LoggerFactory.getLogger(ScheduleJobsByProfile.class); + + @Profile("prod") + @Bean + public ScheduledJob scheduledJob() + { + return new ScheduledJob("@Profile"); + } +} diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJob.java b/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJob.java new file mode 100644 index 0000000000..df7cefcd3c --- /dev/null +++ b/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJob.java @@ -0,0 +1,21 @@ +package com.baeldung.scheduling; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; + +public class ScheduledJob { + + private String source; + + public ScheduledJob(String source) { + this.source = source; + } + + private final static Logger LOG = LoggerFactory.getLogger(ScheduledJob.class); + + @Scheduled(fixedDelay = 60000) + public void cleanTempDir() { + LOG.info("Cleaning temp directory via {}", source); + } +} diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java b/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java new file mode 100644 index 0000000000..b03de61641 --- /dev/null +++ b/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java @@ -0,0 +1,28 @@ +package com.baeldung.scheduling; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Scheduled; + +@Configuration +public class ScheduledJobsWithBoolean { + + private final static Logger LOG = LoggerFactory.getLogger(ScheduledJobsWithBoolean.class); + + @Value("${jobs.enabled:true}") + private boolean isEnabled; + + /** + * A scheduled job controlled via application property. The job always + * executes, but the logic inside is protected by a configurable boolean + * flag. + */ + @Scheduled(fixedDelay = 60000) + public void cleanTempDirectory() { + if(isEnabled) { + LOG.info("Cleaning temp directory via boolean flag"); + } + } +} diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java b/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java new file mode 100644 index 0000000000..081c8d990a --- /dev/null +++ b/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java @@ -0,0 +1,20 @@ +package com.baeldung.scheduling; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ScheduledJobsWithConditional +{ + /** + * This uses @ConditionalOnProperty to conditionally create a bean, which itself + * is a scheduled job. + * @return ScheduledJob + */ + @Bean + @ConditionalOnProperty(value = "jobs.enabled", matchIfMissing = true, havingValue = "true") + public ScheduledJob runMyCronTask() { + return new ScheduledJob("@ConditionalOnProperty"); + } +} diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java b/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java new file mode 100644 index 0000000000..577a01f241 --- /dev/null +++ b/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java @@ -0,0 +1,23 @@ +package com.baeldung.scheduling; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Scheduled; + +@Configuration +public class ScheduledJobsWithExpression +{ + private final static Logger LOG = + LoggerFactory.getLogger(ScheduledJobsWithExpression.class); + + /** + * A scheduled job controlled via application property. The job always + * executes, but the logic inside is protected by a configurable boolean + * flag. + */ + @Scheduled(cron = "${jobs.cronSchedule:-}") + public void cleanTempDirectory() { + LOG.info("Cleaning temp directory via placeholder"); + } +} diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/SchedulingApplication.java b/spring-scheduling/src/main/java/com/baeldung/scheduling/SchedulingApplication.java new file mode 100644 index 0000000000..913e2137f8 --- /dev/null +++ b/spring-scheduling/src/main/java/com/baeldung/scheduling/SchedulingApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.scheduling; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableScheduling +public class SchedulingApplication { + + public static void main(String[] args) { + SpringApplication.run(SchedulingApplication.class, args); + } + +} + diff --git a/spring-scheduling/src/main/resources/application.properties b/spring-scheduling/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-scheduling/src/test/java/com/baeldung/scheduling/SchedulingApplicationTests.java b/spring-scheduling/src/test/java/com/baeldung/scheduling/SchedulingApplicationTests.java new file mode 100644 index 0000000000..60e6d820bb --- /dev/null +++ b/spring-scheduling/src/test/java/com/baeldung/scheduling/SchedulingApplicationTests.java @@ -0,0 +1,17 @@ +package com.baeldung.scheduling; + +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 SchedulingApplicationTests { + + @Test + public void contextLoads() { + } + +} + From 196c17e612c00e789d2aee0138709ae8c49362fb Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 21 Jan 2019 15:14:13 +0000 Subject: [PATCH 117/190] BAEL-2491: Conditionally enable spring scheduled jobs --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1c0738cafb..1f25dd0691 100644 --- a/pom.xml +++ b/pom.xml @@ -714,7 +714,7 @@ spring-rest-simple spring-resttemplate spring-roo - + spring-scheduling spring-security-acl spring-security-angular/server spring-security-cache-control From 974950923c1069448c873033f27f42463d1c2350 Mon Sep 17 00:00:00 2001 From: Trevor Gowing Date: Mon, 24 Dec 2018 17:15:46 +0200 Subject: [PATCH 118/190] Refactor Passenger Entity Change seat number type to integer wrapper. Enable QuerybyExample (QBE) BAEL-2406 --- .../src/main/java/com/baeldung/passenger/Passenger.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java index 24ae47e597..a96b1edb20 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/Passenger.java @@ -25,15 +25,15 @@ class Passenger { @Basic(optional = false) @Column(nullable = false) - private int seatNumber; + private Integer seatNumber; - private Passenger(String firstName, String lastName, int seatNumber) { + private Passenger(String firstName, String lastName, Integer seatNumber) { this.firstName = firstName; this.lastName = lastName; this.seatNumber = seatNumber; } - static Passenger from(String firstName, String lastName, int seatNumber) { + static Passenger from(String firstName, String lastName, Integer seatNumber) { return new Passenger(firstName, lastName, seatNumber); } @@ -76,7 +76,7 @@ class Passenger { return lastName; } - int getSeatNumber() { + Integer getSeatNumber() { return seatNumber; } } From 14b65b327f571594f1572df4c145a0097cd272e8 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Sun, 20 Jan 2019 18:19:52 -0200 Subject: [PATCH 119/190] moved Rest Pagination article code from spring-rest-full to spring-boot-rest --- spring-boot-rest/README.md | 1 + spring-boot-rest/pom.xml | 30 ++++- .../{web => }/SpringBootRestApplication.java | 2 +- .../com/baeldung/persistence/IOperations.java | 16 +++ .../com/baeldung/persistence/dao/IFooDao.java | 9 ++ .../com/baeldung/persistence/model/Foo.java | 83 ++++++++++++++ .../persistence/service/IFooService.java | 13 +++ .../service/common/AbstractService.java | 31 ++++++ .../persistence/service/impl/FooService.java | 40 +++++++ .../baeldung/spring/PersistenceConfig.java | 85 +++++++++++++++ .../java/com/baeldung/spring/WebConfig.java | 43 ++++++++ .../web/config/MyErrorController.java | 1 - .../com/baeldung/web/config/WebConfig.java | 8 -- .../web/controller/FooController.java | 89 +++++++++++++++ .../web/controller/RootController.java | 40 +++++++ .../event/PaginatedResultsRetrievedEvent.java | 2 +- .../hateoas/event/ResourceCreatedEvent.java | 28 +++++ ...sultsRetrievedDiscoverabilityListener.java | 6 +- ...esourceCreatedDiscoverabilityListener.java | 36 ++++++ .../java/com/baeldung/web/util/LinkUtil.java | 36 ++++++ .../baeldung/web/util/RestPreconditions.java | 48 ++++++++ .../src/main/resources/application.properties | 3 + .../main/resources/persistence-h2.properties | 22 ++++ .../resources/persistence-mysql.properties | 10 ++ .../resources/springDataPersistenceConfig.xml | 12 ++ .../src/test/java/com/baeldung/Consts.java | 5 + .../SpringContextIntegrationTest.java | 2 +- .../common/web/AbstractBasicLiveTest.java | 103 ++++++++++++++++++ .../baeldung/common/web/AbstractLiveTest.java | 65 +++++++++++ .../spring/ConfigIntegrationTest.java | 17 +++ .../java/com/baeldung/test/IMarshaller.java | 15 +++ .../com/baeldung/test/JacksonMarshaller.java | 81 ++++++++++++++ .../baeldung/test/TestMarshallerFactory.java | 49 +++++++++ .../java/com/baeldung/web/FooLiveTest.java | 36 ++++++ .../baeldung/web/FooPageableLiveTest.java | 22 ++-- .../baeldung/web/LiveTestSuiteLiveTest.java | 14 +++ .../web/error/ErrorHandlingLiveTest.java | 7 +- .../baeldung/web/util/HTTPLinkHeaderUtil.java | 36 ++++++ spring-rest-full/README.md | 1 - .../org/baeldung/persistence/IOperations.java | 4 - .../persistence/service/IFooService.java | 4 - .../service/common/AbstractService.java | 7 -- .../persistence/service/impl/FooService.java | 7 -- .../web/controller/FooController.java | 31 ------ .../baeldung/web/util/RestPreconditions.java | 3 +- .../common/web/AbstractBasicLiveTest.java | 80 +------------- .../web/AbstractDiscoverabilityLiveTest.java | 5 +- .../baeldung/web/LiveTestSuiteLiveTest.java | 1 - 48 files changed, 1125 insertions(+), 164 deletions(-) rename spring-boot-rest/src/main/java/com/baeldung/{web => }/SpringBootRestApplication.java (92%) create mode 100644 spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/persistence/dao/IFooDao.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/persistence/service/IFooService.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java delete mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java rename {spring-rest-full/src/main/java/org => spring-boot-rest/src/main/java/com}/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java (97%) create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/ResourceCreatedEvent.java rename {spring-rest-full/src/main/java/org => spring-boot-rest/src/main/java/com}/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java (96%) create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/util/LinkUtil.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/util/RestPreconditions.java create mode 100644 spring-boot-rest/src/main/resources/persistence-h2.properties create mode 100644 spring-boot-rest/src/main/resources/persistence-mysql.properties create mode 100644 spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml create mode 100644 spring-boot-rest/src/test/java/com/baeldung/Consts.java rename spring-boot-rest/src/test/java/com/baeldung/{web => }/SpringContextIntegrationTest.java (92%) create mode 100644 spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java create mode 100644 spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java create mode 100644 spring-boot-rest/src/test/java/com/baeldung/spring/ConfigIntegrationTest.java create mode 100644 spring-boot-rest/src/test/java/com/baeldung/test/IMarshaller.java create mode 100644 spring-boot-rest/src/test/java/com/baeldung/test/JacksonMarshaller.java create mode 100644 spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java create mode 100644 spring-boot-rest/src/test/java/com/baeldung/web/FooLiveTest.java rename {spring-rest-full/src/test/java/org => spring-boot-rest/src/test/java/com}/baeldung/web/FooPageableLiveTest.java (86%) create mode 100644 spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java create mode 100644 spring-boot-rest/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index 2b955ddc5b..2c89a64a00 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -2,3 +2,4 @@ Module for the articles that are part of the Spring REST E-book: 1. [Bootstrap a Web Application with Spring 5](https://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) 2. [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring) +3. [REST Pagination in Spring](http://www.baeldung.com/rest-api-pagination-in-spring) \ No newline at end of file diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index f05d242072..bcd0381603 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -1,5 +1,6 @@ - 4.0.0 com.baeldung.web @@ -24,7 +25,7 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml - + org.hibernate hibernate-entitymanager @@ -32,6 +33,30 @@ org.springframework spring-jdbc + + org.springframework.data + spring-data-jpa + + + com.h2database + h2 + + + org.springframework + spring-tx + + + org.springframework.data + spring-data-commons + + + + + + com.google.guava + guava + ${guava.version} + org.springframework.boot @@ -58,5 +83,6 @@ com.baeldung.SpringBootRestApplication 2.32 + 27.0.1-jre diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java similarity index 92% rename from spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java rename to spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java index c945b20aa1..62aae7619d 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/SpringBootRestApplication.java +++ b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.web; +package com.baeldung; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java new file mode 100644 index 0000000000..d8996ca50d --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java @@ -0,0 +1,16 @@ +package com.baeldung.persistence; + +import java.io.Serializable; + +import org.springframework.data.domain.Page; + +public interface IOperations { + + // read - all + + Page findPaginated(int page, int size); + + // write + + T create(final T entity); +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/dao/IFooDao.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/dao/IFooDao.java new file mode 100644 index 0000000000..59394d0d28 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/dao/IFooDao.java @@ -0,0 +1,9 @@ +package com.baeldung.persistence.dao; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.persistence.model.Foo; + +public interface IFooDao extends JpaRepository { + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java new file mode 100644 index 0000000000..9af3d07bed --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java @@ -0,0 +1,83 @@ +package com.baeldung.persistence.model; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Foo implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @Column(nullable = false) + private String name; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + // API + + 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; + } + + // + + @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(); + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/IFooService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/IFooService.java new file mode 100644 index 0000000000..0f165238eb --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/IFooService.java @@ -0,0 +1,13 @@ +package com.baeldung.persistence.service; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import com.baeldung.persistence.IOperations; +import com.baeldung.persistence.model.Foo; + +public interface IFooService extends IOperations { + + Page findPaginated(Pageable pageable); + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java new file mode 100644 index 0000000000..871f768895 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java @@ -0,0 +1,31 @@ +package com.baeldung.persistence.service.common; + +import java.io.Serializable; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.persistence.IOperations; + +@Transactional +public abstract class AbstractService implements IOperations { + + // read - all + + @Override + public Page findPaginated(final int page, final int size) { + return getDao().findAll(PageRequest.of(page, size)); + } + + // write + + @Override + public T create(final T entity) { + return getDao().save(entity); + } + + protected abstract PagingAndSortingRepository getDao(); + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java new file mode 100644 index 0000000000..9d705f51d3 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java @@ -0,0 +1,40 @@ +package com.baeldung.persistence.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.persistence.dao.IFooDao; +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IFooService; +import com.baeldung.persistence.service.common.AbstractService; + +@Service +@Transactional +public class FooService extends AbstractService implements IFooService { + + @Autowired + private IFooDao dao; + + public FooService() { + super(); + } + + // API + + @Override + protected PagingAndSortingRepository getDao() { + return dao; + } + + // custom methods + + @Override + public Page findPaginated(Pageable pageable) { + return dao.findAll(pageable); + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java new file mode 100644 index 0000000000..4a4b9eee3f --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java @@ -0,0 +1,85 @@ +package com.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.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence-${envTarget:h2}.properties" }) +@ComponentScan({ "com.baeldung.persistence" }) +// @ImportResource("classpath*:springDataPersistenceConfig.xml") +@EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao") +public class PersistenceConfig { + + @Autowired + private Environment env; + + public PersistenceConfig() { + super(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + // vendorAdapter.set + 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 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")); + // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); + return hibernateProperties; + } + +} \ No newline at end of file diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java new file mode 100644 index 0000000000..39aade174b --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -0,0 +1,43 @@ +package com.baeldung.spring; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +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.WebMvcConfigurer; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +@Configuration +@ComponentScan("com.baeldung.web") +@EnableWebMvc +public class WebConfig implements WebMvcConfigurer { + + public WebConfig() { + super(); + } + + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/WEB-INF/view/"); + viewResolver.setSuffix(".jsp"); + return viewResolver; + } + + // API + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + registry.addViewController("/graph.html"); + registry.addViewController("/homepage.html"); + } + + @Override + public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { + configurer.defaultContentType(MediaType.APPLICATION_JSON); + } + +} \ No newline at end of file diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/config/MyErrorController.java b/spring-boot-rest/src/main/java/com/baeldung/web/config/MyErrorController.java index e3716ec113..cf3f9c4dbd 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/config/MyErrorController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/config/MyErrorController.java @@ -27,5 +27,4 @@ public class MyErrorController extends BasicErrorController { HttpStatus status = getStatus(request); return new ResponseEntity<>(body, status); } - } diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java deleted file mode 100644 index 808e946218..0000000000 --- a/spring-boot-rest/src/main/java/com/baeldung/web/config/WebConfig.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.web.config; - -import org.springframework.context.annotation.Configuration; - -@Configuration -public class WebConfig { - -} \ No newline at end of file diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java new file mode 100644 index 0000000000..b35295cf99 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java @@ -0,0 +1,89 @@ +package com.baeldung.web.controller; + +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.util.UriComponentsBuilder; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IFooService; +import com.baeldung.web.exception.MyResourceNotFoundException; +import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; +import com.baeldung.web.hateoas.event.ResourceCreatedEvent; +import com.google.common.base.Preconditions; + +@Controller +@RequestMapping(value = "/auth/foos") +public class FooController { + + @Autowired + private ApplicationEventPublisher eventPublisher; + + @Autowired + private IFooService service; + + public FooController() { + super(); + } + + // API + + // read - all + + @RequestMapping(params = { "page", "size" }, method = RequestMethod.GET) + @ResponseBody + public List findPaginated(@RequestParam("page") final int page, @RequestParam("size") final int size, + final UriComponentsBuilder uriBuilder, final HttpServletResponse response) { + final Page resultPage = service.findPaginated(page, size); + if (page > resultPage.getTotalPages()) { + throw new MyResourceNotFoundException(); + } + eventPublisher.publishEvent(new PaginatedResultsRetrievedEvent(Foo.class, uriBuilder, response, page, + resultPage.getTotalPages(), size)); + + return resultPage.getContent(); + } + + @GetMapping("/pageable") + @ResponseBody + public List findPaginatedWithPageable(Pageable pageable, final UriComponentsBuilder uriBuilder, + final HttpServletResponse response) { + final Page resultPage = service.findPaginated(pageable); + if (pageable.getPageNumber() > resultPage.getTotalPages()) { + throw new MyResourceNotFoundException(); + } + eventPublisher.publishEvent(new PaginatedResultsRetrievedEvent(Foo.class, uriBuilder, response, + pageable.getPageNumber(), resultPage.getTotalPages(), pageable.getPageSize())); + + return resultPage.getContent(); + } + + // write + + @RequestMapping(method = RequestMethod.POST) + @ResponseStatus(HttpStatus.CREATED) + @ResponseBody + public Foo create(@RequestBody final Foo resource, final HttpServletResponse response) { + Preconditions.checkNotNull(resource); + final Foo foo = service.create(resource); + final Long idOfCreatedResource = foo.getId(); + + eventPublisher.publishEvent(new ResourceCreatedEvent(this, response, idOfCreatedResource)); + + return foo; + } +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java new file mode 100644 index 0000000000..436e41e8eb --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java @@ -0,0 +1,40 @@ +package com.baeldung.web.controller; + +import java.net.URI; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.util.UriTemplate; + +import com.baeldung.web.util.LinkUtil; + +@Controller +@RequestMapping(value = "/auth/") +public class RootController { + + public RootController() { + super(); + } + + // API + + // discover + + @RequestMapping(value = "admin", method = RequestMethod.GET) + @ResponseStatus(value = HttpStatus.NO_CONTENT) + public void adminRoot(final HttpServletRequest request, final HttpServletResponse response) { + final String rootUri = request.getRequestURL() + .toString(); + + final URI fooUri = new UriTemplate("{rootUri}/{resource}").expand(rootUri, "foo"); + final String linkToFoo = LinkUtil.createLinkHeader(fooUri.toASCIIString(), "collection"); + response.addHeader("Link", linkToFoo); + } + +} diff --git a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java similarity index 97% rename from spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java rename to spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java index 01f7e658f1..f62fbf6247 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/PaginatedResultsRetrievedEvent.java @@ -1,4 +1,4 @@ -package org.baeldung.web.hateoas.event; +package com.baeldung.web.hateoas.event; import java.io.Serializable; diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/ResourceCreatedEvent.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/ResourceCreatedEvent.java new file mode 100644 index 0000000000..b602f7ec4b --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/ResourceCreatedEvent.java @@ -0,0 +1,28 @@ +package com.baeldung.web.hateoas.event; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.context.ApplicationEvent; + +public class ResourceCreatedEvent extends ApplicationEvent { + private final HttpServletResponse response; + private final long idOfNewResource; + + public ResourceCreatedEvent(final Object source, final HttpServletResponse response, final long idOfNewResource) { + super(source); + + this.response = response; + this.idOfNewResource = idOfNewResource; + } + + // API + + public HttpServletResponse getResponse() { + return response; + } + + public long getIdOfNewResource() { + return idOfNewResource; + } + +} diff --git a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java similarity index 96% rename from spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java rename to spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java index 603c91007d..bb60bab171 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java @@ -1,13 +1,13 @@ -package org.baeldung.web.hateoas.listener; +package com.baeldung.web.hateoas.listener; import javax.servlet.http.HttpServletResponse; -import org.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; -import org.baeldung.web.util.LinkUtil; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; import org.springframework.web.util.UriComponentsBuilder; +import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; +import com.baeldung.web.util.LinkUtil; import com.google.common.base.Preconditions; import com.google.common.net.HttpHeaders; diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java new file mode 100644 index 0000000000..37afcdace4 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java @@ -0,0 +1,36 @@ +package com.baeldung.web.hateoas.listener; + +import java.net.URI; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.http.HttpHeaders; +import com.baeldung.web.hateoas.event.ResourceCreatedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import com.google.common.base.Preconditions; + +@Component +class ResourceCreatedDiscoverabilityListener implements ApplicationListener { + + @Override + public void onApplicationEvent(final ResourceCreatedEvent resourceCreatedEvent) { + Preconditions.checkNotNull(resourceCreatedEvent); + + final HttpServletResponse response = resourceCreatedEvent.getResponse(); + final long idOfNewResource = resourceCreatedEvent.getIdOfNewResource(); + + addLinkHeaderOnResourceCreation(response, idOfNewResource); + } + + void addLinkHeaderOnResourceCreation(final HttpServletResponse response, final long idOfNewResource) { + // final String requestUrl = request.getRequestURL().toString(); + // final URI uri = new UriTemplate("{requestUrl}/{idOfNewResource}").expand(requestUrl, idOfNewResource); + + final URI uri = ServletUriComponentsBuilder.fromCurrentRequestUri().path("/{idOfNewResource}").buildAndExpand(idOfNewResource).toUri(); + response.setHeader(HttpHeaders.LOCATION, uri.toASCIIString()); + } + +} \ No newline at end of file diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/util/LinkUtil.java b/spring-boot-rest/src/main/java/com/baeldung/web/util/LinkUtil.java new file mode 100644 index 0000000000..3ebba8ae1c --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/util/LinkUtil.java @@ -0,0 +1,36 @@ +package com.baeldung.web.util; + +import javax.servlet.http.HttpServletResponse; + +/** + * Provides some constants and utility methods to build a Link Header to be stored in the {@link HttpServletResponse} object + */ +public final class LinkUtil { + + public static final String REL_COLLECTION = "collection"; + public static final String REL_NEXT = "next"; + public static final String REL_PREV = "prev"; + public static final String REL_FIRST = "first"; + public static final String REL_LAST = "last"; + + private LinkUtil() { + throw new AssertionError(); + } + + // + + /** + * Creates a Link Header to be stored in the {@link HttpServletResponse} to provide Discoverability features to the user + * + * @param uri + * the base uri + * @param rel + * the relative path + * + * @return the complete url + */ + public static String createLinkHeader(final String uri, final String rel) { + return "<" + uri + ">; rel=\"" + rel + "\""; + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/util/RestPreconditions.java b/spring-boot-rest/src/main/java/com/baeldung/web/util/RestPreconditions.java new file mode 100644 index 0000000000..d86aeeebd1 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/util/RestPreconditions.java @@ -0,0 +1,48 @@ +package com.baeldung.web.util; + +import org.springframework.http.HttpStatus; + +import com.baeldung.web.exception.MyResourceNotFoundException; + +/** + * Simple static methods to be called at the start of your own methods to verify correct arguments and state. If the Precondition fails, an {@link HttpStatus} code is thrown + */ +public final class RestPreconditions { + + private RestPreconditions() { + throw new AssertionError(); + } + + // API + + /** + * Check if some value was found, otherwise throw exception. + * + * @param expression + * has value true if found, otherwise false + * @throws MyResourceNotFoundException + * if expression is false, means value not found. + */ + public static void checkFound(final boolean expression) { + if (!expression) { + throw new MyResourceNotFoundException(); + } + } + + /** + * Check if some value was found, otherwise throw exception. + * + * @param expression + * has value true if found, otherwise false + * @throws MyResourceNotFoundException + * if expression is false, means value not found. + */ + public static T checkFound(final T resource) { + if (resource == null) { + throw new MyResourceNotFoundException(); + } + + return resource; + } + +} diff --git a/spring-boot-rest/src/main/resources/application.properties b/spring-boot-rest/src/main/resources/application.properties index e65440e2b9..a0179f1e4b 100644 --- a/spring-boot-rest/src/main/resources/application.properties +++ b/spring-boot-rest/src/main/resources/application.properties @@ -1,3 +1,6 @@ +server.port=8082 +server.servlet.context-path=/spring-boot-rest + ### Spring Boot default error handling configurations #server.error.whitelabel.enabled=false #server.error.include-stacktrace=always \ No newline at end of file diff --git a/spring-boot-rest/src/main/resources/persistence-h2.properties b/spring-boot-rest/src/main/resources/persistence-h2.properties new file mode 100644 index 0000000000..839a466533 --- /dev/null +++ b/spring-boot-rest/src/main/resources/persistence-h2.properties @@ -0,0 +1,22 @@ +## jdbc.X +#jdbc.driverClassName=com.mysql.jdbc.Driver +#jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate4_01?createDatabaseIfNotExist=true +#jdbc.user=tutorialuser +#jdbc.pass=tutorialmy5ql +# +## hibernate.X +#hibernate.dialect=org.hibernate.dialect.MySQL5Dialect +#hibernate.show_sql=false +#hibernate.hbm2ddl.auto=create-drop + + +# jdbc.X +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:security_permission;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE +jdbc.user=sa +jdbc.pass= + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop diff --git a/spring-boot-rest/src/main/resources/persistence-mysql.properties b/spring-boot-rest/src/main/resources/persistence-mysql.properties new file mode 100644 index 0000000000..8263b0d9ac --- /dev/null +++ b/spring-boot-rest/src/main/resources/persistence-mysql.properties @@ -0,0 +1,10 @@ +# jdbc.X +jdbc.driverClassName=com.mysql.jdbc.Driver +jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate4_01?createDatabaseIfNotExist=true +jdbc.user=tutorialuser +jdbc.pass=tutorialmy5ql + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.MySQL5Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop diff --git a/spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml b/spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml new file mode 100644 index 0000000000..5ea2d9c05b --- /dev/null +++ b/spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/spring-boot-rest/src/test/java/com/baeldung/Consts.java b/spring-boot-rest/src/test/java/com/baeldung/Consts.java new file mode 100644 index 0000000000..e33efd589e --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/Consts.java @@ -0,0 +1,5 @@ +package com.baeldung; + +public interface Consts { + int APPLICATION_PORT = 8082; +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java similarity index 92% rename from spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java rename to spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java index 1e49df2909..25fbc4cc02 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/SpringContextIntegrationTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.web; +package com.baeldung; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java new file mode 100644 index 0000000000..61eb9400cc --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java @@ -0,0 +1,103 @@ +package com.baeldung.common.web; + +import static com.baeldung.web.util.HTTPLinkHeaderUtil.extractURIByRel; +import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; + +import java.io.Serializable; +import java.util.List; + +import org.junit.Test; + +import com.google.common.net.HttpHeaders; + +import io.restassured.RestAssured; +import io.restassured.response.Response; + +public abstract class AbstractBasicLiveTest extends AbstractLiveTest { + + public AbstractBasicLiveTest(final Class clazzToSet) { + super(clazzToSet); + } + + // find - all - paginated + + @Test + public void whenResourcesAreRetrievedPaged_then200IsReceived() { + create(); + + final Response response = RestAssured.get(getURL() + "?page=0&size=10"); + + assertThat(response.getStatusCode(), is(200)); + } + + @Test + public void whenPageOfResourcesAreRetrievedOutOfBounds_then404IsReceived() { + final String url = getURL() + "?page=" + randomNumeric(5) + "&size=10"; + final Response response = RestAssured.get(url); + + assertThat(response.getStatusCode(), is(404)); + } + + @Test + public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources() { + create(); + + final Response response = RestAssured.get(getURL() + "?page=0&size=10"); + + assertFalse(response.body().as(List.class).isEmpty()); + } + + @Test + public void whenFirstPageOfResourcesAreRetrieved_thenSecondPageIsNext() { + create(); + create(); + create(); + + final Response response = RestAssured.get(getURL() + "?page=0&size=2"); + + final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next"); + assertEquals(getURL() + "?page=1&size=2", uriToNextPage); + } + + @Test + public void whenFirstPageOfResourcesAreRetrieved_thenNoPreviousPage() { + final Response response = RestAssured.get(getURL() + "?page=0&size=2"); + + final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev"); + assertNull(uriToPrevPage); + } + + @Test + public void whenSecondPageOfResourcesAreRetrieved_thenFirstPageIsPrevious() { + create(); + create(); + + final Response response = RestAssured.get(getURL() + "?page=1&size=2"); + + final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev"); + assertEquals(getURL() + "?page=0&size=2", uriToPrevPage); + } + + @Test + public void whenLastPageOfResourcesIsRetrieved_thenNoNextPageIsDiscoverable() { + create(); + create(); + create(); + + final Response first = RestAssured.get(getURL() + "?page=0&size=2"); + final String uriToLastPage = extractURIByRel(first.getHeader(HttpHeaders.LINK), "last"); + + final Response response = RestAssured.get(uriToLastPage); + + final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next"); + assertNull(uriToNextPage); + } + + // count + +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java new file mode 100644 index 0000000000..d26632bc38 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java @@ -0,0 +1,65 @@ +package com.baeldung.common.web; + +import io.restassured.RestAssured; +import io.restassured.response.Response; + +import static com.baeldung.Consts.APPLICATION_PORT; + +import java.io.Serializable; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.baeldung.test.IMarshaller; +import com.google.common.base.Preconditions; +import com.google.common.net.HttpHeaders; + +public abstract class AbstractLiveTest { + + protected final Class clazz; + + @Autowired + protected IMarshaller marshaller; + + public AbstractLiveTest(final Class clazzToSet) { + super(); + + Preconditions.checkNotNull(clazzToSet); + clazz = clazzToSet; + } + + // template method + + public abstract void create(); + + public abstract String createAsUri(); + + protected final void create(final T resource) { + createAsUri(resource); + } + + protected final String createAsUri(final T resource) { + final Response response = createAsResponse(resource); + Preconditions.checkState(response.getStatusCode() == 201, "create operation: " + response.getStatusCode()); + + final String locationOfCreatedResource = response.getHeader(HttpHeaders.LOCATION); + Preconditions.checkNotNull(locationOfCreatedResource); + return locationOfCreatedResource; + } + + final Response createAsResponse(final T resource) { + Preconditions.checkNotNull(resource); + + final String resourceAsString = marshaller.encode(resource); + return RestAssured.given() + .contentType(marshaller.getMime()) + .body(resourceAsString) + .post(getURL()); + } + + // + + protected String getURL() { + return "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest/auth/foos"; + } + +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/spring/ConfigIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/spring/ConfigIntegrationTest.java new file mode 100644 index 0000000000..da8421ea6c --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/spring/ConfigIntegrationTest.java @@ -0,0 +1,17 @@ +package com.baeldung.spring; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@ComponentScan("com.baeldung.test") +public class ConfigIntegrationTest implements WebMvcConfigurer { + + public ConfigIntegrationTest() { + super(); + } + + // API + +} \ No newline at end of file diff --git a/spring-boot-rest/src/test/java/com/baeldung/test/IMarshaller.java b/spring-boot-rest/src/test/java/com/baeldung/test/IMarshaller.java new file mode 100644 index 0000000000..e2198ecb59 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/test/IMarshaller.java @@ -0,0 +1,15 @@ +package com.baeldung.test; + +import java.util.List; + +public interface IMarshaller { + + String encode(final T entity); + + T decode(final String entityAsString, final Class clazz); + + List decodeList(final String entitiesAsString, final Class clazz); + + String getMime(); + +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/test/JacksonMarshaller.java b/spring-boot-rest/src/test/java/com/baeldung/test/JacksonMarshaller.java new file mode 100644 index 0000000000..23b5d60b6b --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/test/JacksonMarshaller.java @@ -0,0 +1,81 @@ +package com.baeldung.test; + +import java.io.IOException; +import java.util.List; + +import com.baeldung.persistence.model.Foo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Preconditions; + +public final class JacksonMarshaller implements IMarshaller { + private final Logger logger = LoggerFactory.getLogger(JacksonMarshaller.class); + + private final ObjectMapper objectMapper; + + public JacksonMarshaller() { + super(); + + objectMapper = new ObjectMapper(); + } + + // API + + @Override + public final String encode(final T resource) { + Preconditions.checkNotNull(resource); + String entityAsJSON = null; + try { + entityAsJSON = objectMapper.writeValueAsString(resource); + } catch (final IOException ioEx) { + logger.error("", ioEx); + } + + return entityAsJSON; + } + + @Override + public final T decode(final String resourceAsString, final Class clazz) { + Preconditions.checkNotNull(resourceAsString); + + T entity = null; + try { + entity = objectMapper.readValue(resourceAsString, clazz); + } catch (final IOException ioEx) { + logger.error("", ioEx); + } + + return entity; + } + + @SuppressWarnings("unchecked") + @Override + public final List decodeList(final String resourcesAsString, final Class clazz) { + Preconditions.checkNotNull(resourcesAsString); + + List entities = null; + try { + if (clazz.equals(Foo.class)) { + entities = objectMapper.readValue(resourcesAsString, new TypeReference>() { + // ... + }); + } else { + entities = objectMapper.readValue(resourcesAsString, List.class); + } + } catch (final IOException ioEx) { + logger.error("", ioEx); + } + + return entities; + } + + @Override + public final String getMime() { + return MediaType.APPLICATION_JSON.toString(); + } + +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java b/spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java new file mode 100644 index 0000000000..740ee07839 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java @@ -0,0 +1,49 @@ +package com.baeldung.test; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +@Component +@Profile("test") +public class TestMarshallerFactory implements FactoryBean { + + @Autowired + private Environment env; + + public TestMarshallerFactory() { + super(); + } + + // API + + @Override + public IMarshaller getObject() { + final String testMime = env.getProperty("test.mime"); + if (testMime != null) { + switch (testMime) { + case "json": + return new JacksonMarshaller(); + case "xml": + // If we need to implement xml marshaller we can include spring-rest-full XStreamMarshaller + throw new IllegalStateException(); + default: + throw new IllegalStateException(); + } + } + + return new JacksonMarshaller(); + } + + @Override + public Class getObjectType() { + return IMarshaller.class; + } + + @Override + public boolean isSingleton() { + return true; + } +} \ No newline at end of file diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooLiveTest.java new file mode 100644 index 0000000000..f721489eff --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooLiveTest.java @@ -0,0 +1,36 @@ +package com.baeldung.web; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import org.junit.runner.RunWith; +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 com.baeldung.common.web.AbstractBasicLiveTest; +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.ConfigIntegrationTest; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { ConfigIntegrationTest.class }, loader = AnnotationConfigContextLoader.class) +@ActiveProfiles("test") +public class FooLiveTest extends AbstractBasicLiveTest { + + public FooLiveTest() { + super(Foo.class); + } + + // API + + @Override + public final void create() { + create(new Foo(randomAlphabetic(6))); + } + + @Override + public final String createAsUri() { + return createAsUri(new Foo(randomAlphabetic(6))); + } + +} diff --git a/spring-rest-full/src/test/java/org/baeldung/web/FooPageableLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java similarity index 86% rename from spring-rest-full/src/test/java/org/baeldung/web/FooPageableLiveTest.java rename to spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java index 3f637c5213..359a62a4d8 100644 --- a/spring-rest-full/src/test/java/org/baeldung/web/FooPageableLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java @@ -1,19 +1,14 @@ -package org.baeldung.web; +package com.baeldung.web; +import static com.baeldung.Consts.APPLICATION_PORT; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; -import static org.baeldung.Consts.APPLICATION_PORT; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; -import io.restassured.RestAssured; -import io.restassured.response.Response; import java.util.List; -import org.baeldung.common.web.AbstractBasicLiveTest; -import org.baeldung.persistence.model.Foo; -import org.baeldung.spring.ConfigIntegrationTest; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ActiveProfiles; @@ -21,6 +16,13 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; +import com.baeldung.common.web.AbstractBasicLiveTest; +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.ConfigIntegrationTest; + +import io.restassured.RestAssured; +import io.restassured.response.Response; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { ConfigIntegrationTest.class }, loader = AnnotationConfigContextLoader.class) @ActiveProfiles("test") @@ -34,7 +36,7 @@ public class FooPageableLiveTest extends AbstractBasicLiveTest { @Override public final void create() { - create(new Foo(randomAlphabetic(6))); + super.create(new Foo(randomAlphabetic(6))); } @Override @@ -45,6 +47,8 @@ public class FooPageableLiveTest extends AbstractBasicLiveTest { @Override @Test public void whenResourcesAreRetrievedPaged_then200IsReceived() { + this.create(); + final Response response = RestAssured.get(getPageableURL() + "?page=0&size=10"); assertThat(response.getStatusCode(), is(200)); @@ -70,7 +74,7 @@ public class FooPageableLiveTest extends AbstractBasicLiveTest { } protected String getPageableURL() { - return "http://localhost:" + APPLICATION_PORT + "/spring-rest-full/auth/foos/pageable"; + return "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest/auth/foos/pageable"; } } diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java new file mode 100644 index 0000000000..1e2ddd5ec5 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java @@ -0,0 +1,14 @@ +package com.baeldung.web; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ +// @formatter:off + FooLiveTest.class + ,FooPageableLiveTest.class +}) // +public class LiveTestSuiteLiveTest { + +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/error/ErrorHandlingLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/error/ErrorHandlingLiveTest.java index ea1b6ab227..3e21af524f 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/error/ErrorHandlingLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/error/ErrorHandlingLiveTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isA; import static org.hamcrest.Matchers.not; +import static com.baeldung.Consts.APPLICATION_PORT; import org.junit.jupiter.api.Test; import org.springframework.http.HttpHeaders; @@ -16,8 +17,8 @@ import com.gargoylesoftware.htmlunit.html.HtmlPage; public class ErrorHandlingLiveTest { - private static final String BASE_URL = "http://localhost:8080"; - private static final String EXCEPTION_ENDPOINT = "/exception"; + private static final String BASE_URL = "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest"; + private static final String EXCEPTION_ENDPOINT = BASE_URL + "/exception"; private static final String ERROR_RESPONSE_KEY_PATH = "error"; private static final String XML_RESPONSE_KEY_PATH = "xmlkey"; @@ -57,7 +58,7 @@ public class ErrorHandlingLiveTest { try (WebClient webClient = new WebClient()) { webClient.getOptions() .setThrowExceptionOnFailingStatusCode(false); - HtmlPage page = webClient.getPage(BASE_URL + EXCEPTION_ENDPOINT); + HtmlPage page = webClient.getPage(EXCEPTION_ENDPOINT); assertThat(page.getBody() .asText()).contains("Whitelabel Error Page"); } diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java b/spring-boot-rest/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java new file mode 100644 index 0000000000..54d62b64e8 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java @@ -0,0 +1,36 @@ +package com.baeldung.web.util; + +public final class HTTPLinkHeaderUtil { + + private HTTPLinkHeaderUtil() { + throw new AssertionError(); + } + + // + + public static String extractURIByRel(final String linkHeader, final String rel) { + if (linkHeader == null) { + return null; + } + + String uriWithSpecifiedRel = null; + final String[] links = linkHeader.split(", "); + String linkRelation; + for (final String link : links) { + final int positionOfSeparator = link.indexOf(';'); + linkRelation = link.substring(positionOfSeparator + 1, link.length()).trim(); + if (extractTypeOfRelation(linkRelation).equals(rel)) { + uriWithSpecifiedRel = link.substring(1, positionOfSeparator - 1); + break; + } + } + + return uriWithSpecifiedRel; + } + + private static Object extractTypeOfRelation(final String linkRelation) { + final int positionOfEquals = linkRelation.indexOf('='); + return linkRelation.substring(positionOfEquals + 2, linkRelation.length() - 1).trim(); + } + +} diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md index 3a8d0a727a..2ef3a09e37 100644 --- a/spring-rest-full/README.md +++ b/spring-rest-full/README.md @@ -8,7 +8,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: -- [REST Pagination in Spring](http://www.baeldung.com/rest-api-pagination-in-spring) - [HATEOAS for a Spring REST Service](http://www.baeldung.com/rest-api-discoverability-with-spring) - [REST API Discoverability and HATEOAS](http://www.baeldung.com/restful-web-service-discoverability) - [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java b/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java index d4f3f0982c..8c5593c3e8 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java @@ -3,8 +3,6 @@ package org.baeldung.persistence; import java.io.Serializable; import java.util.List; -import org.springframework.data.domain.Page; - public interface IOperations { // read - one @@ -15,8 +13,6 @@ public interface IOperations { List findAll(); - Page findPaginated(int page, int size); - // write T create(final T entity); diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/IFooService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/IFooService.java index a3d16d9c15..60d607b9ef 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/IFooService.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/IFooService.java @@ -2,13 +2,9 @@ package org.baeldung.persistence.service; import org.baeldung.persistence.IOperations; import org.baeldung.persistence.model.Foo; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; public interface IFooService extends IOperations { Foo retrieveByName(String name); - - Page findPaginated(Pageable pageable); } diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java index 5987bbae5f..59ccea8b12 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java @@ -4,8 +4,6 @@ import java.io.Serializable; import java.util.List; import org.baeldung.persistence.IOperations; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.transaction.annotation.Transactional; @@ -30,11 +28,6 @@ public abstract class AbstractService implements IOperat return Lists.newArrayList(getDao().findAll()); } - @Override - public Page findPaginated(final int page, final int size) { - return getDao().findAll(new PageRequest(page, size)); - } - // write @Override diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java index 376082b2d5..d46f1bfe90 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java @@ -7,8 +7,6 @@ import org.baeldung.persistence.model.Foo; import org.baeldung.persistence.service.IFooService; import org.baeldung.persistence.service.common.AbstractService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -48,9 +46,4 @@ public class FooService extends AbstractService implements IFooService { return Lists.newArrayList(getDao().findAll()); } - @Override - public Page findPaginated(Pageable pageable) { - return dao.findAll(pageable); - } - } diff --git a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java index 484a59f8ef..443d0908ee 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java +++ b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java @@ -6,27 +6,20 @@ import javax.servlet.http.HttpServletResponse; import org.baeldung.persistence.model.Foo; import org.baeldung.persistence.service.IFooService; -import org.baeldung.web.exception.MyResourceNotFoundException; -import org.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; import org.baeldung.web.hateoas.event.ResourceCreatedEvent; import org.baeldung.web.hateoas.event.SingleResourceRetrievedEvent; import org.baeldung.web.util.RestPreconditions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; 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.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.util.UriComponentsBuilder; import com.google.common.base.Preconditions; @@ -72,30 +65,6 @@ public class FooController { return service.findAll(); } - @RequestMapping(params = { "page", "size" }, method = RequestMethod.GET) - @ResponseBody - public List findPaginated(@RequestParam("page") final int page, @RequestParam("size") final int size, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) { - final Page resultPage = service.findPaginated(page, size); - if (page > resultPage.getTotalPages()) { - throw new MyResourceNotFoundException(); - } - eventPublisher.publishEvent(new PaginatedResultsRetrievedEvent(Foo.class, uriBuilder, response, page, resultPage.getTotalPages(), size)); - - return resultPage.getContent(); - } - - @GetMapping("/pageable") - @ResponseBody - public List findPaginatedWithPageable(Pageable pageable, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) { - final Page resultPage = service.findPaginated(pageable); - if (pageable.getPageNumber() > resultPage.getTotalPages()) { - throw new MyResourceNotFoundException(); - } - eventPublisher.publishEvent(new PaginatedResultsRetrievedEvent(Foo.class, uriBuilder, response, pageable.getPageNumber(), resultPage.getTotalPages(), pageable.getPageSize())); - - return resultPage.getContent(); - } - // write @RequestMapping(method = RequestMethod.POST) diff --git a/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java b/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java index 18cb8219ec..4e211ccb10 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java +++ b/spring-rest-full/src/main/java/org/baeldung/web/util/RestPreconditions.java @@ -1,8 +1,9 @@ package org.baeldung.web.util; -import org.baeldung.web.exception.MyResourceNotFoundException; import org.springframework.http.HttpStatus; +import org.baeldung.web.exception.MyResourceNotFoundException; + /** * Simple static methods to be called at the start of your own methods to verify correct arguments and state. If the Precondition fails, an {@link HttpStatus} code is thrown */ diff --git a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java index 4e0007d036..d64807d97f 100644 --- a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java +++ b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java @@ -1,26 +1,19 @@ package org.baeldung.common.web; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; -import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; -import static org.baeldung.web.util.HTTPLinkHeaderUtil.extractURIByRel; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -import io.restassured.RestAssured; -import io.restassured.response.Response; import java.io.Serializable; -import java.util.List; import org.junit.Ignore; import org.junit.Test; import com.google.common.net.HttpHeaders; +import io.restassured.RestAssured; +import io.restassured.response.Response; + public abstract class AbstractBasicLiveTest extends AbstractLiveTest { public AbstractBasicLiveTest(final Class clazzToSet) { @@ -104,71 +97,4 @@ public abstract class AbstractBasicLiveTest extends Abst // find - one // find - all - - // find - all - paginated - - @Test - public void whenResourcesAreRetrievedPaged_then200IsReceived() { - final Response response = RestAssured.get(getURL() + "?page=0&size=10"); - - assertThat(response.getStatusCode(), is(200)); - } - - @Test - public void whenPageOfResourcesAreRetrievedOutOfBounds_then404IsReceived() { - final String url = getURL() + "?page=" + randomNumeric(5) + "&size=10"; - final Response response = RestAssured.get(url); - - assertThat(response.getStatusCode(), is(404)); - } - - @Test - public void givenResourcesExist_whenFirstPageIsRetrieved_thenPageContainsResources() { - create(); - - final Response response = RestAssured.get(getURL() + "?page=0&size=10"); - - assertFalse(response.body().as(List.class).isEmpty()); - } - - @Test - public void whenFirstPageOfResourcesAreRetrieved_thenSecondPageIsNext() { - final Response response = RestAssured.get(getURL() + "?page=0&size=2"); - - final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next"); - assertEquals(getURL() + "?page=1&size=2", uriToNextPage); - } - - @Test - public void whenFirstPageOfResourcesAreRetrieved_thenNoPreviousPage() { - final Response response = RestAssured.get(getURL() + "?page=0&size=2"); - - final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev"); - assertNull(uriToPrevPage); - } - - @Test - public void whenSecondPageOfResourcesAreRetrieved_thenFirstPageIsPrevious() { - create(); - create(); - - final Response response = RestAssured.get(getURL() + "?page=1&size=2"); - - final String uriToPrevPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "prev"); - assertEquals(getURL() + "?page=0&size=2", uriToPrevPage); - } - - @Test - public void whenLastPageOfResourcesIsRetrieved_thenNoNextPageIsDiscoverable() { - final Response first = RestAssured.get(getURL() + "?page=0&size=2"); - final String uriToLastPage = extractURIByRel(first.getHeader(HttpHeaders.LINK), "last"); - - final Response response = RestAssured.get(uriToLastPage); - - final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next"); - assertNull(uriToNextPage); - } - - // count - } diff --git a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractDiscoverabilityLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractDiscoverabilityLiveTest.java index c2dd3d84c7..96d796349a 100644 --- a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractDiscoverabilityLiveTest.java +++ b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractDiscoverabilityLiveTest.java @@ -5,8 +5,6 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; -import io.restassured.RestAssured; -import io.restassured.response.Response; import java.io.Serializable; @@ -18,6 +16,9 @@ import org.springframework.http.MediaType; import com.google.common.net.HttpHeaders; +import io.restassured.RestAssured; +import io.restassured.response.Response; + public abstract class AbstractDiscoverabilityLiveTest extends AbstractLiveTest { public AbstractDiscoverabilityLiveTest(final Class clazzToSet) { diff --git a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java index 71a61ed338..da736392c4 100644 --- a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java +++ b/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java @@ -8,7 +8,6 @@ import org.junit.runners.Suite; // @formatter:off FooDiscoverabilityLiveTest.class ,FooLiveTest.class - ,FooPageableLiveTest.class }) // public class LiveTestSuiteLiveTest { From 4187df5ce9b2c2b06a68742f97e4639a2274b0c9 Mon Sep 17 00:00:00 2001 From: Trevor Gowing Date: Mon, 24 Dec 2018 17:17:50 +0200 Subject: [PATCH 120/190] QueryByExample (QBE) Examples BAEL-2406 --- .../PassengerRepositoryIntegrationTest.java | 65 ++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java index c57e771345..59380c1427 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java @@ -5,6 +5,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.data.domain.Example; +import org.springframework.data.domain.ExampleMatcher; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; @@ -13,10 +15,12 @@ import org.springframework.test.context.junit4.SpringRunner; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.util.List; +import java.util.Optional; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; @DataJpaTest @RunWith(SpringRunner.class) @@ -61,7 +65,8 @@ public class PassengerRepositoryIntegrationTest { public void givenSeveralPassengersWhenFindPageSortedByThenThePassengerInTheFirstFilledSeatIsReturned() { Passenger expected = Passenger.from("Fred", "Bloggs", 22); - Page page = repository.findAll(PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber"))); + Page page = repository.findAll(PageRequest.of(0, 1, + Sort.by(Sort.Direction.ASC, "seatNumber"))); assertEquals(page.getContent().size(), 1); @@ -94,5 +99,61 @@ public class PassengerRepositoryIntegrationTest { assertThat(passengers, contains(fred, ricki, jill, siya, eve)); } - + + @Test + public void givenPassengers_whenFindByExampleDefaultMatcher_thenExpectedReturned() { + Example example = Example.of(Passenger.from("Fred", "Bloggs", null)); + + Optional actual = repository.findOne(example); + + assertTrue(actual.isPresent()); + assertEquals(actual.get(), Passenger.from("Fred", "Bloggs", 22)); + } + + @Test + public void givenPassengers_whenFindByExampleCaseInsensitiveMatcher_thenExpectedReturned() { + ExampleMatcher caseInsensitiveExampleMatcher = ExampleMatcher.matchingAll().withIgnoreCase(); + Example example = Example.of(Passenger.from("fred", "bloggs", null), + caseInsensitiveExampleMatcher); + + Optional actual = repository.findOne(example); + + assertTrue(actual.isPresent()); + assertEquals(actual.get(), Passenger.from("Fred", "Bloggs", 22)); + } + + @Test + public void givenPassengers_whenFindByExampleCustomMatcher_thenExpectedReturned() { + Passenger jill = Passenger.from("Jill", "Smith", 50); + Passenger eve = Passenger.from("Eve", "Jackson", 95); + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger siya = Passenger.from("Siya", "Kolisi", 85); + + ExampleMatcher customExampleMatcher = ExampleMatcher.matchingAny().withMatcher("firstName", + ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase()).withMatcher("lastName", + ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase()); + + Example example = Example.of(Passenger.from("e", "s", null), + customExampleMatcher); + + List passengers = repository.findAll(example); + + assertThat(passengers, contains(jill, eve, fred, siya)); + } + +@Test +public void givenPassengers_whenFindByIgnoringMatcher_thenExpectedReturned() { + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); + + ExampleMatcher ignoringExampleMatcher = ExampleMatcher.matchingAny().withMatcher("lastName", + ExampleMatcher.GenericPropertyMatchers.startsWith().ignoreCase()).withIgnorePaths("firstName", "seatNumber"); + + Example example = Example.of(Passenger.from(null, "b", null), + ignoringExampleMatcher); + + List passengers = repository.findAll(example); + + assertThat(passengers, contains(fred, ricki)); +} } From b50ef0b4002f61131de4d6496f869940eb584d16 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Mon, 21 Jan 2019 23:14:03 -0200 Subject: [PATCH 121/190] improved slightly link generation code --- ...sultsRetrievedDiscoverabilityListener.java | 55 ++++++++++++------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java index bb60bab171..31555ef353 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java @@ -1,5 +1,7 @@ package com.baeldung.web.hateoas.listener; +import java.util.StringJoiner; + import javax.servlet.http.HttpServletResponse; import org.springframework.context.ApplicationListener; @@ -27,32 +29,32 @@ class PaginatedResultsRetrievedDiscoverabilityListener implements ApplicationLis public final void onApplicationEvent(final PaginatedResultsRetrievedEvent ev) { Preconditions.checkNotNull(ev); - addLinkHeaderOnPagedResourceRetrieval(ev.getUriBuilder(), ev.getResponse(), ev.getClazz(), ev.getPage(), ev.getTotalPages(), ev.getPageSize()); + addLinkHeaderOnPagedResourceRetrieval(ev.getUriBuilder(), ev.getResponse(), ev.getClazz(), ev.getPage(), + ev.getTotalPages(), ev.getPageSize()); } // - note: at this point, the URI is transformed into plural (added `s`) in a hardcoded way - this will change in the future - final void addLinkHeaderOnPagedResourceRetrieval(final UriComponentsBuilder uriBuilder, final HttpServletResponse response, final Class clazz, final int page, final int totalPages, final int pageSize) { + final void addLinkHeaderOnPagedResourceRetrieval(final UriComponentsBuilder uriBuilder, + final HttpServletResponse response, final Class clazz, final int page, final int totalPages, + final int pageSize) { plural(uriBuilder, clazz); - final StringBuilder linkHeader = new StringBuilder(); + final StringJoiner linkHeader = new StringJoiner(", "); if (hasNextPage(page, totalPages)) { final String uriForNextPage = constructNextPageUri(uriBuilder, page, pageSize); - linkHeader.append(LinkUtil.createLinkHeader(uriForNextPage, LinkUtil.REL_NEXT)); + linkHeader.add(LinkUtil.createLinkHeader(uriForNextPage, LinkUtil.REL_NEXT)); } if (hasPreviousPage(page)) { final String uriForPrevPage = constructPrevPageUri(uriBuilder, page, pageSize); - appendCommaIfNecessary(linkHeader); - linkHeader.append(LinkUtil.createLinkHeader(uriForPrevPage, LinkUtil.REL_PREV)); + linkHeader.add(LinkUtil.createLinkHeader(uriForPrevPage, LinkUtil.REL_PREV)); } if (hasFirstPage(page)) { final String uriForFirstPage = constructFirstPageUri(uriBuilder, pageSize); - appendCommaIfNecessary(linkHeader); - linkHeader.append(LinkUtil.createLinkHeader(uriForFirstPage, LinkUtil.REL_FIRST)); + linkHeader.add(LinkUtil.createLinkHeader(uriForFirstPage, LinkUtil.REL_FIRST)); } if (hasLastPage(page, totalPages)) { final String uriForLastPage = constructLastPageUri(uriBuilder, totalPages, pageSize); - appendCommaIfNecessary(linkHeader); - linkHeader.append(LinkUtil.createLinkHeader(uriForLastPage, LinkUtil.REL_LAST)); + linkHeader.add(LinkUtil.createLinkHeader(uriForLastPage, LinkUtil.REL_LAST)); } if (linkHeader.length() > 0) { @@ -61,19 +63,35 @@ class PaginatedResultsRetrievedDiscoverabilityListener implements ApplicationLis } final String constructNextPageUri(final UriComponentsBuilder uriBuilder, final int page, final int size) { - return uriBuilder.replaceQueryParam(PAGE, page + 1).replaceQueryParam("size", size).build().encode().toUriString(); + return uriBuilder.replaceQueryParam(PAGE, page + 1) + .replaceQueryParam("size", size) + .build() + .encode() + .toUriString(); } final String constructPrevPageUri(final UriComponentsBuilder uriBuilder, final int page, final int size) { - return uriBuilder.replaceQueryParam(PAGE, page - 1).replaceQueryParam("size", size).build().encode().toUriString(); + return uriBuilder.replaceQueryParam(PAGE, page - 1) + .replaceQueryParam("size", size) + .build() + .encode() + .toUriString(); } final String constructFirstPageUri(final UriComponentsBuilder uriBuilder, final int size) { - return uriBuilder.replaceQueryParam(PAGE, 0).replaceQueryParam("size", size).build().encode().toUriString(); + return uriBuilder.replaceQueryParam(PAGE, 0) + .replaceQueryParam("size", size) + .build() + .encode() + .toUriString(); } final String constructLastPageUri(final UriComponentsBuilder uriBuilder, final int totalPages, final int size) { - return uriBuilder.replaceQueryParam(PAGE, totalPages).replaceQueryParam("size", size).build().encode().toUriString(); + return uriBuilder.replaceQueryParam(PAGE, totalPages) + .replaceQueryParam("size", size) + .build() + .encode() + .toUriString(); } final boolean hasNextPage(final int page, final int totalPages) { @@ -92,16 +110,11 @@ class PaginatedResultsRetrievedDiscoverabilityListener implements ApplicationLis return (totalPages > 1) && hasNextPage(page, totalPages); } - final void appendCommaIfNecessary(final StringBuilder linkHeader) { - if (linkHeader.length() > 0) { - linkHeader.append(", "); - } - } - // template protected void plural(final UriComponentsBuilder uriBuilder, final Class clazz) { - final String resourceName = clazz.getSimpleName().toLowerCase() + "s"; + final String resourceName = clazz.getSimpleName() + .toLowerCase() + "s"; uriBuilder.path("/auth/" + resourceName); } From 34907bfb0bb6b237c39cec3ac3a4ae00f09b17ee Mon Sep 17 00:00:00 2001 From: aietcn Date: Tue, 22 Jan 2019 14:24:38 +0800 Subject: [PATCH 122/190] BAEL-2551 add parallelprefix section in Arrays (#6184) --- .../arrays/ParallelPrefixBenchmark.java | 44 ++++++++++++++++ .../com/baeldung/arrays/ArraysUnitTest.java | 51 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java diff --git a/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java b/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java new file mode 100644 index 0000000000..ac54aea402 --- /dev/null +++ b/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java @@ -0,0 +1,44 @@ +package com.baeldung.arrays; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.Arrays; + +public class ParallelPrefixBenchmark { + private static final int ARRAY_SIZE = 200_000_000; + + @State(Scope.Benchmark) + public static class BigArray { + + int[] data; + + @Setup(Level.Iteration) + public void prepare() { + data = new int[ARRAY_SIZE]; + for(int j = 0; j< ARRAY_SIZE; j++) { + data[j] = 1; + } + } + + @TearDown(Level.Iteration) + public void destroy() { + data = null; + } + + } + + @Benchmark + public void largeArrayLoopSum(BigArray bigArray, Blackhole blackhole) { + for (int i = 0; i < ARRAY_SIZE - 1; i++) { + bigArray.data[i + 1] += bigArray.data[i]; + } + blackhole.consume(bigArray.data); + } + + @Benchmark + public void largeArrayParallelPrefixSum(BigArray bigArray, Blackhole blackhole) { + Arrays.parallelPrefix(bigArray.data, (left, right) -> left + right); + blackhole.consume(bigArray.data); + } +} diff --git a/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java b/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java index 9e6d3d6131..b6801612b9 100644 --- a/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java +++ b/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java @@ -1,5 +1,7 @@ package com.baeldung.arrays; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.*; import org.junit.Before; @@ -9,6 +11,7 @@ import org.junit.rules.ExpectedException; import java.util.Arrays; import java.util.List; +import java.util.Random; import java.util.stream.Stream; public class ArraysUnitTest { @@ -150,4 +153,52 @@ public class ArraysUnitTest { exception.expect(UnsupportedOperationException.class); rets.add("the"); } + + @Test + public void givenIntArray_whenPrefixAdd_thenAllAccumulated() { + int[] arri = new int[] { 1, 2, 3, 4}; + Arrays.parallelPrefix(arri, (left, right) -> left + right); + assertThat(arri, is(new int[] { 1, 3, 6, 10})); + } + + @Test + public void givenStringArray_whenPrefixConcat_thenAllMerged() { + String[] arrs = new String[] { "1", "2", "3" }; + Arrays.parallelPrefix(arrs, (left, right) -> left + right); + assertThat(arrs, is(new String[] { "1", "12", "123" })); + } + + @Test + public void whenPrefixAddWithRange_thenRangeAdded() { + int[] arri = new int[] { 1, 2, 3, 4, 5 }; + Arrays.parallelPrefix(arri, 1, 4, (left, right) -> left + right); + assertThat(arri, is(new int[] { 1, 2, 5, 9, 5 })); + } + + @Test + public void whenPrefixNonAssociative_thenError() { + boolean consistent = true; + Random r = new Random(); + for (int k = 0; k < 100_000; k++) { + int[] arrA = r.ints(100, 1, 5).toArray(); + int[] arrB = Arrays.copyOf(arrA, arrA.length); + + Arrays.parallelPrefix(arrA, this::nonassociativeFunc); + + for (int i = 1; i < arrB.length; i++) { + arrB[i] = nonassociativeFunc(arrB[i - 1], arrB[i]); + } + consistent = Arrays.equals(arrA, arrB); + if(!consistent) break; + } + assertFalse(consistent); + } + + /** + * non-associative int binary operator + */ + private int nonassociativeFunc(int left, int right) { + return left + right*left; + } + } From 2fb3e867d75aa291a53cf69d0d2f75230404c324 Mon Sep 17 00:00:00 2001 From: Urvy Agrawal Date: Tue, 22 Jan 2019 14:28:12 +0530 Subject: [PATCH 123/190] Adding test file for bitwise operators --- .../BitwiseOperatorExample.java | 56 ------------- .../test/BitwiseOperatorUnitTest.java | 81 +++++++++++++++++++ 2 files changed, 81 insertions(+), 56 deletions(-) delete mode 100644 core-java/src/main/java/com/baeldung/bitwiseoperator/BitwiseOperatorExample.java create mode 100644 core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java diff --git a/core-java/src/main/java/com/baeldung/bitwiseoperator/BitwiseOperatorExample.java b/core-java/src/main/java/com/baeldung/bitwiseoperator/BitwiseOperatorExample.java deleted file mode 100644 index 4fef92102a..0000000000 --- a/core-java/src/main/java/com/baeldung/bitwiseoperator/BitwiseOperatorExample.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.baeldung.bitwiseoperator; - -public class BitwiseOperatorExample { - - public static void main(String[] args) { - - int value1 = 6; - int value2 = 5; - - // Bitwise AND Operator - int result = value1 & value2; - System.out.println("result : " + result); - - // Bitwise OR Operator - result = value1 | value2; - System.out.println("result : " + result); - - // Bitwise Exclusive OR Operator - result = value1 ^ value2; - System.out.println("result : " + result); - - // Bitwise NOT operator - result = ~value1; - System.out.println("result : " + result); - - // Right Shift Operator with positive number - int value = 12; - int rightShift = value >> 2; - System.out.println("rightShift result with positive number : " + rightShift); - - // Right Shift Operator with negative number - value = -12; - rightShift = value >> 2; - System.out.println("rightShift result with negative number : " + rightShift); - - // Left Shift Operator with positive number - value = 1; - int leftShift = value << 1; - System.out.println("leftShift result with positive number : " + leftShift); - - // Left Shift Operator with negative number - value = -12; - leftShift = value << 2; - System.out.println("leftShift result with negative number : " + leftShift); - - // Unsigned Right Shift Operator with positive number - value = 12; - int unsignedRightShift = value >>> 2; - System.out.println("unsignedRightShift result with positive number : " + unsignedRightShift); - - // Unsigned Right Shift Operator with negative number - value = -12; - unsignedRightShift = value >>> 2; - System.out.println("unsignedRightShift result with negative number : " + unsignedRightShift); - } -} diff --git a/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java b/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java new file mode 100644 index 0000000000..139d3a2512 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java @@ -0,0 +1,81 @@ +package com.baeldung.bitwiseoperator.test; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +public class BitwiseOperatorUnitTest { + + @Test + public void givenTwoIntegers_whenAndOperator_thenNewDecimalNumber() { + int value1 = 6; + int value2 = 5; + int result = value1 & value2; + Assert.assertEquals(result, 4); + } + + @Test + public void givenTwoIntegers_whenOrOperator_thenNewDecimalNumber() { + int value1 = 6; + int value2 = 5; + int result = value1 | value2; + Assert.assertEquals(result, 7); + } + + @Test + public void givenTwoIntegers_whenXorOperator_thenNewDecimalNumber() { + int value1 = 6; + int value2 = 5; + int result = value1 ^ value2; + Assert.assertEquals(result, 3); + } + + @Test + public void givenOneInteger_whenNotOperator_thenNewDecimalNumber() { + int value1 = 6; + int result = ~value1; + Assert.assertEquals(result, -7); + } + + @Test + public void givenOnePositiveInteger_whenSignedRightShiftOperator_thenNewDecimalNumber() { + int value = 12; + int rightShift = value >> 2; + Assert.assertEquals(rightShift, 3); + } + + @Test + public void givenOneNegativeInteger_whenSignedRightShiftOperator_thenNewDecimalNumber() { + int value = -12; + int rightShift = value >> 2; + Assert.assertEquals(rightShift, -3); + } + + @Test + public void givenOnePositiveInteger_whenLeftShiftOperator_thenNewDecimalNumber() { + int value = 12; + int leftShift = value << 2; + Assert.assertEquals(leftShift, 48); + } + + @Test + public void givenOneNegativeInteger_whenLeftShiftOperator_thenNewDecimalNumber() { + int value = -12; + int leftShift = value << 2; + Assert.assertEquals(leftShift, -48); + } + + @Test + public void givenOnePositiveInteger_whenUnsignedRightShiftOperator_thenNewDecimalNumber() { + int value = 12; + int unsignedRightShift = value >>> 2; + Assert.assertEquals(unsignedRightShift, 3); + } + + @Test + public void givenOneNegativeInteger_whenUnsignedRightShiftOperator_thenNewDecimalNumber() { + int value = -12; + int unsignedRightShift = value >>> 2; + Assert.assertEquals(unsignedRightShift, 1073741821); + } + +} From 5bbc85c6c1cedb411019e62f506fae42f618bc6d Mon Sep 17 00:00:00 2001 From: enpy Date: Tue, 22 Jan 2019 17:18:11 +0100 Subject: [PATCH 124/190] classes and objects code added (#6173) * classes and objects code added * Car class and test added * fixes and enhancements * code moved to core-java-lang --- .../main/java/com/baeldung/objects/Car.java | 51 +++++++++++++++++++ .../com/baeldung/objects/CarUnitTest.java | 38 ++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 core-java-lang/src/main/java/com/baeldung/objects/Car.java create mode 100644 core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java diff --git a/core-java-lang/src/main/java/com/baeldung/objects/Car.java b/core-java-lang/src/main/java/com/baeldung/objects/Car.java new file mode 100644 index 0000000000..35ef8585b2 --- /dev/null +++ b/core-java-lang/src/main/java/com/baeldung/objects/Car.java @@ -0,0 +1,51 @@ +package com.baeldung.objects; + +public class Car { + + private String type; + private String model; + private String color; + private int speed; + + public Car(String type, String model, String color) { + this.type = type; + this.model = model; + this.color = color; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + + public int getSpeed() { + return speed; + } + + public int increaseSpeed(int increment) { + if (increment > 0) { + this.speed += increment; + } else { + System.out.println("Increment can't be negative."); + } + return this.speed; + } + + public int decreaseSpeed(int decrement) { + if (decrement > 0 && decrement <= this.speed) { + this.speed -= decrement; + } else { + System.out.println("Decrement can't be negative or greater than current speed."); + } + return this.speed; + } + + @Override + public String toString() { + return "Car [type=" + type + ", model=" + model + ", color=" + color + ", speed=" + speed + "]"; + } + +} diff --git a/core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java b/core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java new file mode 100644 index 0000000000..a1ef20523e --- /dev/null +++ b/core-java-lang/src/test/java/com/baeldung/objects/CarUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.objects; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +public class CarUnitTest { + + private Car car; + + @Before + public void setUp() throws Exception { + car = new Car("Ford", "Focus", "red"); + } + + @Test + public final void when_speedIncreased_then_verifySpeed() { + car.increaseSpeed(30); + assertEquals(30, car.getSpeed()); + + car.increaseSpeed(20); + assertEquals(50, car.getSpeed()); + } + + @Test + public final void when_speedDecreased_then_verifySpeed() { + car.increaseSpeed(50); + assertEquals(50, car.getSpeed()); + + car.decreaseSpeed(30); + assertEquals(20, car.getSpeed()); + + car.decreaseSpeed(20); + assertEquals(0, car.getSpeed()); + } + +} From 39ea408549fbce7be95e1b7160525c3b45f64e09 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Tue, 22 Jan 2019 19:58:57 +0200 Subject: [PATCH 125/190] Update BitwiseOperatorUnitTest.java --- .../test/BitwiseOperatorUnitTest.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java b/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java index 139d3a2512..d8af4b0833 100644 --- a/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java +++ b/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java @@ -1,6 +1,6 @@ package com.baeldung.bitwiseoperator.test; -import org.junit.Assert; +import static org.junit.Assert.assertEquals; import org.junit.jupiter.api.Test; public class BitwiseOperatorUnitTest { @@ -10,7 +10,7 @@ public class BitwiseOperatorUnitTest { int value1 = 6; int value2 = 5; int result = value1 & value2; - Assert.assertEquals(result, 4); + assertEquals(result, 4); } @Test @@ -18,7 +18,7 @@ public class BitwiseOperatorUnitTest { int value1 = 6; int value2 = 5; int result = value1 | value2; - Assert.assertEquals(result, 7); + assertEquals(result, 7); } @Test @@ -26,56 +26,56 @@ public class BitwiseOperatorUnitTest { int value1 = 6; int value2 = 5; int result = value1 ^ value2; - Assert.assertEquals(result, 3); + assertEquals(result, 3); } @Test public void givenOneInteger_whenNotOperator_thenNewDecimalNumber() { int value1 = 6; int result = ~value1; - Assert.assertEquals(result, -7); + assertEquals(result, -7); } @Test public void givenOnePositiveInteger_whenSignedRightShiftOperator_thenNewDecimalNumber() { int value = 12; int rightShift = value >> 2; - Assert.assertEquals(rightShift, 3); + assertEquals(rightShift, 3); } @Test public void givenOneNegativeInteger_whenSignedRightShiftOperator_thenNewDecimalNumber() { int value = -12; int rightShift = value >> 2; - Assert.assertEquals(rightShift, -3); + assertEquals(rightShift, -3); } @Test public void givenOnePositiveInteger_whenLeftShiftOperator_thenNewDecimalNumber() { int value = 12; int leftShift = value << 2; - Assert.assertEquals(leftShift, 48); + assertEquals(leftShift, 48); } @Test public void givenOneNegativeInteger_whenLeftShiftOperator_thenNewDecimalNumber() { int value = -12; int leftShift = value << 2; - Assert.assertEquals(leftShift, -48); + assertEquals(leftShift, -48); } @Test public void givenOnePositiveInteger_whenUnsignedRightShiftOperator_thenNewDecimalNumber() { int value = 12; int unsignedRightShift = value >>> 2; - Assert.assertEquals(unsignedRightShift, 3); + assertEquals(unsignedRightShift, 3); } @Test public void givenOneNegativeInteger_whenUnsignedRightShiftOperator_thenNewDecimalNumber() { int value = -12; int unsignedRightShift = value >>> 2; - Assert.assertEquals(unsignedRightShift, 1073741821); + assertEquals(unsignedRightShift, 1073741821); } } From 8c18214c558dc21ca0f956d50ad0587c19be1362 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Wed, 23 Jan 2019 09:44:05 +0400 Subject: [PATCH 126/190] more unit tests --- .../baeldung/string/MatchWordsUnitTest.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java b/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java index 0b25a265b3..1c2288068b 100644 --- a/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java +++ b/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java @@ -8,52 +8,59 @@ public class MatchWordsUnitTest { private final String[] words = {"hello", "Baeldung"}; private final String inputString = "hello there, Baeldung"; + private final String wholeInput = "helloBaeldung"; @Test public void givenText_whenCallingStringContains_shouldMatchWords() { - final boolean result = MatchWords.containsWords(inputString, words); - assertThat(result).isEqualTo(true); } @Test public void givenText_whenCallingJava8_shouldMatchWords() { - final boolean result = MatchWords.containsWordsJava8(inputString, words); - assertThat(result).isEqualTo(true); } + @Test + public void givenText_whenCallingJava8_shouldNotMatchWords() { + final boolean result = MatchWords.containsWordsJava8(wholeInput, words); + assertThat(result).isEqualTo(false); + } + @Test public void givenText_whenCallingPattern_shouldMatchWords() { - final boolean result = MatchWords.containsWordsPatternMatch(inputString, words); - assertThat(result).isEqualTo(true); } @Test public void givenText_whenCallingAhoCorasick_shouldMatchWords() { - final boolean result = MatchWords.containsWordsAhoCorasick(inputString, words); - assertThat(result).isEqualTo(true); } + @Test + public void givenText_whenCallingAhoCorasick_shouldNotMatchWords() { + final boolean result = MatchWords.containsWordsAhoCorasick(wholeInput, words); + assertThat(result).isEqualTo(false); + } + @Test public void givenText_whenCallingIndexOf_shouldMatchWords() { - final boolean result = MatchWords.containsWordsIndexOf(inputString, words); - assertThat(result).isEqualTo(true); } @Test public void givenText_whenCallingArrayList_shouldMatchWords() { - final boolean result = MatchWords.containsWordsArray(inputString, words); - assertThat(result).isEqualTo(true); } + + @Test + public void givenText_whenCallingArrayList_shouldNotMatchWords() { + final boolean result = MatchWords.containsWordsArray(wholeInput, words); + assertThat(result).isEqualTo(false); + } } From 7fa2aba180074969b59b4599a20f9792e76c1dc5 Mon Sep 17 00:00:00 2001 From: Fabian Rivera Date: Tue, 22 Jan 2019 23:54:24 -0600 Subject: [PATCH 127/190] BAEL-2414 Guide to problem-spring-web (#6147) * Fix issue with package name and folder name mismatch * Add problem-spring-web code samples * Use the latest version of the problem-spring-web library. Add spring security exceptions handling samples * Fix issue with security configuration. Fix sample for forbidden operation * Update ProblemDemoConfiguration.java * Add integration tests to validate problems are correctly handled and responses are generated using the problem library --- spring-boot-libraries/pom.xml | 270 +++++++++--------- .../com/baeldung/{ => boot}/Application.java | 2 +- .../problem/SpringProblemApplication.java | 19 ++ .../boot/problem/advice/ExceptionHandler.java | 9 + .../advice/SecurityExceptionHandler.java | 9 + .../ProblemDemoConfiguration.java | 17 ++ .../configuration/SecurityConfiguration.java | 31 ++ .../controller/ProblemDemoController.java | 56 ++++ .../com/baeldung/boot/problem/dto/Task.java | 32 +++ .../problem/problems/TaskNotFoundProblem.java | 16 ++ .../resources/application-problem.properties | 3 + .../ProblemDemoControllerIntegrationTest.java | 75 +++++ 12 files changed, 409 insertions(+), 130 deletions(-) rename spring-boot-libraries/src/main/java/com/baeldung/{ => boot}/Application.java (93%) create mode 100644 spring-boot-libraries/src/main/java/com/baeldung/boot/problem/SpringProblemApplication.java create mode 100644 spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/ExceptionHandler.java create mode 100644 spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/SecurityExceptionHandler.java create mode 100644 spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/ProblemDemoConfiguration.java create mode 100644 spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/SecurityConfiguration.java create mode 100644 spring-boot-libraries/src/main/java/com/baeldung/boot/problem/controller/ProblemDemoController.java create mode 100644 spring-boot-libraries/src/main/java/com/baeldung/boot/problem/dto/Task.java create mode 100644 spring-boot-libraries/src/main/java/com/baeldung/boot/problem/problems/TaskNotFoundProblem.java create mode 100644 spring-boot-libraries/src/main/resources/application-problem.properties create mode 100644 spring-boot-libraries/src/test/java/com/baeldung/boot/problem/controller/ProblemDemoControllerIntegrationTest.java diff --git a/spring-boot-libraries/pom.xml b/spring-boot-libraries/pom.xml index c28128c5f0..66aa66bdfd 100644 --- a/spring-boot-libraries/pom.xml +++ b/spring-boot-libraries/pom.xml @@ -1,144 +1,156 @@ - 4.0.0 - spring-boot-libraries - war - spring-boot-libraries - This is simple boot application for Spring boot actuator test + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + spring-boot-libraries + war + spring-boot-libraries + This is simple boot application for Spring boot actuator test - - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../parent-boot-2 - + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-tomcat - - - org.springframework.boot - spring-boot-starter-test - test - + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-tomcat + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.zalando + problem-spring-web + ${problem-spring-web.version} + - - - net.javacrumbs.shedlock - shedlock-spring - 2.1.0 - - - net.javacrumbs.shedlock - shedlock-provider-jdbc-template - 2.1.0 - + + + net.javacrumbs.shedlock + shedlock-spring + 2.1.0 + + + net.javacrumbs.shedlock + shedlock-provider-jdbc-template + 2.1.0 + - + - - spring-boot - - - src/main/resources - true - - + + spring-boot + + + src/main/resources + true + + - + - - org.apache.maven.plugins - maven-war-plugin - + + org.apache.maven.plugins + maven-war-plugin + - - pl.project13.maven - git-commit-id-plugin - ${git-commit-id-plugin.version} - - - get-the-git-infos - - revision - - initialize - - - validate-the-git-infos - - validateRevision - - package - - - - true - ${project.build.outputDirectory}/git.properties - - + + pl.project13.maven + git-commit-id-plugin + ${git-commit-id-plugin.version} + + + get-the-git-infos + + revision + + initialize + + + validate-the-git-infos + + validateRevision + + package + + + + true + ${project.build.outputDirectory}/git.properties + + - + - + - - - autoconfiguration - - - - org.apache.maven.plugins - maven-surefire-plugin - - - integration-test - - test - - - - **/*LiveTest.java - **/*IntegrationTest.java - **/*IntTest.java - - - **/AutoconfigurationTest.java - - - - - - - json - - - - - - - + + + autoconfiguration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + **/*IntegrationTest.java + **/*IntTest.java + + + **/AutoconfigurationTest.java + + + + + + + json + + + + + + + - - - com.baeldung.intro.App - 8.5.11 - 2.4.1.Final - 1.9.0 - 2.0.0 - 5.0.2 - 5.0.2 - 5.2.4 - 18.0 - 2.2.4 - 2.3.2 - + + + com.baeldung.intro.App + 8.5.11 + 2.4.1.Final + 1.9.0 + 2.0.0 + 5.0.2 + 5.0.2 + 5.2.4 + 18.0 + 2.2.4 + 2.3.2 + 0.23.0 + diff --git a/spring-boot-libraries/src/main/java/com/baeldung/Application.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java similarity index 93% rename from spring-boot-libraries/src/main/java/com/baeldung/Application.java rename to spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java index c1b6558b26..cb0d0c1532 100644 --- a/spring-boot-libraries/src/main/java/com/baeldung/Application.java +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/Application.java @@ -1,4 +1,4 @@ -package org.baeldung.boot; +package com.baeldung.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/SpringProblemApplication.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/SpringProblemApplication.java new file mode 100644 index 0000000000..7ca9881fb9 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/SpringProblemApplication.java @@ -0,0 +1,19 @@ +package com.baeldung.boot.problem; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@EnableAutoConfiguration(exclude = ErrorMvcAutoConfiguration.class) +@ComponentScan("com.baeldung.boot.problem") +public class SpringProblemApplication { + + public static void main(String[] args) { + System.setProperty("spring.profiles.active", "problem"); + SpringApplication.run(SpringProblemApplication.class, args); + } + +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/ExceptionHandler.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/ExceptionHandler.java new file mode 100644 index 0000000000..7b4cbac7f7 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/ExceptionHandler.java @@ -0,0 +1,9 @@ +package com.baeldung.boot.problem.advice; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.zalando.problem.spring.web.advice.ProblemHandling; + +@ControllerAdvice +public class ExceptionHandler implements ProblemHandling { + +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/SecurityExceptionHandler.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/SecurityExceptionHandler.java new file mode 100644 index 0000000000..8013cbf5c3 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/advice/SecurityExceptionHandler.java @@ -0,0 +1,9 @@ +package com.baeldung.boot.problem.advice; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.zalando.problem.spring.web.advice.security.SecurityAdviceTrait; + +@ControllerAdvice +public class SecurityExceptionHandler implements SecurityAdviceTrait { + +} \ No newline at end of file diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/ProblemDemoConfiguration.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/ProblemDemoConfiguration.java new file mode 100644 index 0000000000..209ff553c7 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/ProblemDemoConfiguration.java @@ -0,0 +1,17 @@ +package com.baeldung.boot.problem.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.zalando.problem.ProblemModule; +import org.zalando.problem.validation.ConstraintViolationProblemModule; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@Configuration +public class ProblemDemoConfiguration { + + @Bean + public ObjectMapper objectMapper() { + return new ObjectMapper().registerModules(new ProblemModule(), new ConstraintViolationProblemModule()); + } +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/SecurityConfiguration.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/SecurityConfiguration.java new file mode 100644 index 0000000000..0cb8048981 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/configuration/SecurityConfiguration.java @@ -0,0 +1,31 @@ +package com.baeldung.boot.problem.configuration; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +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.zalando.problem.spring.web.advice.security.SecurityProblemSupport; + +@Configuration +@EnableWebSecurity +@Import(SecurityProblemSupport.class) +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Autowired + private SecurityProblemSupport problemSupport; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.csrf().disable(); + + http.authorizeRequests() + .antMatchers("/") + .permitAll(); + + http.exceptionHandling() + .authenticationEntryPoint(problemSupport) + .accessDeniedHandler(problemSupport); + } +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/controller/ProblemDemoController.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/controller/ProblemDemoController.java new file mode 100644 index 0000000000..50f1ad5137 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/controller/ProblemDemoController.java @@ -0,0 +1,56 @@ +package com.baeldung.boot.problem.controller; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.http.MediaType; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.boot.problem.dto.Task; +import com.baeldung.boot.problem.problems.TaskNotFoundProblem; + +@RestController +@RequestMapping("/tasks") +public class ProblemDemoController { + + private static final Map MY_TASKS; + + static { + MY_TASKS = new HashMap<>(); + MY_TASKS.put(1L, new Task(1L, "My first task")); + MY_TASKS.put(2L, new Task(2L, "My second task")); + } + + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public List getTasks() { + return new ArrayList<>(MY_TASKS.values()); + } + + @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + public Task getTasks(@PathVariable("id") Long taskId) { + if (MY_TASKS.containsKey(taskId)) { + return MY_TASKS.get(taskId); + } else { + throw new TaskNotFoundProblem(taskId); + } + } + + @PutMapping("/{id}") + public void updateTask(@PathVariable("id") Long id) { + throw new UnsupportedOperationException(); + } + + @DeleteMapping("/{id}") + public void deleteTask(@PathVariable("id") Long id) { + throw new AccessDeniedException("You can't delete this task"); + } + +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/dto/Task.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/dto/Task.java new file mode 100644 index 0000000000..a5f39474e7 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/dto/Task.java @@ -0,0 +1,32 @@ +package com.baeldung.boot.problem.dto; + +public class Task { + + private Long id; + private String description; + + public Task() { + } + + public Task(Long id, String description) { + this.id = id; + this.description = description; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/problems/TaskNotFoundProblem.java b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/problems/TaskNotFoundProblem.java new file mode 100644 index 0000000000..cc3f21d4a5 --- /dev/null +++ b/spring-boot-libraries/src/main/java/com/baeldung/boot/problem/problems/TaskNotFoundProblem.java @@ -0,0 +1,16 @@ +package com.baeldung.boot.problem.problems; + +import java.net.URI; + +import org.zalando.problem.AbstractThrowableProblem; +import org.zalando.problem.Status; + +public class TaskNotFoundProblem extends AbstractThrowableProblem { + + private static final URI TYPE = URI.create("https://example.org/not-found"); + + public TaskNotFoundProblem(Long taskId) { + super(TYPE, "Not found", Status.NOT_FOUND, String.format("Task '%s' not found", taskId)); + } + +} diff --git a/spring-boot-libraries/src/main/resources/application-problem.properties b/spring-boot-libraries/src/main/resources/application-problem.properties new file mode 100644 index 0000000000..7d0b0a2720 --- /dev/null +++ b/spring-boot-libraries/src/main/resources/application-problem.properties @@ -0,0 +1,3 @@ +spring.resources.add-mappings=false +spring.mvc.throw-exception-if-no-handler-found=true +spring.http.encoding.force=true diff --git a/spring-boot-libraries/src/test/java/com/baeldung/boot/problem/controller/ProblemDemoControllerIntegrationTest.java b/spring-boot-libraries/src/test/java/com/baeldung/boot/problem/controller/ProblemDemoControllerIntegrationTest.java new file mode 100644 index 0000000000..3b7e43a565 --- /dev/null +++ b/spring-boot-libraries/src/test/java/com/baeldung/boot/problem/controller/ProblemDemoControllerIntegrationTest.java @@ -0,0 +1,75 @@ +package com.baeldung.boot.problem.controller; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import com.baeldung.boot.problem.SpringProblemApplication; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = SpringProblemApplication.class) +@AutoConfigureMockMvc +public class ProblemDemoControllerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenRequestingAllTasks_thenReturnSuccessfulResponseWithArrayWithTwoTasks() throws Exception { + mockMvc.perform(get("/tasks").contentType(MediaType.APPLICATION_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.length()", equalTo(2))) + .andExpect(status().isOk()); + } + + @Test + public void whenRequestingExistingTask_thenReturnSuccessfulResponse() throws Exception { + mockMvc.perform(get("/tasks/1").contentType(MediaType.APPLICATION_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.id", equalTo(1))) + .andExpect(status().isOk()); + } + + @Test + public void whenRequestingMissingTask_thenReturnNotFoundProblemResponse() throws Exception { + mockMvc.perform(get("/tasks/5").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.title", equalTo("Not found"))) + .andExpect(jsonPath("$.status", equalTo(404))) + .andExpect(jsonPath("$.detail", equalTo("Task '5' not found"))) + .andExpect(status().isNotFound()); + } + + @Test + public void whenMakePutCall_thenReturnNotImplementedProblemResponse() throws Exception { + mockMvc.perform(put("/tasks/1").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.title", equalTo("Not Implemented"))) + .andExpect(jsonPath("$.status", equalTo(501))) + .andExpect(status().isNotImplemented()); + } + + @Test + public void whenMakeDeleteCall_thenReturnForbiddenProblemResponse() throws Exception { + mockMvc.perform(delete("/tasks/2").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE)) + .andDo(print()) + .andExpect(jsonPath("$.title", equalTo("Forbidden"))) + .andExpect(jsonPath("$.status", equalTo(403))) + .andExpect(jsonPath("$.detail", equalTo("You can't delete this task"))) + .andExpect(status().isForbidden()); + } + +} From effde80333489fa4b74cb173261c812456de8134 Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Wed, 23 Jan 2019 14:19:48 +0200 Subject: [PATCH 128/190] BAEL - 2420 Converting Float to Byte Array and vice-versa in Java (#6194) * Hexagonal Architecture in Java - Spring boot app * create README.md * Update README.md * Update README.md * BAEL-2420 Converting Float to Byte Array and vice-versa in Java * BAEL-2420 Converting Float to Byte Array and vice-versa in Java - conversions package added * Hexagonal architecture code removed --- .../array/conversions/FloatToByteArray.java | 44 ++++++++++++++++++ .../conversions/FloatToByteArrayUnitTest.java | 46 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 core-java-arrays/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java create mode 100644 core-java-arrays/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java diff --git a/core-java-arrays/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java b/core-java-arrays/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java new file mode 100644 index 0000000000..b831e436a5 --- /dev/null +++ b/core-java-arrays/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java @@ -0,0 +1,44 @@ +package com.baeldung.array.conversions; + +import java.nio.ByteBuffer; + +public class FloatToByteArray { + + /** + * convert float into byte array using Float API floatToIntBits + * @param value + * @return byte[] + */ + public static byte[] floatToByteArray(float value) { + int intBits = Float.floatToIntBits(value); + return new byte[] {(byte) (intBits >> 24), (byte) (intBits >> 16), (byte) (intBits >> 8), (byte) (intBits) }; + } + + /** + * convert byte array into float using Float API intBitsToFloat + * @param bytes + * @return float + */ + public static float byteArrayToFloat(byte[] bytes) { + int intBits = bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF); + return Float.intBitsToFloat(intBits); + } + + /** + * convert float into byte array using ByteBuffer + * @param value + * @return byte[] + */ + public static byte[] floatToByteArrayWithByteBuffer(float value) { + return ByteBuffer.allocate(4).putFloat(value).array(); + } + + /** + * convert byte array into float using ByteBuffer + * @param bytes + * @return float + */ + public static float byteArrayToFloatWithByteBuffer(byte[] bytes) { + return ByteBuffer.wrap(bytes).getFloat(); + } +} diff --git a/core-java-arrays/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java b/core-java-arrays/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java new file mode 100644 index 0000000000..a2cd273f21 --- /dev/null +++ b/core-java-arrays/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.array.conversions; + +import static com.baeldung.array.conversions.FloatToByteArray.byteArrayToFloat; +import static com.baeldung.array.conversions.FloatToByteArray.byteArrayToFloatWithByteBuffer; +import static com.baeldung.array.conversions.FloatToByteArray.floatToByteArray; +import static com.baeldung.array.conversions.FloatToByteArray.floatToByteArrayWithByteBuffer; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class FloatToByteArrayUnitTest { + + @Test + public void givenAFloat_thenConvertToByteArray() { + assertArrayEquals(new byte[] { 63, -116, -52, -51}, floatToByteArray(1.1f)); + } + + @Test + public void givenAByteArray_thenConvertToFloat() { + assertEquals(1.1f, byteArrayToFloat(new byte[] { 63, -116, -52, -51}), 0); + } + + @Test + public void givenAFloat_thenConvertToByteArrayUsingByteBuffer() { + assertArrayEquals(new byte[] { 63, -116, -52, -51}, floatToByteArrayWithByteBuffer(1.1f)); + } + + @Test + public void givenAByteArray_thenConvertToFloatUsingByteBuffer() { + assertEquals(1.1f, byteArrayToFloatWithByteBuffer(new byte[] { 63, -116, -52, -51}), 0); + } + + @Test + public void givenAFloat_thenConvertToByteArray_thenConvertToFloat() { + float floatToConvert = 200.12f; + byte[] byteArray = floatToByteArray(floatToConvert); + assertEquals(200.12f, byteArrayToFloat(byteArray), 0); + } + + @Test + public void givenAFloat_thenConvertToByteArrayWithByteBuffer_thenConvertToFloatWithByteBuffer() { + float floatToConvert = 30100.42f; + byte[] byteArray = floatToByteArrayWithByteBuffer(floatToConvert); + assertEquals(30100.42f, byteArrayToFloatWithByteBuffer(byteArray), 0); + } +} From 4c7ef02bf3781299a09db3430c2989648f6d5841 Mon Sep 17 00:00:00 2001 From: Andrea Ligios Date: Wed, 23 Jan 2019 18:12:06 +0100 Subject: [PATCH 129/190] BAEL-2294 (#6191) * BAEL-2294 * BAEL-2294 * live tests... * formatting * Live Tests! But not parent pom. Yet. --- blade/README.md | 5 + blade/pom.xml | 189 ++++++++++++++++++ .../java/com/baeldung/blade/sample/App.java | 38 ++++ .../sample/AttributesExampleController.java | 37 ++++ .../blade/sample/LogExampleController.java | 22 ++ .../ParameterInjectionExampleController.java | 71 +++++++ .../blade/sample/RouteExampleController.java | 78 ++++++++ .../configuration/BaeldungException.java | 9 + .../configuration/GlobalExceptionHandler.java | 25 +++ .../sample/configuration/LoadConfig.java | 23 +++ .../sample/configuration/ScheduleExample.java | 15 ++ .../sample/interceptors/BaeldungHook.java | 17 ++ .../interceptors/BaeldungMiddleware.java | 15 ++ .../com/baeldung/blade/sample/vo/User.java | 16 ++ .../src/main/resources/application.properties | 5 + .../src/main/resources/custom-static/icon.png | Bin 0 -> 28893 bytes blade/src/main/resources/favicon.ico | Bin 0 -> 650 bytes blade/src/main/resources/static/app.css | 1 + blade/src/main/resources/static/app.js | 0 .../main/resources/static/file-upload.html | 43 ++++ .../src/main/resources/static/user-post.html | 25 +++ .../main/resources/templates/allmatch.html | 1 + .../src/main/resources/templates/delete.html | 1 + blade/src/main/resources/templates/get.html | 1 + blade/src/main/resources/templates/index.html | 30 +++ .../src/main/resources/templates/my-404.html | 10 + .../src/main/resources/templates/my-500.html | 12 ++ blade/src/main/resources/templates/post.html | 1 + blade/src/main/resources/templates/put.html | 1 + .../templates/template-output-test.html | 1 + .../baeldung/blade/sample/AppLiveTest.java | 56 ++++++ .../AttributesExampleControllerLiveTest.java | 55 +++++ ...terInjectionExampleControllerLiveTest.java | 82 ++++++++ .../RouteExampleControllerLiveTest.java | 117 +++++++++++ pom.xml | 2 + 35 files changed, 1004 insertions(+) create mode 100644 blade/README.md create mode 100644 blade/pom.xml create mode 100644 blade/src/main/java/com/baeldung/blade/sample/App.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java create mode 100644 blade/src/main/java/com/baeldung/blade/sample/vo/User.java create mode 100644 blade/src/main/resources/application.properties create mode 100644 blade/src/main/resources/custom-static/icon.png create mode 100644 blade/src/main/resources/favicon.ico create mode 100644 blade/src/main/resources/static/app.css create mode 100644 blade/src/main/resources/static/app.js create mode 100644 blade/src/main/resources/static/file-upload.html create mode 100644 blade/src/main/resources/static/user-post.html create mode 100644 blade/src/main/resources/templates/allmatch.html create mode 100644 blade/src/main/resources/templates/delete.html create mode 100644 blade/src/main/resources/templates/get.html create mode 100644 blade/src/main/resources/templates/index.html create mode 100644 blade/src/main/resources/templates/my-404.html create mode 100644 blade/src/main/resources/templates/my-500.html create mode 100644 blade/src/main/resources/templates/post.html create mode 100644 blade/src/main/resources/templates/put.html create mode 100644 blade/src/main/resources/templates/template-output-test.html create mode 100644 blade/src/test/java/com/baeldung/blade/sample/AppLiveTest.java create mode 100644 blade/src/test/java/com/baeldung/blade/sample/AttributesExampleControllerLiveTest.java create mode 100644 blade/src/test/java/com/baeldung/blade/sample/ParameterInjectionExampleControllerLiveTest.java create mode 100644 blade/src/test/java/com/baeldung/blade/sample/RouteExampleControllerLiveTest.java diff --git a/blade/README.md b/blade/README.md new file mode 100644 index 0000000000..d823de775f --- /dev/null +++ b/blade/README.md @@ -0,0 +1,5 @@ +### Relevant Articles: + +- [Blade - A Complete GuideBook](http://www.baeldung.com/blade) + +Run Integration Tests with `mvn integration-test` \ No newline at end of file diff --git a/blade/pom.xml b/blade/pom.xml new file mode 100644 index 0000000000..6bad505f4a --- /dev/null +++ b/blade/pom.xml @@ -0,0 +1,189 @@ + + + 4.0.0 + blade + blade + + + com.baeldung + 1.0.0-SNAPSHOT + + + + + + + + + + 1.8 + 1.8 + + + + + com.bladejava + blade-mvc + 2.0.14.RELEASE + + + + org.webjars + bootstrap + 4.2.1 + + + + org.apache.commons + commons-lang3 + 3.8.1 + + + + + org.projectlombok + lombok + 1.18.4 + provided + + + + + junit + junit + 4.12 + test + + + org.assertj + assertj-core + 3.11.1 + test + + + org.apache.httpcomponents + httpclient + 4.5.6 + test + + + org.apache.httpcomponents + httpmime + 4.5.6 + test + + + org.apache.httpcomponents + httpcore + 4.4.10 + test + + + + sample-blade-app + + + + org.apache.maven.plugins + maven-surefire-plugin + + 3 + true + + **/*LiveTest.java + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.0.0-M3 + + + **/*LiveTest.java + + + + + + integration-test + verify + + + + + + + com.bazaarvoice.maven.plugins + process-exec-maven-plugin + 0.7 + + + + blade-process + pre-integration-test + + start + + + Blade + false + + java + -jar + sample-blade-app.jar + + + + + + + stop-all + post-integration-test + + stop-all + + + + + + + + maven-assembly-plugin + 3.1.0 + + ${project.build.finalName} + false + + + com.baeldung.blade.sample.App + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + + + + + diff --git a/blade/src/main/java/com/baeldung/blade/sample/App.java b/blade/src/main/java/com/baeldung/blade/sample/App.java new file mode 100644 index 0000000000..f3f3d4aebd --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/App.java @@ -0,0 +1,38 @@ +package com.baeldung.blade.sample; + +import com.baeldung.blade.sample.interceptors.BaeldungMiddleware; +import com.blade.Blade; +import com.blade.event.EventType; +import com.blade.mvc.WebContext; +import com.blade.mvc.http.Session; + +public class App { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(App.class); + + public static void main(String[] args) { + + Blade.of() + .get("/", ctx -> ctx.render("index.html")) + .get("/basic-route-example", ctx -> ctx.text("GET called")) + .post("/basic-route-example", ctx -> ctx.text("POST called")) + .put("/basic-route-example", ctx -> ctx.text("PUT called")) + .delete("/basic-route-example", ctx -> ctx.text("DELETE called")) + .addStatics("/custom-static") + // .showFileList(true) + .enableCors(true) + .before("/user/*", ctx -> log.info("[NarrowedHook] Before '/user/*', URL called: " + ctx.uri())) + .on(EventType.SERVER_STARTED, e -> { + String version = WebContext.blade() + .env("app.version") + .orElse("N/D"); + log.info("[Event::serverStarted] Loading 'app.version' from configuration, value: " + version); + }) + .on(EventType.SESSION_CREATED, e -> { + Session session = (Session) e.attribute("session"); + session.attribute("mySessionValue", "Baeldung"); + }) + .use(new BaeldungMiddleware()) + .start(App.class, args); + } +} diff --git a/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java new file mode 100644 index 0000000000..339ba701f7 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java @@ -0,0 +1,37 @@ +package com.baeldung.blade.sample; + +import com.blade.mvc.annotation.GetRoute; +import com.blade.mvc.annotation.Path; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; +import com.blade.mvc.http.Session; + +@Path +public class AttributesExampleController { + + public final static String REQUEST_VALUE = "Some Request value"; + public final static String SESSION_VALUE = "1337"; + public final static String HEADER = "Some Header"; + + @GetRoute("/request-attribute-example") + public void getRequestAttribute(Request request, Response response) { + request.attribute("request-val", REQUEST_VALUE); + String requestVal = request.attribute("request-val"); + response.text(requestVal); + } + + @GetRoute("/session-attribute-example") + public void getSessionAttribute(Request request, Response response) { + Session session = request.session(); + session.attribute("session-val", SESSION_VALUE); + String sessionVal = session.attribute("session-val"); + response.text(sessionVal); + } + + @GetRoute("/header-example") + public void getHeader(Request request, Response response) { + String headerVal = request.header("a-header", HEADER); + response.header("a-header", headerVal); + } + +} diff --git a/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java new file mode 100644 index 0000000000..f0c22c70dd --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java @@ -0,0 +1,22 @@ +package com.baeldung.blade.sample; + +import com.blade.mvc.annotation.Path; +import com.blade.mvc.annotation.Route; +import com.blade.mvc.http.Response; + +@Path +public class LogExampleController { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleController.class); + + @Route(value = "/test-logs") + public void testLogs(Response response) { + log.trace("This is a TRACE Message"); + log.debug("This is a DEBUG Message"); + log.info("This is an INFO Message"); + log.warn("This is a WARN Message"); + log.error("This is an ERROR Message"); + response.text("Check in ./logs"); + } + +} diff --git a/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java new file mode 100644 index 0000000000..bc28244022 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java @@ -0,0 +1,71 @@ +package com.baeldung.blade.sample; + +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; + +import com.baeldung.blade.sample.vo.User; +import com.blade.mvc.annotation.CookieParam; +import com.blade.mvc.annotation.GetRoute; +import com.blade.mvc.annotation.HeaderParam; +import com.blade.mvc.annotation.JSON; +import com.blade.mvc.annotation.MultipartParam; +import com.blade.mvc.annotation.Param; +import com.blade.mvc.annotation.Path; +import com.blade.mvc.annotation.PathParam; +import com.blade.mvc.annotation.PostRoute; +import com.blade.mvc.http.Response; +import com.blade.mvc.multipart.FileItem; +import com.blade.mvc.ui.RestResponse; + +@Path +public class ParameterInjectionExampleController { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ParameterInjectionExampleController.class); + + @GetRoute("/params/form") + public void formParam(@Param String name, Response response) { + log.info("name: " + name); + response.text(name); + } + + @GetRoute("/params/path/:uid") + public void restfulParam(@PathParam Integer uid, Response response) { + log.info("uid: " + uid); + response.text(String.valueOf(uid)); + } + + @PostRoute("/params-file") // DO NOT USE A SLASH WITHIN THE ROUTE OR IT WILL BREAK (?) + @JSON + public RestResponse fileParam(@MultipartParam FileItem fileItem) throws Exception { + try { + byte[] fileContent = fileItem.getData(); + + log.debug("Saving the uploaded file"); + java.nio.file.Path tempFile = Files.createTempFile("baeldung_tempfiles", ".tmp"); + Files.write(tempFile, fileContent, StandardOpenOption.WRITE); + + return RestResponse.ok(); + } catch (Exception e) { + log.error(e.getMessage(), e); + return RestResponse.fail(e.getMessage()); + } + } + + @GetRoute("/params/header") + public void headerParam(@HeaderParam String customheader, Response response) { + log.info("Custom header: " + customheader); + response.text(customheader); + } + + @GetRoute("/params/cookie") + public void cookieParam(@CookieParam(defaultValue = "default value") String myCookie, Response response) { + log.info("myCookie: " + myCookie); + response.text(myCookie); + } + + @PostRoute("/params/vo") + public void voParam(@Param User user, Response response) { + log.info("user as voParam: " + user.toString()); + response.html(user.toString() + "

Back"); + } +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java new file mode 100644 index 0000000000..7ba2a270a9 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java @@ -0,0 +1,78 @@ +package com.baeldung.blade.sample; + +import com.baeldung.blade.sample.configuration.BaeldungException; +import com.blade.mvc.WebContext; +import com.blade.mvc.annotation.DeleteRoute; +import com.blade.mvc.annotation.GetRoute; +import com.blade.mvc.annotation.Path; +import com.blade.mvc.annotation.PostRoute; +import com.blade.mvc.annotation.PutRoute; +import com.blade.mvc.annotation.Route; +import com.blade.mvc.http.HttpMethod; +import com.blade.mvc.http.Request; +import com.blade.mvc.http.Response; + +@Path +public class RouteExampleController { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RouteExampleController.class); + + @GetRoute("/route-example") + public String get() { + return "get.html"; + } + + @PostRoute("/route-example") + public String post() { + return "post.html"; + } + + @PutRoute("/route-example") + public String put() { + return "put.html"; + } + + @DeleteRoute("/route-example") + public String delete() { + return "delete.html"; + } + + @Route(value = "/another-route-example", method = HttpMethod.GET) + public String anotherGet() { + return "get.html"; + } + + @Route(value = "/allmatch-route-example") + public String allmatch() { + return "allmatch.html"; + } + + @Route(value = "/triggerInternalServerError") + public void triggerInternalServerError() { + int x = 1 / 0; + } + + @Route(value = "/triggerBaeldungException") + public void triggerBaeldungException() throws BaeldungException { + throw new BaeldungException("Foobar Exception to threat differently"); + } + + @Route(value = "/user/foo") + public void urlCoveredByNarrowedWebhook(Response response) { + response.text("Check out for the WebHook covering '/user/*' in the logs"); + } + + @GetRoute("/load-configuration-in-a-route") + public void loadConfigurationInARoute(Response response) { + String authors = WebContext.blade() + .env("app.authors", "Unknown authors"); + log.info("[/load-configuration-in-a-route] Loading 'app.authors' from configuration, value: " + authors); + response.render("index.html"); + } + + @GetRoute("/template-output-test") + public void templateOutputTest(Request request, Response response) { + request.attribute("name", "Blade"); + response.render("template-output-test.html"); + } +} diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java new file mode 100644 index 0000000000..01a030b7e7 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java @@ -0,0 +1,9 @@ +package com.baeldung.blade.sample.configuration; + +public class BaeldungException extends RuntimeException { + + public BaeldungException(String message) { + super(message); + } + +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java new file mode 100644 index 0000000000..ab7b81c0dc --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java @@ -0,0 +1,25 @@ +package com.baeldung.blade.sample.configuration; + +import com.blade.ioc.annotation.Bean; +import com.blade.mvc.WebContext; +import com.blade.mvc.handler.DefaultExceptionHandler; + +@Bean +public class GlobalExceptionHandler extends DefaultExceptionHandler { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GlobalExceptionHandler.class); + + @Override + public void handle(Exception e) { + if (e instanceof BaeldungException) { + Exception baeldungException = (BaeldungException) e; + String msg = baeldungException.getMessage(); + log.error("[GlobalExceptionHandler] Intercepted an exception to threat with additional logic. Error message: " + msg); + WebContext.response() + .render("index.html"); + + } else { + super.handle(e); + } + } +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java new file mode 100644 index 0000000000..0f1aab1b52 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java @@ -0,0 +1,23 @@ +package com.baeldung.blade.sample.configuration; + +import com.blade.Blade; +import com.blade.ioc.annotation.Bean; +import com.blade.loader.BladeLoader; +import com.blade.mvc.WebContext; + +@Bean +public class LoadConfig implements BladeLoader { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoadConfig.class); + + @Override + public void load(Blade blade) { + String version = WebContext.blade() + .env("app.version") + .orElse("N/D"); + String authors = WebContext.blade() + .env("app.authors", "Unknown authors"); + + log.info("[LoadConfig] loaded 'app.version' (" + version + ") and 'app.authors' (" + authors + ") in a configuration bean"); + } +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java new file mode 100644 index 0000000000..c170975818 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java @@ -0,0 +1,15 @@ +package com.baeldung.blade.sample.configuration; + +import com.blade.ioc.annotation.Bean; +import com.blade.task.annotation.Schedule; + +@Bean +public class ScheduleExample { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ScheduleExample.class); + + @Schedule(name = "baeldungTask", cron = "0 */1 * * * ?") + public void runScheduledTask() { + log.info("[ScheduleExample] This is a scheduled Task running once per minute."); + } +} diff --git a/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java new file mode 100644 index 0000000000..4d0d178b0d --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java @@ -0,0 +1,17 @@ +package com.baeldung.blade.sample.interceptors; + +import com.blade.ioc.annotation.Bean; +import com.blade.mvc.RouteContext; +import com.blade.mvc.hook.WebHook; + +@Bean +public class BaeldungHook implements WebHook { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BaeldungHook.class); + + @Override + public boolean before(RouteContext ctx) { + log.info("[BaeldungHook] called before Route method"); + return true; + } +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java new file mode 100644 index 0000000000..3342cd8b01 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java @@ -0,0 +1,15 @@ +package com.baeldung.blade.sample.interceptors; + +import com.blade.mvc.RouteContext; +import com.blade.mvc.hook.WebHook; + +public class BaeldungMiddleware implements WebHook { + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BaeldungMiddleware.class); + + @Override + public boolean before(RouteContext context) { + log.info("[BaeldungMiddleware] called before Route method and other WebHooks"); + return true; + } +} \ No newline at end of file diff --git a/blade/src/main/java/com/baeldung/blade/sample/vo/User.java b/blade/src/main/java/com/baeldung/blade/sample/vo/User.java new file mode 100644 index 0000000000..b493dc3663 --- /dev/null +++ b/blade/src/main/java/com/baeldung/blade/sample/vo/User.java @@ -0,0 +1,16 @@ +package com.baeldung.blade.sample.vo; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +import lombok.Getter; +import lombok.Setter; + +public class User { + @Getter @Setter private String name; + @Getter @Setter private String site; + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } +} \ No newline at end of file diff --git a/blade/src/main/resources/application.properties b/blade/src/main/resources/application.properties new file mode 100644 index 0000000000..ebf365406a --- /dev/null +++ b/blade/src/main/resources/application.properties @@ -0,0 +1,5 @@ +mvc.statics.show-list=true +mvc.view.404=my-404.html +mvc.view.500=my-500.html +app.version=0.0.1 +app.authors=Andrea Ligios diff --git a/blade/src/main/resources/custom-static/icon.png b/blade/src/main/resources/custom-static/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..59af395afc55f38e5a727a119b4627088753c28e GIT binary patch literal 28893 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 literal 0 HcmV?d00001 diff --git a/blade/src/main/resources/static/app.css b/blade/src/main/resources/static/app.css new file mode 100644 index 0000000000..9fff13d9b6 --- /dev/null +++ b/blade/src/main/resources/static/app.css @@ -0,0 +1 @@ +/* App CSS */ \ No newline at end of file diff --git a/blade/src/main/resources/static/app.js b/blade/src/main/resources/static/app.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/blade/src/main/resources/static/file-upload.html b/blade/src/main/resources/static/file-upload.html new file mode 100644 index 0000000000..b805be81b1 --- /dev/null +++ b/blade/src/main/resources/static/file-upload.html @@ -0,0 +1,43 @@ + + + + +Title + + + + + +

File Upload and download test

+
+ + +
+ +
+ Back + + + + \ No newline at end of file diff --git a/blade/src/main/resources/static/user-post.html b/blade/src/main/resources/static/user-post.html new file mode 100644 index 0000000000..ccfc4e8d0b --- /dev/null +++ b/blade/src/main/resources/static/user-post.html @@ -0,0 +1,25 @@ + + + + +Title + + + + + +

User POJO post test

+ + +
+ Person POJO: + + + +
+ +
+ Back + + + \ No newline at end of file diff --git a/blade/src/main/resources/templates/allmatch.html b/blade/src/main/resources/templates/allmatch.html new file mode 100644 index 0000000000..7a4bfa070f --- /dev/null +++ b/blade/src/main/resources/templates/allmatch.html @@ -0,0 +1 @@ +ALLMATCH called \ No newline at end of file diff --git a/blade/src/main/resources/templates/delete.html b/blade/src/main/resources/templates/delete.html new file mode 100644 index 0000000000..1acb4b0b62 --- /dev/null +++ b/blade/src/main/resources/templates/delete.html @@ -0,0 +1 @@ +DELETE called \ No newline at end of file diff --git a/blade/src/main/resources/templates/get.html b/blade/src/main/resources/templates/get.html new file mode 100644 index 0000000000..2c37aa1058 --- /dev/null +++ b/blade/src/main/resources/templates/get.html @@ -0,0 +1 @@ +GET called \ No newline at end of file diff --git a/blade/src/main/resources/templates/index.html b/blade/src/main/resources/templates/index.html new file mode 100644 index 0000000000..6b7c2e77ad --- /dev/null +++ b/blade/src/main/resources/templates/index.html @@ -0,0 +1,30 @@ + + + + +Baeldung Blade App • Written by Andrea Ligios + + + +

Baeldung Blade App - Showcase

+ +

Manual tests

+

The following are tests which are not covered by integration tests, but that can be run manually in order to check the functionality, either in the browser or in the logs, depending on the case.

+ + + + +

Session value created in App.java

+

mySessionValue = ${mySessionValue}

+ + + + + \ No newline at end of file diff --git a/blade/src/main/resources/templates/my-404.html b/blade/src/main/resources/templates/my-404.html new file mode 100644 index 0000000000..0fa694f241 --- /dev/null +++ b/blade/src/main/resources/templates/my-404.html @@ -0,0 +1,10 @@ + + + + + 404 Not found + + + Custom Error 404 Page + + \ No newline at end of file diff --git a/blade/src/main/resources/templates/my-500.html b/blade/src/main/resources/templates/my-500.html new file mode 100644 index 0000000000..cc8438bfd6 --- /dev/null +++ b/blade/src/main/resources/templates/my-500.html @@ -0,0 +1,12 @@ + + + + + 500 Internal Server Error + + +

Custom Error 500 Page

+

The following error occurred: "${message}"

+
 ${stackTrace} 
+ + \ No newline at end of file diff --git a/blade/src/main/resources/templates/post.html b/blade/src/main/resources/templates/post.html new file mode 100644 index 0000000000..b7a8a931cd --- /dev/null +++ b/blade/src/main/resources/templates/post.html @@ -0,0 +1 @@ +POST called \ No newline at end of file diff --git a/blade/src/main/resources/templates/put.html b/blade/src/main/resources/templates/put.html new file mode 100644 index 0000000000..bdbe6d3285 --- /dev/null +++ b/blade/src/main/resources/templates/put.html @@ -0,0 +1 @@ +PUT called \ No newline at end of file diff --git a/blade/src/main/resources/templates/template-output-test.html b/blade/src/main/resources/templates/template-output-test.html new file mode 100644 index 0000000000..233b12fb88 --- /dev/null +++ b/blade/src/main/resources/templates/template-output-test.html @@ -0,0 +1 @@ +

Hello, ${name}!

\ No newline at end of file diff --git a/blade/src/test/java/com/baeldung/blade/sample/AppLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/AppLiveTest.java new file mode 100644 index 0000000000..1172e6755f --- /dev/null +++ b/blade/src/test/java/com/baeldung/blade/sample/AppLiveTest.java @@ -0,0 +1,56 @@ +package com.baeldung.blade.sample; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +public class AppLiveTest { + + @Test + public void givenBasicRoute_whenGet_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/basic-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called"); + } + } + + @Test + public void givenBasicRoute_whenPost_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPost("http://localhost:9000/basic-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("POST called"); + } + } + + @Test + public void givenBasicRoute_whenPut_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPut("http://localhost:9000/basic-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("PUT called"); + } + } + + @Test + public void givenBasicRoute_whenDelete_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpDelete("http://localhost:9000/basic-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("DELETE called"); + } + } +} diff --git a/blade/src/test/java/com/baeldung/blade/sample/AttributesExampleControllerLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/AttributesExampleControllerLiveTest.java new file mode 100644 index 0000000000..7cf00c2d4b --- /dev/null +++ b/blade/src/test/java/com/baeldung/blade/sample/AttributesExampleControllerLiveTest.java @@ -0,0 +1,55 @@ +package com.baeldung.blade.sample; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +public class AttributesExampleControllerLiveTest { + + @Test + public void givenRequestAttribute_whenSet_thenRetrieveWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/request-attribute-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo(AttributesExampleController.REQUEST_VALUE); + } + } + + @Test + public void givenSessionAttribute_whenSet_thenRetrieveWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/session-attribute-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo(AttributesExampleController.SESSION_VALUE); + } + } + + @Test + public void givenHeader_whenSet_thenRetrieveWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/header-example"); + request.addHeader("a-header","foobar"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(httpResponse.getHeaders("a-header")[0].getValue()).isEqualTo("foobar"); + } + } + + @Test + public void givenNoHeader_whenSet_thenRetrieveDefaultValueWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/header-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(httpResponse.getHeaders("a-header")[0].getValue()).isEqualTo(AttributesExampleController.HEADER); + } + } + +} diff --git a/blade/src/test/java/com/baeldung/blade/sample/ParameterInjectionExampleControllerLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/ParameterInjectionExampleControllerLiveTest.java new file mode 100644 index 0000000000..fbd5280116 --- /dev/null +++ b/blade/src/test/java/com/baeldung/blade/sample/ParameterInjectionExampleControllerLiveTest.java @@ -0,0 +1,82 @@ +package com.baeldung.blade.sample; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +public class ParameterInjectionExampleControllerLiveTest { + + @Test + public void givenFormParam_whenSet_thenRetrieveWithGet() throws Exception { + URIBuilder builder = new URIBuilder("http://localhost:9000/params/form"); + builder.setParameter("name", "Andrea Ligios"); + + final HttpUriRequest request = new HttpGet(builder.build()); + + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("Andrea Ligios"); + } + } + + @Test + public void givenPathParam_whenSet_thenRetrieveWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/params/path/1337"); + + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("1337"); + } + } + + // @Test + // public void givenFileParam_whenSet_thenRetrieveWithGet() throws Exception { + // + // byte[] data = "this is some temp file content".getBytes("UTF-8"); + // java.nio.file.Path tempFile = Files.createTempFile("baeldung_test_tempfiles", ".tmp"); + // Files.write(tempFile, data, StandardOpenOption.WRITE); + // + // //HttpEntity entity = MultipartEntityBuilder.create().addPart("file", new FileBody(tempFile.toFile())).build(); + // HttpEntity entity = MultipartEntityBuilder.create().addTextBody("field1", "value1") + // .addBinaryBody("fileItem", tempFile.toFile(), ContentType.create("application/octet-stream"), "file1.txt").build(); + // + // final HttpPost post = new HttpPost("http://localhost:9000/params-file"); + // post.setEntity(entity); + // + // try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create().build().execute(post);) { + // assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("file1.txt"); + // } + // } + + @Test + public void givenHeader_whenSet_thenRetrieveWithGet() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/params/header"); + request.addHeader("customheader", "foobar"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("foobar"); + } + } + + @Test + public void givenNoCookie_whenCalled_thenReadDefaultValue() throws Exception { + + final HttpUriRequest request = new HttpGet("http://localhost:9000/params/cookie"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("default value"); + } + + } + +} diff --git a/blade/src/test/java/com/baeldung/blade/sample/RouteExampleControllerLiveTest.java b/blade/src/test/java/com/baeldung/blade/sample/RouteExampleControllerLiveTest.java new file mode 100644 index 0000000000..df8e70c461 --- /dev/null +++ b/blade/src/test/java/com/baeldung/blade/sample/RouteExampleControllerLiveTest.java @@ -0,0 +1,117 @@ +package com.baeldung.blade.sample; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +public class RouteExampleControllerLiveTest { + + @Test + public void givenRoute_whenGet_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called"); + } + } + + @Test + public void givenRoute_whenPost_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPost("http://localhost:9000/route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("POST called"); + } + } + + @Test + public void givenRoute_whenPut_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPut("http://localhost:9000/route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("PUT called"); + } + } + + @Test + public void givenRoute_whenDelete_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpDelete("http://localhost:9000/route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("DELETE called"); + } + } + + @Test + public void givenAnotherRoute_whenGet_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/another-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called"); + } + } + + @Test + public void givenAllMatchRoute_whenGet_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/allmatch-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called"); + } + } + + @Test + public void givenAllMatchRoute_whenPost_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPost("http://localhost:9000/allmatch-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called"); + } + } + + @Test + public void givenAllMatchRoute_whenPut_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpPut("http://localhost:9000/allmatch-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called"); + } + } + + @Test + public void givenAllMatchRoute_whenDelete_thenCorrectOutput() throws Exception { + final HttpUriRequest request = new HttpDelete("http://localhost:9000/allmatch-route-example"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called"); + } + } + + @Test + public void givenRequestAttribute_whenRenderedWithTemplate_thenCorrectlyEvaluateIt() throws Exception { + final HttpUriRequest request = new HttpGet("http://localhost:9000/template-output-test"); + try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create() + .build() + .execute(request);) { + assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("

Hello, Blade!

"); + } + } + +} diff --git a/pom.xml b/pom.xml index 1c0738cafb..d084d0f7af 100644 --- a/pom.xml +++ b/pom.xml @@ -367,6 +367,8 @@ axon azure + blade + bootique cas/cas-secured-app From f2d26dfa38941c9088883ebfc6fd6c5f0877f736 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 23 Jan 2019 17:45:07 -0700 Subject: [PATCH 130/190] Move new code under different module --- pom.xml | 1 - .../scheduling/ScheduleJobsByProfile.java | 0 .../com/baeldung/scheduling/ScheduledJob.java | 0 .../scheduling/ScheduledJobsWithBoolean.java | 0 .../ScheduledJobsWithConditional.java | 0 .../ScheduledJobsWithExpression.java | 0 .../scheduling/SchedulingApplication.java | 0 spring-scheduling/.gitignore | 25 -- .../.mvn/wrapper/maven-wrapper.jar | Bin 48337 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 1 - spring-scheduling/mvnw | 286 ------------------ spring-scheduling/mvnw.cmd | 161 ---------- spring-scheduling/pom.xml | 42 --- .../src/main/resources/application.properties | 0 .../SchedulingApplicationTests.java | 17 -- 15 files changed, 533 deletions(-) rename {spring-scheduling => spring-boot-mvc}/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java (100%) rename {spring-scheduling => spring-boot-mvc}/src/main/java/com/baeldung/scheduling/ScheduledJob.java (100%) rename {spring-scheduling => spring-boot-mvc}/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java (100%) rename {spring-scheduling => spring-boot-mvc}/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java (100%) rename {spring-scheduling => spring-boot-mvc}/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java (100%) rename {spring-scheduling => spring-boot-mvc}/src/main/java/com/baeldung/scheduling/SchedulingApplication.java (100%) delete mode 100644 spring-scheduling/.gitignore delete mode 100644 spring-scheduling/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-scheduling/.mvn/wrapper/maven-wrapper.properties delete mode 100755 spring-scheduling/mvnw delete mode 100644 spring-scheduling/mvnw.cmd delete mode 100644 spring-scheduling/pom.xml delete mode 100644 spring-scheduling/src/main/resources/application.properties delete mode 100644 spring-scheduling/src/test/java/com/baeldung/scheduling/SchedulingApplicationTests.java diff --git a/pom.xml b/pom.xml index 1f25dd0691..1dd2768793 100644 --- a/pom.xml +++ b/pom.xml @@ -714,7 +714,6 @@ spring-rest-simple spring-resttemplate spring-roo - spring-scheduling spring-security-acl spring-security-angular/server spring-security-cache-control diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java similarity index 100% rename from spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java rename to spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduleJobsByProfile.java diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJob.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJob.java similarity index 100% rename from spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJob.java rename to spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJob.java diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java similarity index 100% rename from spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java rename to spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithBoolean.java diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java similarity index 100% rename from spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java rename to spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithConditional.java diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java similarity index 100% rename from spring-scheduling/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java rename to spring-boot-mvc/src/main/java/com/baeldung/scheduling/ScheduledJobsWithExpression.java diff --git a/spring-scheduling/src/main/java/com/baeldung/scheduling/SchedulingApplication.java b/spring-boot-mvc/src/main/java/com/baeldung/scheduling/SchedulingApplication.java similarity index 100% rename from spring-scheduling/src/main/java/com/baeldung/scheduling/SchedulingApplication.java rename to spring-boot-mvc/src/main/java/com/baeldung/scheduling/SchedulingApplication.java diff --git a/spring-scheduling/.gitignore b/spring-scheduling/.gitignore deleted file mode 100644 index 82eca336e3..0000000000 --- a/spring-scheduling/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -/target/ -!.mvn/wrapper/maven-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/build/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ \ No newline at end of file diff --git a/spring-scheduling/.mvn/wrapper/maven-wrapper.jar b/spring-scheduling/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997377a393fd672c7dcde9dccbedf0cb1e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48337 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 \(.*\)$'` - 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 Mingw, 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 - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# 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"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -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} $MAVEN_CONFIG "$@" diff --git a/spring-scheduling/mvnw.cmd b/spring-scheduling/mvnw.cmd deleted file mode 100644 index e5cfb0ae9e..0000000000 --- a/spring-scheduling/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@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 set title of command window -title %0 -@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 - -@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="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -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% diff --git a/spring-scheduling/pom.xml b/spring-scheduling/pom.xml deleted file mode 100644 index d739985f7c..0000000000 --- a/spring-scheduling/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.1.2.RELEASE - - - com.baeldung - scheduling - 0.0.1-SNAPSHOT - scheduling - Example of conditionally enabling spring scheduled jobs - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/spring-scheduling/src/main/resources/application.properties b/spring-scheduling/src/main/resources/application.properties deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/spring-scheduling/src/test/java/com/baeldung/scheduling/SchedulingApplicationTests.java b/spring-scheduling/src/test/java/com/baeldung/scheduling/SchedulingApplicationTests.java deleted file mode 100644 index 60e6d820bb..0000000000 --- a/spring-scheduling/src/test/java/com/baeldung/scheduling/SchedulingApplicationTests.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.scheduling; - -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 SchedulingApplicationTests { - - @Test - public void contextLoads() { - } - -} - From 24cf6b473d903256b1d906305b47e2f9c88ca066 Mon Sep 17 00:00:00 2001 From: Diego Moreira Date: Thu, 24 Jan 2019 21:32:29 -0300 Subject: [PATCH 131/190] BAEL-2270 Refactor - Moved classes from libraries to libraries-server (#6210) --- libraries-server/pom.xml | 25 +++++++++++++++++++ .../java/com/baeldung/smack/StanzaThread.java | 0 .../baeldung/smack/SmackIntegrationTest.java | 0 libraries/pom.xml | 24 ------------------ 4 files changed, 25 insertions(+), 24 deletions(-) rename {libraries => libraries-server}/src/main/java/com/baeldung/smack/StanzaThread.java (100%) rename {libraries => libraries-server}/src/test/java/com/baeldung/smack/SmackIntegrationTest.java (100%) diff --git a/libraries-server/pom.xml b/libraries-server/pom.xml index 661f5f01d5..f60e664fa7 100644 --- a/libraries-server/pom.xml +++ b/libraries-server/pom.xml @@ -71,6 +71,30 @@ tomcat-catalina ${tomcat.version} + + + org.igniterealtime.smack + smack-tcp + ${smack.version} + + + + org.igniterealtime.smack + smack-im + ${smack.version} + + + + org.igniterealtime.smack + smack-extensions + ${smack.version} + + + + org.igniterealtime.smack + smack-java7 + ${smack.version} + @@ -82,6 +106,7 @@ 4.1 4.12 8.5.24 + 4.3.1 \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/smack/StanzaThread.java b/libraries-server/src/main/java/com/baeldung/smack/StanzaThread.java similarity index 100% rename from libraries/src/main/java/com/baeldung/smack/StanzaThread.java rename to libraries-server/src/main/java/com/baeldung/smack/StanzaThread.java diff --git a/libraries/src/test/java/com/baeldung/smack/SmackIntegrationTest.java b/libraries-server/src/test/java/com/baeldung/smack/SmackIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/smack/SmackIntegrationTest.java rename to libraries-server/src/test/java/com/baeldung/smack/SmackIntegrationTest.java diff --git a/libraries/pom.xml b/libraries/pom.xml index 301fa86c8d..d067525315 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -676,29 +676,6 @@ test - - org.igniterealtime.smack - smack-tcp - ${smack.version} - - - - org.igniterealtime.smack - smack-im - ${smack.version} - - - - org.igniterealtime.smack - smack-extensions - ${smack.version} - - - - org.igniterealtime.smack - smack-java7 - ${smack.version} - @@ -920,7 +897,6 @@ 1.1.0 2.7.1 3.6 - 4.3.1
From 4c540b764c9911a1e7f90cd01eea7087a9c170cd Mon Sep 17 00:00:00 2001 From: jose Date: Thu, 24 Jan 2019 23:04:56 -0300 Subject: [PATCH 132/190] Moving classes into core-java-lang --- .../baeldung/scope/BracketScopeExample.java | 14 -------------- .../com/baeldung/scope/ClassScopeExample.java | 14 -------------- .../com/baeldung/scope/LoopScopeExample.java | 18 ------------------ .../com/baeldung/scope/MethodScopeExample.java | 13 ------------- .../baeldung/scope/NestedScopesExample.java | 12 ------------ 5 files changed, 71 deletions(-) delete mode 100644 core-java/src/main/java/com/baeldung/scope/BracketScopeExample.java delete mode 100644 core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java delete mode 100644 core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java delete mode 100644 core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java delete mode 100644 core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java diff --git a/core-java/src/main/java/com/baeldung/scope/BracketScopeExample.java b/core-java/src/main/java/com/baeldung/scope/BracketScopeExample.java deleted file mode 100644 index 37ae211dcb..0000000000 --- a/core-java/src/main/java/com/baeldung/scope/BracketScopeExample.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.baeldung.variable.scope.examples; - -public class BracketScopeExample { - - public void mathOperationExample() { - Integer sum = 0; - { - Integer number = 2; - sum = sum + number; - } - // compiler error, number cannot be solved as a variable - // number++; - } -} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java b/core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java deleted file mode 100644 index 241c6b466e..0000000000 --- a/core-java/src/main/java/com/baeldung/scope/ClassScopeExample.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.baeldung.variable.scope.examples; - -public class ClassScopeExample { - - Integer amount = 0; - - public void exampleMethod() { - amount++; - } - - public void anotherExampleMethod() { - Integer anotherAmount = amount + 4; - } -} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java b/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java deleted file mode 100644 index 7bf92a6d26..0000000000 --- a/core-java/src/main/java/com/baeldung/scope/LoopScopeExample.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.baeldung.variable.scope.examples; - -import java.util.Arrays; -import java.util.List; - -public class LoopScopeExample { - - List listOfNames = Arrays.asList("Joe", "Susan", "Pattrick"); - - public void iterationOfNames() { - String allNames = ""; - for (String name : listOfNames) { - allNames = allNames + " " + name; - } - // compiler error, name cannot be resolved to a variable - // String lastNameUsed = name; - } -} diff --git a/core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java b/core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java deleted file mode 100644 index e62c6a2a1c..0000000000 --- a/core-java/src/main/java/com/baeldung/scope/MethodScopeExample.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.variable.scope.examples; - -public class MethodScopeExample { - - public void methodA() { - Integer area = 2; - } - - public void methodB() { - // compiler error, area cannot be resolved to a variable - // area = area + 2; - } -} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java b/core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java deleted file mode 100644 index fcd23e5ae0..0000000000 --- a/core-java/src/main/java/com/baeldung/scope/NestedScopesExample.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.baeldung.variable.scope.examples; - -public class NestedScopesExample { - - String title = "Baeldung"; - - public void printTitle() { - System.out.println(title); - String title = "John Doe"; - System.out.println(title); - } -} \ No newline at end of file From ca5ff8ac8c70ea1f12148b363ce1a83824131c07 Mon Sep 17 00:00:00 2001 From: jose Date: Thu, 24 Jan 2019 23:06:51 -0300 Subject: [PATCH 133/190] Moving classes into core-java-lang --- .../baeldung/scope/BracketScopeExample.java | 14 ++++++++++++++ .../com/baeldung/scope/ClassScopeExample.java | 14 ++++++++++++++ .../com/baeldung/scope/LoopScopeExample.java | 18 ++++++++++++++++++ .../com/baeldung/scope/MethodScopeExample.java | 13 +++++++++++++ .../baeldung/scope/NestedScopesExample.java | 12 ++++++++++++ 5 files changed, 71 insertions(+) create mode 100644 core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java create mode 100644 core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java create mode 100644 core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java create mode 100644 core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java create mode 100644 core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java diff --git a/core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java b/core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java new file mode 100644 index 0000000000..37ae211dcb --- /dev/null +++ b/core-java-lang/src/main/java/com/baeldung/scope/BracketScopeExample.java @@ -0,0 +1,14 @@ +package org.baeldung.variable.scope.examples; + +public class BracketScopeExample { + + public void mathOperationExample() { + Integer sum = 0; + { + Integer number = 2; + sum = sum + number; + } + // compiler error, number cannot be solved as a variable + // number++; + } +} \ No newline at end of file diff --git a/core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java b/core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java new file mode 100644 index 0000000000..241c6b466e --- /dev/null +++ b/core-java-lang/src/main/java/com/baeldung/scope/ClassScopeExample.java @@ -0,0 +1,14 @@ +package org.baeldung.variable.scope.examples; + +public class ClassScopeExample { + + Integer amount = 0; + + public void exampleMethod() { + amount++; + } + + public void anotherExampleMethod() { + Integer anotherAmount = amount + 4; + } +} \ No newline at end of file diff --git a/core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java b/core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java new file mode 100644 index 0000000000..7bf92a6d26 --- /dev/null +++ b/core-java-lang/src/main/java/com/baeldung/scope/LoopScopeExample.java @@ -0,0 +1,18 @@ +package org.baeldung.variable.scope.examples; + +import java.util.Arrays; +import java.util.List; + +public class LoopScopeExample { + + List listOfNames = Arrays.asList("Joe", "Susan", "Pattrick"); + + public void iterationOfNames() { + String allNames = ""; + for (String name : listOfNames) { + allNames = allNames + " " + name; + } + // compiler error, name cannot be resolved to a variable + // String lastNameUsed = name; + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java b/core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java new file mode 100644 index 0000000000..e62c6a2a1c --- /dev/null +++ b/core-java-lang/src/main/java/com/baeldung/scope/MethodScopeExample.java @@ -0,0 +1,13 @@ +package org.baeldung.variable.scope.examples; + +public class MethodScopeExample { + + public void methodA() { + Integer area = 2; + } + + public void methodB() { + // compiler error, area cannot be resolved to a variable + // area = area + 2; + } +} \ No newline at end of file diff --git a/core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java b/core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java new file mode 100644 index 0000000000..fcd23e5ae0 --- /dev/null +++ b/core-java-lang/src/main/java/com/baeldung/scope/NestedScopesExample.java @@ -0,0 +1,12 @@ +package org.baeldung.variable.scope.examples; + +public class NestedScopesExample { + + String title = "Baeldung"; + + public void printTitle() { + System.out.println(title); + String title = "John Doe"; + System.out.println(title); + } +} \ No newline at end of file From ae344b37ec7d7c0ed2cb0141e96c9811ad4eea71 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Fri, 25 Jan 2019 09:51:15 +0400 Subject: [PATCH 134/190] move the code into core-java-collections-lists module --- core-java-arrays/pom.xml | 16 ---------- core-java-collections-list/pom.xml | 29 +++++++++++++++++++ .../list/primitive}/PrimitiveCollections.java | 2 +- .../primitive}/PrimitivesListPerformance.java | 3 +- 4 files changed, 31 insertions(+), 19 deletions(-) rename {core-java-arrays/src/main/java/com/baeldung/array => core-java-collections-list/src/main/java/com/baeldung/list/primitive}/PrimitiveCollections.java (95%) rename {core-java-arrays/src/main/java/com/baeldung/array => core-java-collections-list/src/main/java/com/baeldung/list/primitive}/PrimitivesListPerformance.java (97%) diff --git a/core-java-arrays/pom.xml b/core-java-arrays/pom.xml index 6d4109804e..d2d0453e87 100644 --- a/core-java-arrays/pom.xml +++ b/core-java-arrays/pom.xml @@ -52,22 +52,6 @@ spring-web ${springframework.spring-web.version} - - - net.sf.trove4j - trove4j - 3.0.2 - - - it.unimi.dsi - fastutil - 8.1.0 - - - colt - colt - 1.2.0 - diff --git a/core-java-collections-list/pom.xml b/core-java-collections-list/pom.xml index ee99e470d0..bc71882683 100644 --- a/core-java-collections-list/pom.xml +++ b/core-java-collections-list/pom.xml @@ -36,6 +36,33 @@ ${lombok.version} provided + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-generator-annprocess.version} + + + + net.sf.trove4j + trove4j + 3.0.2 + + + it.unimi.dsi + fastutil + 8.1.0 + + + colt + colt + 1.2.0 + @@ -44,5 +71,7 @@ 1.7.0 3.11.1 1.16.12 + 1.19 + 1.19 diff --git a/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java similarity index 95% rename from core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java rename to core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java index 85f4dd2498..d6da32d899 100644 --- a/core-java-arrays/src/main/java/com/baeldung/array/PrimitiveCollections.java +++ b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java @@ -1,4 +1,4 @@ -package com.baeldung.array; +package com.baeldung.list.primitive; import com.google.common.primitives.ImmutableIntArray; import com.google.common.primitives.Ints; diff --git a/core-java-arrays/src/main/java/com/baeldung/array/PrimitivesListPerformance.java b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java similarity index 97% rename from core-java-arrays/src/main/java/com/baeldung/array/PrimitivesListPerformance.java rename to core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java index 9db3a75574..f57c8d65a6 100644 --- a/core-java-arrays/src/main/java/com/baeldung/array/PrimitivesListPerformance.java +++ b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java @@ -1,4 +1,4 @@ -package com.baeldung.array; +package com.baeldung.list.primitive; import it.unimi.dsi.fastutil.ints.IntArrayList; import gnu.trove.list.array.TIntArrayList; @@ -9,7 +9,6 @@ import org.openjdk.jmh.runner.options.OptionsBuilder; import java.util.ArrayList; import java.util.List; -import java.util.Random; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) From 2f5ef3480b97cea30ec57dafb9370a114f9f8b18 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Fri, 25 Jan 2019 10:54:59 +0400 Subject: [PATCH 135/190] remove Ints examples --- .../com/baeldung/list/primitive/PrimitiveCollections.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java index d6da32d899..5a8ddc0acd 100644 --- a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java +++ b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java @@ -20,13 +20,5 @@ public class PrimitiveCollections { ImmutableIntArray immutableIntArray = ImmutableIntArray.builder().addAll(primitives).build(); System.out.println(immutableIntArray); - - List list = Ints.asList(primitives); - - int[] primitiveArray = Ints.toArray(list); - - int[] concatenated = Ints.concat(primitiveArray, primitives); - - System.out.println(Arrays.toString(concatenated)); } } From 1293f4e17232fd39d3eb5dd97b141bd98b934533 Mon Sep 17 00:00:00 2001 From: Loredana Date: Fri, 25 Jan 2019 22:40:12 +0200 Subject: [PATCH 136/190] update boot dependencies, config --- spring-boot-rest/pom.xml | 27 ++++---------- .../baeldung/spring/PersistenceConfig.java | 1 - .../java/com/baeldung/spring/WebConfig.java | 35 +------------------ .../resources/springDataPersistenceConfig.xml | 12 ------- 4 files changed, 7 insertions(+), 68 deletions(-) delete mode 100644 spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index bcd0381603..cf4ac0371b 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -25,31 +25,16 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml - - org.hibernate - hibernate-entitymanager - - - org.springframework - spring-jdbc - - - org.springframework.data - spring-data-jpa - + com.h2database h2 - - org.springframework - spring-tx - - - org.springframework.data - spring-data-commons - - + + org.springframework.boot + spring-boot-starter-data-jpa + + diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java index 4a4b9eee3f..5179c66978 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java @@ -25,7 +25,6 @@ import com.google.common.base.Preconditions; @EnableTransactionManagement @PropertySource({ "classpath:persistence-${envTarget:h2}.properties" }) @ComponentScan({ "com.baeldung.persistence" }) -// @ImportResource("classpath*:springDataPersistenceConfig.xml") @EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao") public class PersistenceConfig { diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java index 39aade174b..80ee975e84 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -1,43 +1,10 @@ package com.baeldung.spring; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; 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.WebMvcConfigurer; -import org.springframework.web.servlet.view.InternalResourceViewResolver; + @Configuration -@ComponentScan("com.baeldung.web") -@EnableWebMvc public class WebConfig implements WebMvcConfigurer { - public WebConfig() { - super(); - } - - @Bean - public ViewResolver viewResolver() { - final InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); - viewResolver.setPrefix("/WEB-INF/view/"); - viewResolver.setSuffix(".jsp"); - return viewResolver; - } - - // API - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - registry.addViewController("/graph.html"); - registry.addViewController("/homepage.html"); - } - - @Override - public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { - configurer.defaultContentType(MediaType.APPLICATION_JSON); - } - } \ No newline at end of file diff --git a/spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml b/spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml deleted file mode 100644 index 5ea2d9c05b..0000000000 --- a/spring-boot-rest/src/main/resources/springDataPersistenceConfig.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file From 06023ec09f889214970fdc9615325e92f14769b3 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sat, 26 Jan 2019 06:45:40 +0530 Subject: [PATCH 137/190] Feature/bael 2129 (#6182) * BAEL-2129 Added Unit test for Void Type in Kotlin article * BAEL-2129 Updated test case * BAEL-2129 Added comment for commented code --- .../com/baeldung/voidtypes/VoidTypesUnitTest.kt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt index 5c285c3135..468352dbed 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt @@ -6,7 +6,19 @@ import kotlin.test.assertTrue class VoidTypesUnitTest { - fun returnTypeAsVoid(): Void? { + // Un-commenting below methods will result into compilation error + // as the syntax used is incorrect and is used for explanation in tutorial. + + // fun returnTypeAsVoidAttempt1(): Void { + // println("Trying with Void as return type") + // } + + // fun returnTypeAsVoidAttempt2(): Void { + // println("Trying with Void as return type") + // return null + // } + + fun returnTypeAsVoidSuccess(): Void? { println("Function can have Void as return type") return null } @@ -36,7 +48,7 @@ class VoidTypesUnitTest { @Test fun givenVoidReturnType_thenReturnsNullOnly() { - assertNull(returnTypeAsVoid()) + assertNull(returnTypeAsVoidSuccess()) } @Test From c6e808348ddbcb70a90045db7b86affdf6ad9e38 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 26 Jan 2019 10:41:54 +0200 Subject: [PATCH 138/190] Update README.md --- spring-cloud/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-cloud/README.md b/spring-cloud/README.md index eb2e46c3d0..fede3cc12d 100644 --- a/spring-cloud/README.md +++ b/spring-cloud/README.md @@ -15,8 +15,6 @@ ### Relevant Articles: - [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) -- [Using a Spring Cloud App Starter](http://www.baeldung.com/using-a-spring-cloud-app-starter) -- [Using a Spring Cloud App Starter](http://www.baeldung.com/spring-cloud-app-starter) - [Instance Profile Credentials using Spring Cloud](http://www.baeldung.com/spring-cloud-instance-profiles) - [Running Spring Boot Applications With Minikube](http://www.baeldung.com/spring-boot-minikube) From 2437a265006e4f7a485952d254058914bd2d8d0f Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 26 Jan 2019 10:42:34 +0200 Subject: [PATCH 139/190] Create README.md --- spring-cloud/spring-cloud-stream-starters/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 spring-cloud/spring-cloud-stream-starters/README.md diff --git a/spring-cloud/spring-cloud-stream-starters/README.md b/spring-cloud/spring-cloud-stream-starters/README.md new file mode 100644 index 0000000000..761d54abbd --- /dev/null +++ b/spring-cloud/spring-cloud-stream-starters/README.md @@ -0,0 +1,3 @@ +#Revelant Articles: + +- [Using a Spring Cloud App Starter](http://www.baeldung.com/spring-cloud-app-starter) From 630d07277e7851ef2c4b5952ac2206f5fe57107d Mon Sep 17 00:00:00 2001 From: eric-martin Date: Sat, 26 Jan 2019 15:25:41 -0600 Subject: [PATCH 140/190] BAEL-2406: Improve asserts in PassengerRepositoryIntegrationTest --- .../PassengerRepositoryIntegrationTest.java | 70 +++++++++++-------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java index 59380c1427..8cd19cec03 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java @@ -1,5 +1,17 @@ package com.baeldung.passenger; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.Optional; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -12,16 +24,6 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.test.context.junit4.SpringRunner; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import java.util.List; -import java.util.Optional; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - @DataJpaTest @RunWith(SpringRunner.class) public class PassengerRepositoryIntegrationTest { @@ -49,7 +51,7 @@ public class PassengerRepositoryIntegrationTest { assertEquals(1, passengers.size()); Passenger actual = passengers.get(0); - assertEquals(actual, expected); + assertEquals(expected, actual); } @Test @@ -58,7 +60,7 @@ public class PassengerRepositoryIntegrationTest { Passenger actual = repository.findFirstByOrderBySeatNumberAsc(); - assertEquals(actual, expected); + assertEquals(expected, actual); } @Test @@ -68,7 +70,7 @@ public class PassengerRepositoryIntegrationTest { Page page = repository.findAll(PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber"))); - assertEquals(page.getContent().size(), 1); + assertEquals(1, page.getContent().size()); Passenger actual = page.getContent().get(0); assertEquals(expected, actual); @@ -107,7 +109,7 @@ public class PassengerRepositoryIntegrationTest { Optional actual = repository.findOne(example); assertTrue(actual.isPresent()); - assertEquals(actual.get(), Passenger.from("Fred", "Bloggs", 22)); + assertEquals(Passenger.from("Fred", "Bloggs", 22), actual.get()); } @Test @@ -119,7 +121,7 @@ public class PassengerRepositoryIntegrationTest { Optional actual = repository.findOne(example); assertTrue(actual.isPresent()); - assertEquals(actual.get(), Passenger.from("Fred", "Bloggs", 22)); + assertEquals(Passenger.from("Fred", "Bloggs", 22), actual.get()); } @Test @@ -128,6 +130,7 @@ public class PassengerRepositoryIntegrationTest { Passenger eve = Passenger.from("Eve", "Jackson", 95); Passenger fred = Passenger.from("Fred", "Bloggs", 22); Passenger siya = Passenger.from("Siya", "Kolisi", 85); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); ExampleMatcher customExampleMatcher = ExampleMatcher.matchingAny().withMatcher("firstName", ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase()).withMatcher("lastName", @@ -139,21 +142,28 @@ public class PassengerRepositoryIntegrationTest { List passengers = repository.findAll(example); assertThat(passengers, contains(jill, eve, fred, siya)); + assertThat(passengers, not(contains(ricki))); } -@Test -public void givenPassengers_whenFindByIgnoringMatcher_thenExpectedReturned() { - Passenger fred = Passenger.from("Fred", "Bloggs", 22); - Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); - - ExampleMatcher ignoringExampleMatcher = ExampleMatcher.matchingAny().withMatcher("lastName", - ExampleMatcher.GenericPropertyMatchers.startsWith().ignoreCase()).withIgnorePaths("firstName", "seatNumber"); - - Example example = Example.of(Passenger.from(null, "b", null), - ignoringExampleMatcher); - - List passengers = repository.findAll(example); - - assertThat(passengers, contains(fred, ricki)); -} + @Test + public void givenPassengers_whenFindByIgnoringMatcher_thenExpectedReturned() { + Passenger jill = Passenger.from("Jill", "Smith", 50); + Passenger eve = Passenger.from("Eve", "Jackson", 95); + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger siya = Passenger.from("Siya", "Kolisi", 85); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); + + ExampleMatcher ignoringExampleMatcher = ExampleMatcher.matchingAny().withMatcher("lastName", + ExampleMatcher.GenericPropertyMatchers.startsWith().ignoreCase()).withIgnorePaths("firstName", "seatNumber"); + + Example example = Example.of(Passenger.from(null, "b", null), + ignoringExampleMatcher); + + List passengers = repository.findAll(example); + + assertThat(passengers, contains(fred, ricki)); + assertThat(passengers, not(contains(jill))); + assertThat(passengers, not(contains(eve))); + assertThat(passengers, not(contains(siya))); + } } From 9a567f95b4be0737af8a9a0cd2b02e09d793bc54 Mon Sep 17 00:00:00 2001 From: PranayVJain Date: Sun, 27 Jan 2019 11:51:13 +0530 Subject: [PATCH 141/190] List files within directory Issue: BAEL-2447 --- .../java/com/baeldung/files/ListFiles.java | 64 +++++++++++++++++++ .../com/baeldung/file/ListFilesUnitTest.java | 46 +++++++++++++ .../listFilesUnitTestFolder/country.txt | 1 + .../listFilesUnitTestFolder/employee.json | 1 + .../listFilesUnitTestFolder/students.json | 1 + .../listFilesUnitTestFolder/test.xml | 1 + 6 files changed, 114 insertions(+) create mode 100644 core-java-io/src/main/java/com/baeldung/files/ListFiles.java create mode 100644 core-java-io/src/test/java/com/baeldung/file/ListFilesUnitTest.java create mode 100644 core-java-io/src/test/resources/listFilesUnitTestFolder/country.txt create mode 100644 core-java-io/src/test/resources/listFilesUnitTestFolder/employee.json create mode 100644 core-java-io/src/test/resources/listFilesUnitTestFolder/students.json create mode 100644 core-java-io/src/test/resources/listFilesUnitTestFolder/test.xml diff --git a/core-java-io/src/main/java/com/baeldung/files/ListFiles.java b/core-java-io/src/main/java/com/baeldung/files/ListFiles.java new file mode 100644 index 0000000000..c5de36270c --- /dev/null +++ b/core-java-io/src/main/java/com/baeldung/files/ListFiles.java @@ -0,0 +1,64 @@ +package com.baeldung.files; + +import java.io.File; +import java.io.IOException; +import java.nio.file.DirectoryStream; +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.attribute.BasicFileAttributes; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ListFiles { + public static final int DEPTH = 1; + + public Set listFilesUsingJavaIO(String dir) { + return Stream.of(new File(dir).listFiles()) + .filter(file -> !file.isDirectory()) + .map(File::getName) + .collect(Collectors.toSet()); + } + + public Set listFilesUsingFileWalk(String dir, int depth) throws IOException { + try (Stream stream = Files.walk(Paths.get(dir), depth)) { + return stream.filter(file -> !Files.isDirectory(file)) + .map(Path::getFileName) + .map(Path::toString) + .collect(Collectors.toSet()); + } + } + + public Set listFilesUsingFileWalkAndVisitor(String dir) throws IOException { + Set fileList = new HashSet<>(); + Files.walkFileTree(Paths.get(dir), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (!Files.isDirectory(file)) { + fileList.add(file.getFileName() + .toString()); + } + return FileVisitResult.CONTINUE; + } + }); + return fileList; + } + + public Set listFilesUsingDirectoryStream(String dir) throws IOException { + Set fileList = new HashSet<>(); + try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(dir))) { + for (Path path : stream) { + if (!Files.isDirectory(path)) { + fileList.add(path.getFileName() + .toString()); + } + } + } + return fileList; + } + +} diff --git a/core-java-io/src/test/java/com/baeldung/file/ListFilesUnitTest.java b/core-java-io/src/test/java/com/baeldung/file/ListFilesUnitTest.java new file mode 100644 index 0000000000..65710121cc --- /dev/null +++ b/core-java-io/src/test/java/com/baeldung/file/ListFilesUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.file; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Test; + +import com.baeldung.files.ListFiles; + +public class ListFilesUnitTest { + + private ListFiles listFiles = new ListFiles(); + private String DIRECTORY = "src/test/resources/listFilesUnitTestFolder"; + private static final int DEPTH = 1; + private Set EXPECTED_FILE_LIST = new HashSet() { + { + add("test.xml"); + add("employee.json"); + add("students.json"); + add("country.txt"); + } + }; + + @Test + public void givenDir_whenUsingJAVAIO_thenListAllFiles() throws IOException { + assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingJavaIO(DIRECTORY)); + } + + @Test + public void givenDir_whenWalkingTree_thenListAllFiles() throws IOException { + assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingFileWalk(DIRECTORY,DEPTH)); + } + + @Test + public void givenDir_whenWalkingTreeWithVisitor_thenListAllFiles() throws IOException { + assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingFileWalkAndVisitor(DIRECTORY)); + } + + @Test + public void givenDir_whenUsingDirectoryStream_thenListAllFiles() throws IOException { + assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingDirectoryStream(DIRECTORY)); + } +} diff --git a/core-java-io/src/test/resources/listFilesUnitTestFolder/country.txt b/core-java-io/src/test/resources/listFilesUnitTestFolder/country.txt new file mode 100644 index 0000000000..45bfe896dc --- /dev/null +++ b/core-java-io/src/test/resources/listFilesUnitTestFolder/country.txt @@ -0,0 +1 @@ +This is a sample txt file for unit test ListFilesUnitTest \ No newline at end of file diff --git a/core-java-io/src/test/resources/listFilesUnitTestFolder/employee.json b/core-java-io/src/test/resources/listFilesUnitTestFolder/employee.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/core-java-io/src/test/resources/listFilesUnitTestFolder/employee.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/core-java-io/src/test/resources/listFilesUnitTestFolder/students.json b/core-java-io/src/test/resources/listFilesUnitTestFolder/students.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/core-java-io/src/test/resources/listFilesUnitTestFolder/students.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/core-java-io/src/test/resources/listFilesUnitTestFolder/test.xml b/core-java-io/src/test/resources/listFilesUnitTestFolder/test.xml new file mode 100644 index 0000000000..19b16cc72c --- /dev/null +++ b/core-java-io/src/test/resources/listFilesUnitTestFolder/test.xml @@ -0,0 +1 @@ + \ No newline at end of file From 2a308c51cb3c68635a1510190528fdbd168a51c1 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Sun, 27 Jan 2019 10:34:13 +0400 Subject: [PATCH 142/190] suggested refactor --- .../main/java/com/baeldung/string/MatchWords.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/java-strings/src/main/java/com/baeldung/string/MatchWords.java b/java-strings/src/main/java/com/baeldung/string/MatchWords.java index 4baaa49227..0cad52c320 100644 --- a/java-strings/src/main/java/com/baeldung/string/MatchWords.java +++ b/java-strings/src/main/java/com/baeldung/string/MatchWords.java @@ -15,8 +15,7 @@ public class MatchWords { public static boolean containsWordsIndexOf(String inputString, String[] words) { boolean found = true; for (String word : words) { - int index = inputString.indexOf(word); - if (index == -1) { + if (inputString.indexOf(word) == -1) { found = false; break; } @@ -64,21 +63,19 @@ public class MatchWords { } Pattern pattern = Pattern.compile(regexp.toString()); - if (pattern.matcher(inputString).find()) { - return true; - } - return false; + + return pattern.matcher(inputString).find(); } public static boolean containsWordsJava8(String inputString, String[] words) { - List inputStringList = Arrays.asList(inputString.split(" ")); + List inputStringList = Arrays.asList(inputString.split(" ")); List wordsList = Arrays.asList(words); return wordsList.stream().allMatch(inputStringList::contains); } public static boolean containsWordsArray(String inputString, String[] words) { - List inputStringList = Arrays.asList(inputString.split(" ")); + List inputStringList = Arrays.asList(inputString.split(" ")); List wordsList = Arrays.asList(words); return inputStringList.containsAll(wordsList); From 4bd87241ce8cc99f98446b3703cb8ddfba9c2dca Mon Sep 17 00:00:00 2001 From: rodolforfq <31481067+rodolforfq@users.noreply.github.com> Date: Sun, 27 Jan 2019 02:38:38 -0400 Subject: [PATCH 143/190] BAEL-2524 (#6206) * BAEL-2524 Uploading article examples. * Fixing build error Used List.of, which is not available on java 8 (running java 11 on my PC) --- .../java8/lambda/methodreference/Bicycle.java | 29 ++++++++ .../methodreference/BicycleComparator.java | 13 ++++ .../MethodReferenceExamples.java | 70 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java create mode 100644 core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java create mode 100644 core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java new file mode 100644 index 0000000000..760a24d7c2 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java @@ -0,0 +1,29 @@ +package com.baeldung.java8.lambda.methodreference; + +public class Bicycle { + + private String brand; + private Integer frameSize; + + public Bicycle(String brand, Integer frameSize) { + this.brand = brand; + this.frameSize = frameSize; + } + + public String getBrand() { + return brand; + } + + public void setBrand(String brand) { + this.brand = brand; + } + + public Integer getFrameSize() { + return frameSize; + } + + public void setFrameSize(Integer frameSize) { + this.frameSize = frameSize; + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java new file mode 100644 index 0000000000..153a7d105a --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java @@ -0,0 +1,13 @@ +package com.baeldung.java8.lambda.methodreference; + +import java.util.Comparator; + +public class BicycleComparator implements Comparator { + + @Override + public int compare(Bicycle a, Bicycle b) { + return a.getFrameSize() + .compareTo(b.getFrameSize()); + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java new file mode 100644 index 0000000000..3b9a5ec6ff --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java @@ -0,0 +1,70 @@ +package com.baeldung.java8.lambda.methodreference; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.BiFunction; + +import org.junit.Test; + +public class MethodReferenceExamples { + + private static void doNothingAtAll(Object... o) { + } + + ; + + @Test + public void referenceToStaticMethod() { + List messages = Arrays.asList("Hello", "Baeldung", "readers!"); + messages.forEach((word) -> { + System.out.println(word); + }); + messages.forEach(System.out::println); + } + + @Test + public void referenceToInstanceMethodOfParticularObject() { + BicycleComparator bikeFrameSizeComparator = new BicycleComparator(); + createBicyclesList().stream() + .sorted((a, b) -> bikeFrameSizeComparator.compare(a, b)); + createBicyclesList().stream() + .sorted(bikeFrameSizeComparator::compare); + } + + @Test + public void referenceToInstanceMethodOfArbitratyObjectOfParticularType() { + List numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18); + numbers.stream() + .sorted((a, b) -> Integer.compare(a, b)); + numbers.stream() + .sorted(Integer::compare); + } + + @Test + public void referenceToConstructor() { + BiFunction bikeCreator = (brand, frameSize) -> new Bicycle(brand, frameSize); + BiFunction bikeCreatorMethodReference = Bicycle::new; + List bikes = new ArrayList<>(); + bikes.add(bikeCreator.apply("Giant", 50)); + bikes.add(bikeCreator.apply("Scott", 20)); + bikes.add(bikeCreatorMethodReference.apply("Trek", 35)); + bikes.add(bikeCreatorMethodReference.apply("GT", 40)); + } + + @Test + public void limitationsAndAdditionalExamples() { + createBicyclesList().forEach(b -> System.out.printf("Bike brand is '%s' and frame size is '%d'%n", b.getBrand(), b.getFrameSize())); + createBicyclesList().forEach((o) -> this.doNothingAtAll(o)); + } + + private List createBicyclesList() { + List bikes = new ArrayList<>(); + bikes.add(new Bicycle("Giant", 50)); + bikes.add(new Bicycle("Scott", 20)); + bikes.add(new Bicycle("Trek", 35)); + bikes.add(new Bicycle("GT", 40)); + return bikes; + } + +} From 8ccec9a413ee3e36eb73d0d1e2294596b2b3681f Mon Sep 17 00:00:00 2001 From: pcoates33 Date: Sun, 27 Jan 2019 06:55:25 +0000 Subject: [PATCH 144/190] BAEL-2510 Add nested properties section (#6212) Add nested properties section to ConfigurationProperties article. --- .../baeldung/properties/ConfigProperties.java | 62 +++++-------------- .../org/baeldung/properties/Credentials.java | 37 +++++++++++ .../src/main/resources/configprops.properties | 2 +- .../ConfigPropertiesIntegrationTest.java | 31 +++++++--- .../resources/configprops-test.properties | 2 +- 5 files changed, 75 insertions(+), 59 deletions(-) create mode 100644 spring-boot/src/main/java/org/baeldung/properties/Credentials.java diff --git a/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java b/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java index 2d3e56100c..3698d8ef30 100644 --- a/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java +++ b/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java @@ -8,7 +8,6 @@ import javax.validation.constraints.Min; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; -import org.hibernate.validator.constraints.Length; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @@ -20,41 +19,8 @@ import org.springframework.validation.annotation.Validated; @Validated public class ConfigProperties { - @Validated - public static class Credentials { - - @Length(max = 4, min = 1) - private String authMethod; - private String username; - private String password; - - public String getAuthMethod() { - return authMethod; - } - - public void setAuthMethod(String authMethod) { - this.authMethod = authMethod; - } - - 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; - } - } - @NotBlank - private String host; + private String hostName; @Min(1025) @Max(65536) @@ -63,16 +29,16 @@ public class ConfigProperties { @Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$") private String from; - private Credentials credentials; private List defaultRecipients; private Map additionalHeaders; + private Credentials credentials; - public String getHost() { - return host; + public String getHostName() { + return hostName; } - public void setHost(String host) { - this.host = host; + public void setHostName(String hostName) { + this.hostName = hostName; } public int getPort() { @@ -91,14 +57,6 @@ public class ConfigProperties { this.from = from; } - public Credentials getCredentials() { - return credentials; - } - - public void setCredentials(Credentials credentials) { - this.credentials = credentials; - } - public List getDefaultRecipients() { return defaultRecipients; } @@ -114,4 +72,12 @@ public class ConfigProperties { public void setAdditionalHeaders(Map additionalHeaders) { this.additionalHeaders = additionalHeaders; } + + public Credentials getCredentials() { + return credentials; + } + + public void setCredentials(Credentials credentials) { + this.credentials = credentials; + } } diff --git a/spring-boot/src/main/java/org/baeldung/properties/Credentials.java b/spring-boot/src/main/java/org/baeldung/properties/Credentials.java new file mode 100644 index 0000000000..2d8ac76e62 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/properties/Credentials.java @@ -0,0 +1,37 @@ +package org.baeldung.properties; + +import org.hibernate.validator.constraints.Length; +import org.springframework.validation.annotation.Validated; + +@Validated +public class Credentials { + + @Length(max = 4, min = 1) + private String authMethod; + private String username; + private String password; + + public String getAuthMethod() { + return authMethod; + } + + public void setAuthMethod(String authMethod) { + this.authMethod = authMethod; + } + + 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; + } +} diff --git a/spring-boot/src/main/resources/configprops.properties b/spring-boot/src/main/resources/configprops.properties index e5d9ae621d..2dad11f9cc 100644 --- a/spring-boot/src/main/resources/configprops.properties +++ b/spring-boot/src/main/resources/configprops.properties @@ -1,5 +1,5 @@ #Simple properties -mail.host=mailer@mail.com +mail.hostname=host@mail.com mail.port=9000 mail.from=mailer@mail.com diff --git a/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java index 3f3b558db9..4ba6bf29d8 100644 --- a/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java @@ -1,5 +1,8 @@ package org.baeldung.properties; +import java.util.List; +import java.util.Map; + import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -18,26 +21,36 @@ public class ConfigPropertiesIntegrationTest { @Test public void whenSimplePropertyQueriedthenReturnsProperty() throws Exception { - Assert.assertTrue("From address is read as null!", properties.getFrom() != null); + Assert.assertEquals("Incorrectly bound hostName property", "host@mail.com", properties.getHostName()); + Assert.assertEquals("Incorrectly bound port property", 9000, properties.getPort()); + Assert.assertEquals("Incorrectly bound from property", "mailer@mail.com", properties.getFrom()); } @Test public void whenListPropertyQueriedthenReturnsProperty() throws Exception { - Assert.assertTrue("Couldn't bind list property!", properties.getDefaultRecipients().size() == 2); - Assert.assertTrue("Incorrectly bound list property. Expected 2 entries!", properties.getDefaultRecipients().size() == 2); + List defaultRecipients = properties.getDefaultRecipients(); + Assert.assertTrue("Couldn't bind list property!", defaultRecipients.size() == 2); + Assert.assertTrue("Incorrectly bound list property. Expected 2 entries!", defaultRecipients.size() == 2); + Assert.assertEquals("Incorrectly bound list[0] property", "admin@mail.com", defaultRecipients.get(0)); + Assert.assertEquals("Incorrectly bound list[1] property", "owner@mail.com", defaultRecipients.get(1)); } @Test public void whenMapPropertyQueriedthenReturnsProperty() throws Exception { - Assert.assertTrue("Couldn't bind map property!", properties.getAdditionalHeaders() != null); - Assert.assertTrue("Incorrectly bound map property. Expected 3 Entries!", properties.getAdditionalHeaders().size() == 3); + Map additionalHeaders = properties.getAdditionalHeaders(); + Assert.assertTrue("Couldn't bind map property!", additionalHeaders != null); + Assert.assertTrue("Incorrectly bound map property. Expected 3 Entries!", additionalHeaders.size() == 3); + Assert.assertEquals("Incorrectly bound map[redelivery] property", "true", additionalHeaders.get("redelivery")); + Assert.assertEquals("Incorrectly bound map[secure] property", "true", additionalHeaders.get("secure")); + Assert.assertEquals("Incorrectly bound map[p3] property", "value", additionalHeaders.get("p3")); } @Test public void whenObjectPropertyQueriedthenReturnsProperty() throws Exception { - Assert.assertTrue("Couldn't bind map property!", properties.getCredentials() != null); - Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getAuthMethod().equals("SHA1")); - Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getUsername().equals("john")); - Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getPassword().equals("password")); + Credentials credentials = properties.getCredentials(); + Assert.assertTrue("Couldn't bind map property!", credentials != null); + Assert.assertEquals("Incorrectly bound object property, authMethod", "SHA1", credentials.getAuthMethod()); + Assert.assertEquals("Incorrectly bound object property, username", "john", credentials.getUsername()); + Assert.assertEquals("Incorrectly bound object property, password", "password", credentials.getPassword()); } } diff --git a/spring-boot/src/test/resources/configprops-test.properties b/spring-boot/src/test/resources/configprops-test.properties index b27cf2107a..697771ae6e 100644 --- a/spring-boot/src/test/resources/configprops-test.properties +++ b/spring-boot/src/test/resources/configprops-test.properties @@ -1,5 +1,5 @@ #Simple properties -mail.host=mailer@mail.com +mail.hostname=host@mail.com mail.port=9000 mail.from=mailer@mail.com From 2e733c38675d49f250861cae91166d5c4b18495b Mon Sep 17 00:00:00 2001 From: Eugen Paraschiv Date: Sun, 27 Jan 2019 14:25:36 +0200 Subject: [PATCH 145/190] minor formatting cleanup --- .../java/com/baeldung/config/DbConfig.java | 16 +++--- .../java/com/baeldung/config/MvcConfig.java | 8 +-- .../java/com/baeldung/config/RestConfig.java | 5 +- .../config/ValidatorEventRegister.java | 8 +-- .../baeldung/events/AuthorEventHandler.java | 49 +++++++++--------- .../com/baeldung/events/BookEventHandler.java | 23 +++++---- .../RestResponseEntityExceptionHandler.java | 7 +-- .../java/com/baeldung/models/Address.java | 2 +- .../main/java/com/baeldung/models/Author.java | 2 +- .../main/java/com/baeldung/models/Book.java | 7 ++- .../java/com/baeldung/models/Library.java | 2 +- .../java/com/baeldung/models/Subject.java | 2 +- .../com/baeldung/projections/CustomBook.java | 10 ++-- .../baeldung/repositories/BookRepository.java | 3 +- .../repositories/SubjectRepository.java | 4 +- .../events/AuthorEventHandlerUnitTest.java | 28 +++++------ .../events/BookEventHandlerUnitTest.java | 28 +++++------ .../SpringDataProjectionLiveTest.java | 50 +++++++++---------- 18 files changed, 122 insertions(+), 132 deletions(-) diff --git a/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java b/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java index 05fa27bbff..3ca728ec94 100644 --- a/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java +++ b/spring-data-rest/src/main/java/com/baeldung/config/DbConfig.java @@ -20,7 +20,7 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; // @PropertySource("persistence-h2.properties") // @PropertySource("persistence-hsqldb.properties") // @PropertySource("persistence-derby.properties") -//@PropertySource("persistence-sqlite.properties") +// @PropertySource("persistence-sqlite.properties") public class DbConfig { @Autowired @@ -65,21 +65,23 @@ public class DbConfig { @Configuration @Profile("h2") @PropertySource("classpath:persistence-h2.properties") -class H2Config {} +class H2Config { +} @Configuration @Profile("hsqldb") @PropertySource("classpath:persistence-hsqldb.properties") -class HsqldbConfig {} - +class HsqldbConfig { +} @Configuration @Profile("derby") @PropertySource("classpath:persistence-derby.properties") -class DerbyConfig {} - +class DerbyConfig { +} @Configuration @Profile("sqlite") @PropertySource("classpath:persistence-sqlite.properties") -class SqliteConfig {} +class SqliteConfig { +} diff --git a/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java b/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java index e5748f2f55..9d0d3a6687 100644 --- a/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java +++ b/spring-data-rest/src/main/java/com/baeldung/config/MvcConfig.java @@ -11,11 +11,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @EnableWebMvc public class MvcConfig implements WebMvcConfigurer { - - public MvcConfig(){ + + public MvcConfig() { super(); } - + @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); @@ -27,7 +27,7 @@ public class MvcConfig implements WebMvcConfigurer { } @Bean - BookEventHandler bookEventHandler(){ + BookEventHandler bookEventHandler() { return new BookEventHandler(); } diff --git a/spring-data-rest/src/main/java/com/baeldung/config/RestConfig.java b/spring-data-rest/src/main/java/com/baeldung/config/RestConfig.java index 39f90e867b..47cb95693b 100644 --- a/spring-data-rest/src/main/java/com/baeldung/config/RestConfig.java +++ b/spring-data-rest/src/main/java/com/baeldung/config/RestConfig.java @@ -12,10 +12,9 @@ import org.springframework.http.HttpMethod; public class RestConfig implements RepositoryRestConfigurer { @Override - public void configureRepositoryRestConfiguration(RepositoryRestConfiguration repositoryRestConfiguration){ + public void configureRepositoryRestConfiguration(RepositoryRestConfiguration repositoryRestConfiguration) { repositoryRestConfiguration.getProjectionConfiguration().addProjection(CustomBook.class); ExposureConfiguration config = repositoryRestConfiguration.getExposureConfiguration(); - config.forDomainType(WebsiteUser.class).withItemExposure((metadata, httpMethods) -> - httpMethods.disable(HttpMethod.PATCH)); + config.forDomainType(WebsiteUser.class).withItemExposure((metadata, httpMethods) -> httpMethods.disable(HttpMethod.PATCH)); } } 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 index 8f14d6c1c6..632ad9183a 100644 --- a/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java +++ b/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java @@ -24,13 +24,7 @@ public class ValidatorEventRegister implements InitializingBean { 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())); + 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/events/AuthorEventHandler.java b/spring-data-rest/src/main/java/com/baeldung/events/AuthorEventHandler.java index 5a8ae05c08..485dc8e221 100644 --- a/spring-data-rest/src/main/java/com/baeldung/events/AuthorEventHandler.java +++ b/spring-data-rest/src/main/java/com/baeldung/events/AuthorEventHandler.java @@ -8,33 +8,34 @@ import java.util.logging.Logger; @RepositoryEventHandler public class AuthorEventHandler { - Logger logger = Logger.getLogger("Class AuthorEventHandler"); - public AuthorEventHandler(){ - super(); - } + Logger logger = Logger.getLogger("Class AuthorEventHandler"); - @HandleBeforeCreate - public void handleAuthorBeforeCreate(Author author){ - logger.info("Inside Author Before Create...."); - String name = author.getName(); - } + public AuthorEventHandler() { + super(); + } - @HandleAfterCreate - public void handleAuthorAfterCreate(Author author){ - logger.info("Inside Author After Create ...."); - String name = author.getName(); - } + @HandleBeforeCreate + public void handleAuthorBeforeCreate(Author author) { + logger.info("Inside Author Before Create...."); + String name = author.getName(); + } - @HandleBeforeDelete - public void handleAuthorBeforeDelete(Author author){ - logger.info("Inside Author Before Delete ...."); - String name = author.getName(); - } + @HandleAfterCreate + public void handleAuthorAfterCreate(Author author) { + logger.info("Inside Author After Create ...."); + String name = author.getName(); + } - @HandleAfterDelete - public void handleAuthorAfterDelete(Author author){ - logger.info("Inside Author After Delete ...."); - String name = author.getName(); - } + @HandleBeforeDelete + public void handleAuthorBeforeDelete(Author author) { + logger.info("Inside Author Before Delete ...."); + String name = author.getName(); + } + + @HandleAfterDelete + public void handleAuthorAfterDelete(Author author) { + logger.info("Inside Author After Delete ...."); + String name = author.getName(); + } } diff --git a/spring-data-rest/src/main/java/com/baeldung/events/BookEventHandler.java b/spring-data-rest/src/main/java/com/baeldung/events/BookEventHandler.java index 3953e6ce0d..36ae62b926 100644 --- a/spring-data-rest/src/main/java/com/baeldung/events/BookEventHandler.java +++ b/spring-data-rest/src/main/java/com/baeldung/events/BookEventHandler.java @@ -10,17 +10,18 @@ import org.springframework.data.rest.core.annotation.RepositoryEventHandler; @RepositoryEventHandler public class BookEventHandler { - Logger logger = Logger.getLogger("Class BookEventHandler"); - @HandleBeforeCreate - public void handleBookBeforeCreate(Book book){ + Logger logger = Logger.getLogger("Class BookEventHandler"); - logger.info("Inside Book Before Create ...."); - book.getAuthors(); - } + @HandleBeforeCreate + public void handleBookBeforeCreate(Book book) { - @HandleBeforeCreate - public void handleAuthorBeforeCreate(Author author){ - logger.info("Inside Author Before Create ...."); - author.getBooks(); - } + logger.info("Inside Book Before Create ...."); + book.getAuthors(); + } + + @HandleBeforeCreate + public void handleAuthorBeforeCreate(Author author) { + logger.info("Inside Author Before Create ...."); + author.getBooks(); + } } 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 index aa24fccac7..a3ef91f6d6 100644 --- 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 @@ -19,12 +19,7 @@ public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionH public ResponseEntity handleAccessDeniedException(Exception ex, WebRequest request) { RepositoryConstraintViolationException nevEx = (RepositoryConstraintViolationException) ex; - String errors = nevEx - .getErrors() - .getAllErrors() - .stream() - .map(ObjectError::toString) - .collect(Collectors.joining("\n")); + String errors = nevEx.getErrors().getAllErrors().stream().map(ObjectError::toString).collect(Collectors.joining("\n")); return new ResponseEntity<>(errors, new HttpHeaders(), HttpStatus.NOT_ACCEPTABLE); } diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Address.java b/spring-data-rest/src/main/java/com/baeldung/models/Address.java index 82e3783f3e..713af58ae6 100644 --- a/spring-data-rest/src/main/java/com/baeldung/models/Address.java +++ b/spring-data-rest/src/main/java/com/baeldung/models/Address.java @@ -11,7 +11,7 @@ import javax.persistence.OneToOne; public class Address { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(nullable = false) diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Author.java b/spring-data-rest/src/main/java/com/baeldung/models/Author.java index cdd04cbdcf..3f43af9c47 100644 --- a/spring-data-rest/src/main/java/com/baeldung/models/Author.java +++ b/spring-data-rest/src/main/java/com/baeldung/models/Author.java @@ -16,7 +16,7 @@ import javax.persistence.ManyToMany; public class Author { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(nullable = false) diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Book.java b/spring-data-rest/src/main/java/com/baeldung/models/Book.java index 002a64e738..07b0d08b84 100644 --- a/spring-data-rest/src/main/java/com/baeldung/models/Book.java +++ b/spring-data-rest/src/main/java/com/baeldung/models/Book.java @@ -16,14 +16,14 @@ import javax.persistence.ManyToOne; public class Book { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(nullable = false) private String title; - + private String isbn; - + @ManyToOne @JoinColumn(name = "library_id") private Library library; @@ -63,7 +63,6 @@ public class Book { this.isbn = isbn; } - public Library getLibrary() { return library; } diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Library.java b/spring-data-rest/src/main/java/com/baeldung/models/Library.java index c27512d0e4..091975f5d0 100644 --- a/spring-data-rest/src/main/java/com/baeldung/models/Library.java +++ b/spring-data-rest/src/main/java/com/baeldung/models/Library.java @@ -17,7 +17,7 @@ import org.springframework.data.rest.core.annotation.RestResource; public class Library { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column diff --git a/spring-data-rest/src/main/java/com/baeldung/models/Subject.java b/spring-data-rest/src/main/java/com/baeldung/models/Subject.java index b3b9a5b0a0..4e5fa82148 100644 --- a/spring-data-rest/src/main/java/com/baeldung/models/Subject.java +++ b/spring-data-rest/src/main/java/com/baeldung/models/Subject.java @@ -10,7 +10,7 @@ import javax.persistence.Id; public class Subject { @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(nullable = false) diff --git a/spring-data-rest/src/main/java/com/baeldung/projections/CustomBook.java b/spring-data-rest/src/main/java/com/baeldung/projections/CustomBook.java index 1cd9c01383..3dc6938f5c 100644 --- a/spring-data-rest/src/main/java/com/baeldung/projections/CustomBook.java +++ b/spring-data-rest/src/main/java/com/baeldung/projections/CustomBook.java @@ -8,15 +8,15 @@ import org.springframework.data.rest.core.config.Projection; import com.baeldung.models.Author; import com.baeldung.models.Book; -@Projection(name = "customBook", types = { Book.class }) +@Projection(name = "customBook", types = { Book.class }) public interface CustomBook { @Value("#{target.id}") - long getId(); - + long getId(); + String getTitle(); - + List getAuthors(); - + @Value("#{target.getAuthors().size()}") int getAuthorCount(); } diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java index 34019a9d91..eee44f35d4 100644 --- a/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java +++ b/spring-data-rest/src/main/java/com/baeldung/repositories/BookRepository.java @@ -7,4 +7,5 @@ import com.baeldung.models.Book; import com.baeldung.projections.CustomBook; @RepositoryRestResource(excerptProjection = CustomBook.class) -public interface BookRepository extends CrudRepository {} +public interface BookRepository extends CrudRepository { +} diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java index a91ae2d505..76e34b0799 100644 --- a/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java +++ b/spring-data-rest/src/main/java/com/baeldung/repositories/SubjectRepository.java @@ -8,8 +8,8 @@ import org.springframework.data.rest.core.annotation.RestResource; import com.baeldung.models.Subject; public interface SubjectRepository extends PagingAndSortingRepository { - + @RestResource(path = "nameContains") public Page findByNameContaining(@Param("name") String name, Pageable p); - + } \ No newline at end of file diff --git a/spring-data-rest/src/test/java/com/baeldung/events/AuthorEventHandlerUnitTest.java b/spring-data-rest/src/test/java/com/baeldung/events/AuthorEventHandlerUnitTest.java index 6db536c40c..c01d5882a0 100644 --- a/spring-data-rest/src/test/java/com/baeldung/events/AuthorEventHandlerUnitTest.java +++ b/spring-data-rest/src/test/java/com/baeldung/events/AuthorEventHandlerUnitTest.java @@ -9,21 +9,21 @@ import static org.mockito.Mockito.mock; public class AuthorEventHandlerUnitTest { - @Test - public void whenCreateAuthorThenSuccess() { - Author author = mock(Author.class); - AuthorEventHandler authorEventHandler = new AuthorEventHandler(); - authorEventHandler.handleAuthorBeforeCreate(author); - Mockito.verify(author,Mockito.times(1)).getName(); + @Test + public void whenCreateAuthorThenSuccess() { + Author author = mock(Author.class); + AuthorEventHandler authorEventHandler = new AuthorEventHandler(); + authorEventHandler.handleAuthorBeforeCreate(author); + Mockito.verify(author, Mockito.times(1)).getName(); - } + } - @Test - public void whenDeleteAuthorThenSuccess() { - Author author = mock(Author.class); - AuthorEventHandler authorEventHandler = new AuthorEventHandler(); - authorEventHandler.handleAuthorAfterDelete(author); - Mockito.verify(author,Mockito.times(1)).getName(); + @Test + public void whenDeleteAuthorThenSuccess() { + Author author = mock(Author.class); + AuthorEventHandler authorEventHandler = new AuthorEventHandler(); + authorEventHandler.handleAuthorAfterDelete(author); + Mockito.verify(author, Mockito.times(1)).getName(); - } + } } diff --git a/spring-data-rest/src/test/java/com/baeldung/events/BookEventHandlerUnitTest.java b/spring-data-rest/src/test/java/com/baeldung/events/BookEventHandlerUnitTest.java index 28f0b91e1c..d6b8b3b25e 100644 --- a/spring-data-rest/src/test/java/com/baeldung/events/BookEventHandlerUnitTest.java +++ b/spring-data-rest/src/test/java/com/baeldung/events/BookEventHandlerUnitTest.java @@ -8,21 +8,21 @@ import org.mockito.Mockito; import static org.mockito.Mockito.mock; public class BookEventHandlerUnitTest { - @Test - public void whenCreateBookThenSuccess() { - Book book = mock(Book.class); - BookEventHandler bookEventHandler = new BookEventHandler(); - bookEventHandler.handleBookBeforeCreate(book); - Mockito.verify(book,Mockito.times(1)).getAuthors(); + @Test + public void whenCreateBookThenSuccess() { + Book book = mock(Book.class); + BookEventHandler bookEventHandler = new BookEventHandler(); + bookEventHandler.handleBookBeforeCreate(book); + Mockito.verify(book, Mockito.times(1)).getAuthors(); - } + } - @Test - public void whenCreateAuthorThenSuccess() { - Author author = mock(Author.class); - BookEventHandler bookEventHandler = new BookEventHandler(); - bookEventHandler.handleAuthorBeforeCreate(author); - Mockito.verify(author,Mockito.times(1)).getBooks(); + @Test + public void whenCreateAuthorThenSuccess() { + Author author = mock(Author.class); + BookEventHandler bookEventHandler = new BookEventHandler(); + bookEventHandler.handleAuthorBeforeCreate(author); + Mockito.verify(author, Mockito.times(1)).getBooks(); - } + } } diff --git a/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java b/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java index 702c1521da..ad219ccd53 100644 --- a/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java +++ b/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java @@ -29,16 +29,15 @@ public class SpringDataProjectionLiveTest { private static final String BOOK_ENDPOINT = "http://localhost:8080/books"; private static final String AUTHOR_ENDPOINT = "http://localhost:8080/authors"; - @Autowired private BookRepository bookRepo; @Autowired private AuthorRepository authorRepo; - + @Before - public void setup(){ - if(bookRepo.findById(1L) == null){ + public void setup() { + if (bookRepo.findById(1L) == null) { Book book = new Book("Animal Farm"); book.setIsbn("978-1943138425"); book = bookRepo.save(book); @@ -48,45 +47,44 @@ public class SpringDataProjectionLiveTest { author = authorRepo.save(author); } } - + @Test - public void whenGetBook_thenOK(){ - final Response response = RestAssured.get(BOOK_ENDPOINT+"/1"); - + public void whenGetBook_thenOK() { + final Response response = RestAssured.get(BOOK_ENDPOINT + "/1"); + assertEquals(200, response.getStatusCode()); assertTrue(response.asString().contains("isbn")); assertFalse(response.asString().contains("authorCount")); -// System.out.println(response.asString()); + // System.out.println(response.asString()); } - - + @Test - public void whenGetBookProjection_thenOK(){ - final Response response = RestAssured.get(BOOK_ENDPOINT+"/1?projection=customBook"); - + public void whenGetBookProjection_thenOK() { + final Response response = RestAssured.get(BOOK_ENDPOINT + "/1?projection=customBook"); + assertEquals(200, response.getStatusCode()); assertFalse(response.asString().contains("isbn")); - assertTrue(response.asString().contains("authorCount")); -// System.out.println(response.asString()); + assertTrue(response.asString().contains("authorCount")); + // System.out.println(response.asString()); } - + @Test - public void whenGetAllBooks_thenOK(){ + public void whenGetAllBooks_thenOK() { final Response response = RestAssured.get(BOOK_ENDPOINT); - + assertEquals(200, response.getStatusCode()); assertFalse(response.asString().contains("isbn")); - assertTrue(response.asString().contains("authorCount")); - // System.out.println(response.asString()); + assertTrue(response.asString().contains("authorCount")); + // System.out.println(response.asString()); } - + @Test - public void whenGetAuthorBooks_thenOK(){ - final Response response = RestAssured.get(AUTHOR_ENDPOINT+"/1/books"); - + public void whenGetAuthorBooks_thenOK() { + final Response response = RestAssured.get(AUTHOR_ENDPOINT + "/1/books"); + assertEquals(200, response.getStatusCode()); assertFalse(response.asString().contains("isbn")); - assertTrue(response.asString().contains("authorCount")); + assertTrue(response.asString().contains("authorCount")); System.out.println(response.asString()); } } From 2e8d2a7c1e6d827263b3c380e93a49fbb63a59b5 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 27 Jan 2019 15:08:16 +0200 Subject: [PATCH 146/190] Update README.md --- lombok/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lombok/README.md b/lombok/README.md index bd6282fd18..e3d08d4e26 100644 --- a/lombok/README.md +++ b/lombok/README.md @@ -5,3 +5,5 @@ - [Lombok @Builder with Inheritance](https://www.baeldung.com/lombok-builder-inheritance) - [Lombok Builder with Default Value](https://www.baeldung.com/lombok-builder-default-value) - [Lombok Builder with Custom Setter](https://www.baeldung.com/lombok-builder-custom-setter) +- [Setting up Lombok with Eclipse and Intellij](https://www.baeldung.com/lombok-ide) + From aed3e8f829d418a90afea6d659123afed0dd9e4c Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 27 Jan 2019 15:09:00 +0200 Subject: [PATCH 147/190] Update README.md --- core-java/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java/README.md b/core-java/README.md index 5aee69d9a9..d6cb619ed3 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -46,3 +46,4 @@ - [Graphs in Java](https://www.baeldung.com/java-graphs) - [Console I/O in Java](http://www.baeldung.com/java-console-input-output) - [Formatting with printf() in Java](https://www.baeldung.com/java-printstream-printf) +- [Retrieve Fields from a Java Class Using Reflection](https://www.baeldung.com/java-reflection-class-fields) From 79f1babc26b4d96686e1815d4437d0c5f3f0c65f Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 27 Jan 2019 15:09:46 +0200 Subject: [PATCH 148/190] Update README.md --- persistence-modules/java-jpa/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/java-jpa/README.md b/persistence-modules/java-jpa/README.md index 2eea5e60b4..5fe119cca4 100644 --- a/persistence-modules/java-jpa/README.md +++ b/persistence-modules/java-jpa/README.md @@ -4,3 +4,4 @@ - [A Guide to Stored Procedures with JPA](http://www.baeldung.com/jpa-stored-procedures) - [Fixing the JPA error “java.lang.String cannot be cast to Ljava.lang.String;”](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast) - [JPA Entity Graph](https://www.baeldung.com/jpa-entity-graph) +- [JPA 2.2 Support for Java 8 Date/Time Types](https://www.baeldung.com/jpa-java-time) From 639e0046d7ef36502edffff27be8a88b7d2d1ad4 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 27 Jan 2019 15:10:33 +0200 Subject: [PATCH 149/190] Update README.md --- core-java-io/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core-java-io/README.md b/core-java-io/README.md index 2ad980ca6a..fcb3302a48 100644 --- a/core-java-io/README.md +++ b/core-java-io/README.md @@ -36,4 +36,5 @@ - [Reading a CSV File into an Array](https://www.baeldung.com/java-csv-file-array) - [Guide to BufferedReader](https://www.baeldung.com/java-buffered-reader) - [How to Get the File Extension of a File in Java](http://www.baeldung.com/java-file-extension) -- [Getting a File’s Mime Type in Java](http://www.baeldung.com/java-file-mime-type) \ No newline at end of file +- [Getting a File’s Mime Type in Java](http://www.baeldung.com/java-file-mime-type) +- [Create a Directory in Java](https://www.baeldung.com/java-create-directory) From 242dc1dbcee7394319af5eafb91b209fe39421fc Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 27 Jan 2019 15:11:21 +0200 Subject: [PATCH 150/190] Update README.md --- persistence-modules/hibernate5/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/hibernate5/README.md b/persistence-modules/hibernate5/README.md index 03bdd9b759..a4e95a9062 100644 --- a/persistence-modules/hibernate5/README.md +++ b/persistence-modules/hibernate5/README.md @@ -29,3 +29,4 @@ - [Hibernate Named Query](https://www.baeldung.com/hibernate-named-query) - [Using c3p0 with Hibernate](https://www.baeldung.com/hibernate-c3p0) - [Persist a JSON Object Using Hibernate](https://www.baeldung.com/hibernate-persist-json-object) +- [Common Hibernate Exceptions](https://www.baeldung.com/hibernate-exceptions) From 8a3d3f934402b3409b3392edfccff8b4f1ad8a5e Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 27 Jan 2019 15:12:01 +0200 Subject: [PATCH 151/190] Update README.md --- java-streams/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java-streams/README.md b/java-streams/README.md index 33ca2619a8..f2afd570f6 100644 --- a/java-streams/README.md +++ b/java-streams/README.md @@ -15,3 +15,4 @@ - [Stream Ordering in Java](https://www.baeldung.com/java-stream-ordering) - [Introduction to Protonpack](https://www.baeldung.com/java-protonpack) - [Java Stream Filter with Lambda Expression](https://www.baeldung.com/java-stream-filter-lambda) +- [Counting Matches on a Stream Filter](https://www.baeldung.com/java-stream-filter-count) From fd70f654b54e3ac59a9477809aed14c833ec15fa Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Sun, 27 Jan 2019 17:45:34 +0400 Subject: [PATCH 152/190] primitive list collections --- .../list/primitive/PrimitiveCollections.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java index 5a8ddc0acd..50f372e9c9 100644 --- a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java +++ b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java @@ -2,6 +2,8 @@ package com.baeldung.list.primitive; import com.google.common.primitives.ImmutableIntArray; import com.google.common.primitives.Ints; +import gnu.trove.list.array.TIntArrayList; +import it.unimi.dsi.fastutil.ints.IntArrayList; import java.util.Arrays; import java.util.List; @@ -13,6 +15,18 @@ public class PrimitiveCollections { int[] primitives = new int[] {5, 10, 0, 2}; guavaPrimitives(primitives); + + TIntArrayList tList = new TIntArrayList(primitives); + + cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList(primitives); + + IntArrayList fastUtilList = new IntArrayList(primitives); + + System.out.println(tList); + + System.out.println(coltList); + + System.out.println(fastUtilList); } From 4845bd82a17f61db82e48e68937fb1887c4eb533 Mon Sep 17 00:00:00 2001 From: Sam Millington Date: Sun, 27 Jan 2019 14:18:13 +0000 Subject: [PATCH 153/190] added solid code (#6226) --- patterns/principles/solid/pom.xml | 23 ++++++++++++++++ .../main/java/com/baeldung/d/Keyboard.java | 4 +++ .../src/main/java/com/baeldung/d/Monitor.java | 6 +++++ .../java/com/baeldung/d/Windows98Machine.java | 15 +++++++++++ .../com/baeldung/d/Windows98MachineDI.java | 12 +++++++++ .../main/java/com/baeldung/i/BearCarer.java | 12 +++++++++ .../main/java/com/baeldung/i/BearCleaner.java | 5 ++++ .../main/java/com/baeldung/i/BearFeeder.java | 5 ++++ .../main/java/com/baeldung/i/BearKeeper.java | 9 +++++++ .../main/java/com/baeldung/i/BearPetter.java | 5 ++++ .../main/java/com/baeldung/i/CrazyPerson.java | 8 ++++++ .../src/main/java/com/baeldung/l/Car.java | 8 ++++++ .../main/java/com/baeldung/l/ElectricCar.java | 12 +++++++++ .../src/main/java/com/baeldung/l/Engine.java | 13 +++++++++ .../main/java/com/baeldung/l/MotorCar.java | 18 +++++++++++++ .../src/main/java/com/baeldung/o/Guitar.java | 10 +++++++ .../baeldung/o/SuperCoolGuitarWithFlames.java | 9 +++++++ .../src/main/java/com/baeldung/s/BadBook.java | 27 +++++++++++++++++++ .../main/java/com/baeldung/s/BookPrinter.java | 13 +++++++++ .../main/java/com/baeldung/s/GoodBook.java | 20 ++++++++++++++ 20 files changed, 234 insertions(+) create mode 100644 patterns/principles/solid/pom.xml create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/d/Keyboard.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/d/Monitor.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/d/Windows98Machine.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/d/Windows98MachineDI.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/i/BearCarer.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/i/BearCleaner.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/i/BearFeeder.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/i/BearKeeper.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/i/BearPetter.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/i/CrazyPerson.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/l/Car.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/l/ElectricCar.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/l/Engine.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/l/MotorCar.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/o/Guitar.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/o/SuperCoolGuitarWithFlames.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/s/BadBook.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/s/BookPrinter.java create mode 100644 patterns/principles/solid/src/main/java/com/baeldung/s/GoodBook.java diff --git a/patterns/principles/solid/pom.xml b/patterns/principles/solid/pom.xml new file mode 100644 index 0000000000..825c7730a5 --- /dev/null +++ b/patterns/principles/solid/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + com.baeldung + solid/artifactId> + 1.0-SNAPSHOT + + + + + + junit + junit + 4.12 + test + + + + + diff --git a/patterns/principles/solid/src/main/java/com/baeldung/d/Keyboard.java b/patterns/principles/solid/src/main/java/com/baeldung/d/Keyboard.java new file mode 100644 index 0000000000..acb50cedb4 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/d/Keyboard.java @@ -0,0 +1,4 @@ +package com.baeldung.d; + +public class Keyboard { +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/d/Monitor.java b/patterns/principles/solid/src/main/java/com/baeldung/d/Monitor.java new file mode 100644 index 0000000000..c0ab7a53b2 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/d/Monitor.java @@ -0,0 +1,6 @@ +package com.baeldung.d; + +public class Monitor { + + +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98Machine.java b/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98Machine.java new file mode 100644 index 0000000000..a9f130aedb --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98Machine.java @@ -0,0 +1,15 @@ +package com.baeldung.d; + +public class Windows98Machine { + + private final Keyboard keyboard; + private final Monitor monitor; + + public Windows98Machine() { + + monitor = new Monitor(); + keyboard = new Keyboard(); + + } + +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98MachineDI.java b/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98MachineDI.java new file mode 100644 index 0000000000..2a6fd74a41 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/d/Windows98MachineDI.java @@ -0,0 +1,12 @@ +package com.baeldung.d; + +public class Windows98MachineDI { + + private final Keyboard keyboard; + private final Monitor monitor; + + public Windows98MachineDI(Keyboard keyboard, Monitor monitor) { + this.keyboard = keyboard; + this.monitor = monitor; + } +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/BearCarer.java b/patterns/principles/solid/src/main/java/com/baeldung/i/BearCarer.java new file mode 100644 index 0000000000..3d69211674 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/i/BearCarer.java @@ -0,0 +1,12 @@ +package com.baeldung.i; + +public class BearCarer implements BearCleaner, BearFeeder { + + public void washTheBear() { + //I think we missed a spot.. + } + + public void feedTheBear() { + //Tuna tuesdays.. + } +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/BearCleaner.java b/patterns/principles/solid/src/main/java/com/baeldung/i/BearCleaner.java new file mode 100644 index 0000000000..e2b71b2ce8 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/i/BearCleaner.java @@ -0,0 +1,5 @@ +package com.baeldung.i; + +public interface BearCleaner { + void washTheBear(); +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/BearFeeder.java b/patterns/principles/solid/src/main/java/com/baeldung/i/BearFeeder.java new file mode 100644 index 0000000000..5d0ba7cd29 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/i/BearFeeder.java @@ -0,0 +1,5 @@ +package com.baeldung.i; + +public interface BearFeeder { + void feedTheBear(); +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/BearKeeper.java b/patterns/principles/solid/src/main/java/com/baeldung/i/BearKeeper.java new file mode 100644 index 0000000000..f09774a5ff --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/i/BearKeeper.java @@ -0,0 +1,9 @@ +package com.baeldung.i; + +public interface BearKeeper { + + void washTheBear(); + void feedTheBear(); + void petTheBear(); + +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/BearPetter.java b/patterns/principles/solid/src/main/java/com/baeldung/i/BearPetter.java new file mode 100644 index 0000000000..a913cf3d8a --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/i/BearPetter.java @@ -0,0 +1,5 @@ +package com.baeldung.i; + +public interface BearPetter { + void petTheBear(); +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/i/CrazyPerson.java b/patterns/principles/solid/src/main/java/com/baeldung/i/CrazyPerson.java new file mode 100644 index 0000000000..aae0d4c11b --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/i/CrazyPerson.java @@ -0,0 +1,8 @@ +package com.baeldung.i; + +public class CrazyPerson implements BearPetter { + + public void petTheBear() { + //Good luck with that! + } +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/l/Car.java b/patterns/principles/solid/src/main/java/com/baeldung/l/Car.java new file mode 100644 index 0000000000..b3481f894a --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/l/Car.java @@ -0,0 +1,8 @@ +package com.baeldung.l; + +public interface Car { + + void turnOnEngine(); + void accelerate(); + +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/l/ElectricCar.java b/patterns/principles/solid/src/main/java/com/baeldung/l/ElectricCar.java new file mode 100644 index 0000000000..fd919c5659 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/l/ElectricCar.java @@ -0,0 +1,12 @@ +package com.baeldung.l; + +public class ElectricCar implements Car { + + public void turnOnEngine() { + throw new AssertionError("I don't have an engine!"); + } + + public void accelerate() { + //this acceleration is crazy! + } +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/l/Engine.java b/patterns/principles/solid/src/main/java/com/baeldung/l/Engine.java new file mode 100644 index 0000000000..a8e38b8877 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/l/Engine.java @@ -0,0 +1,13 @@ +package com.baeldung.l; + +public class Engine { + + public void on(){ + //vroom. + } + + public void powerOn(int amount){ + //do something + } + +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/l/MotorCar.java b/patterns/principles/solid/src/main/java/com/baeldung/l/MotorCar.java new file mode 100644 index 0000000000..638f315475 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/l/MotorCar.java @@ -0,0 +1,18 @@ +package com.baeldung.l; + +public class MotorCar implements Car { + + private Engine engine; + + //Constructors, getters + setters + + public void turnOnEngine() { + //turn on the engine! + engine.on(); + } + + public void accelerate() { + //move forward! + engine.powerOn(1000); + } +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/o/Guitar.java b/patterns/principles/solid/src/main/java/com/baeldung/o/Guitar.java new file mode 100644 index 0000000000..baab006b5b --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/o/Guitar.java @@ -0,0 +1,10 @@ +package com.baeldung.o; + +public class Guitar { + + private String make; + private String model; + private int volume; + + //Constructors, getters & setters +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/o/SuperCoolGuitarWithFlames.java b/patterns/principles/solid/src/main/java/com/baeldung/o/SuperCoolGuitarWithFlames.java new file mode 100644 index 0000000000..b69e3be74a --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/o/SuperCoolGuitarWithFlames.java @@ -0,0 +1,9 @@ +package com.baeldung.o; + +public class SuperCoolGuitarWithFlames extends Guitar { + + private String flameColour; + + //constructor, getters + setters + +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/s/BadBook.java b/patterns/principles/solid/src/main/java/com/baeldung/s/BadBook.java new file mode 100644 index 0000000000..03c8fcd488 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/s/BadBook.java @@ -0,0 +1,27 @@ +package com.baeldung.s; + +public class BadBook { + + private String name; + private String author; + private String text; + + //constructor, getters and setters + + + //methods that directly relate to the book properties + public String replaceWordInText(String word){ + return text.replaceAll(word, text); + } + + public boolean isWordInText(String word){ + return text.contains(word); + } + + //methods for outputting text to console - should this really be here? + void printTextToConsole(){ + //our code for formatting and printing the text + } + + +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/s/BookPrinter.java b/patterns/principles/solid/src/main/java/com/baeldung/s/BookPrinter.java new file mode 100644 index 0000000000..0c8ef62e01 --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/s/BookPrinter.java @@ -0,0 +1,13 @@ +package com.baeldung.s; + +public class BookPrinter { + + //methods for outputting text + void printTextToConsole(String text){ + //our code for formatting and printing the text + } + + void printTextToAnotherMedium(String text){ + //code for writing to any other location.. + } +} diff --git a/patterns/principles/solid/src/main/java/com/baeldung/s/GoodBook.java b/patterns/principles/solid/src/main/java/com/baeldung/s/GoodBook.java new file mode 100644 index 0000000000..b0993aca2b --- /dev/null +++ b/patterns/principles/solid/src/main/java/com/baeldung/s/GoodBook.java @@ -0,0 +1,20 @@ +package com.baeldung.s; + +public class GoodBook { + + private String name; + private String author; + private String text; + + //constructor, getters and setters + + //methods that directly relate to the book properties + public String replaceWordInText(String word){ + return text.replaceAll(word, text); + } + + public boolean isWordInText(String word){ + return text.contains(word); + } + +} From e67915213a38cf82c0213f617d3c68ec812603b4 Mon Sep 17 00:00:00 2001 From: anuraggoyal1 Date: Sun, 27 Jan 2019 20:42:18 +0530 Subject: [PATCH 154/190] [BAEL-2471] Guide to Apache Commons MultiValuedMap (#6155) * [BAEL-2471] Guide to Apache Commons MultiValuedMap * Update MultiValuedMapUnitTest.java * added empty lines --- .../java/map/MultiValuedMapUnitTest.java | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java diff --git a/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java new file mode 100644 index 0000000000..67e4a5b0a0 --- /dev/null +++ b/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java @@ -0,0 +1,204 @@ +package com.baeldung.java.map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.collections4.MultiMapUtils; +import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; +import org.apache.commons.collections4.multimap.HashSetValuedHashMap; +import org.junit.Test; + +public class MultiValuedMapUnitTest { + + @Test + public void givenMultiValuesMap_whenPuttingMultipleValuesUsingPutMethod_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("key", "value1"); + map.put("key", "value2"); + map.put("key", "value2"); + + assertThat((Collection) map.get("key")).containsExactly("value1", "value2", "value2"); + } + + @Test + public void givenMultiValuesMap_whenPuttingMultipleValuesUsingPutAllMethod_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.putAll("key", Arrays.asList("value1", "value2", "value2")); + + assertThat((Collection) map.get("key")).containsExactly("value1", "value2", "value2"); + } + + @Test + public void givenMultiValuesMap_whenGettingValueUsingGetMethod_thenReturningValue() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + + assertThat((Collection) map.get("key")).containsExactly("value"); + } + + @Test + public void givenMultiValuesMap_whenUsingEntriesMethod_thenReturningMappings() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value1"); + map.put("key", "value2"); + + Collection> entries = (Collection>) map.entries(); + + for(Map.Entry entry : entries) { + assertThat(entry.getKey()).contains("key"); + assertTrue(entry.getValue().equals("value1") || entry.getValue().equals("value2") ); + } + } + + @Test + public void givenMultiValuesMap_whenUsingKeysMethod_thenReturningAllKeys() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + map.put("key1", "value1"); + map.put("key2", "value2"); + + assertThat(((Collection) map.keys())).contains("key", "key1", "key2"); + } + + @Test + public void givenMultiValuesMap_whenUsingKeySetMethod_thenReturningAllKeys() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + map.put("key1", "value1"); + map.put("key2", "value2"); + + assertThat((Collection) map.keySet()).contains("key", "key1", "key2"); + } + + @Test + public void givenMultiValuesMap_whenUsingValuesMethod_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + map.put("key1", "value1"); + map.put("key2", "value2"); + + assertThat(((Collection) map.values())).contains("value", "value1", "value2"); + } + + @Test + public void givenMultiValuesMap_whenUsingRemoveMethod_thenReturningUpdatedMap() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + map.put("key1", "value1"); + map.put("key2", "value2"); + assertThat(((Collection) map.values())).contains("value", "value1", "value2"); + + map.remove("key"); + + assertThat(((Collection) map.values())).contains("value1", "value2"); + } + + @Test + public void givenMultiValuesMap_whenUsingRemoveMappingMethod_thenReturningUpdatedMapAfterMappingRemoved() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + map.put("key1", "value1"); + map.put("key2", "value2"); + assertThat(((Collection) map.values())).contains("value", "value1", "value2"); + + map.removeMapping("key", "value"); + + assertThat(((Collection) map.values())).contains("value1", "value2"); + } + + @Test + public void givenMultiValuesMap_whenUsingClearMethod_thenReturningEmptyMap() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + map.put("key1", "value1"); + map.put("key2", "value2"); + assertThat(((Collection) map.values())).contains("value", "value1", "value2"); + + map.clear(); + + assertTrue(map.isEmpty()); + } + + @Test + public void givenMultiValuesMap_whenUsingContainsKeyMethod_thenReturningTrue() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + map.put("key1", "value1"); + map.put("key2", "value2"); + + assertTrue(map.containsKey("key")); + } + + @Test + public void givenMultiValuesMap_whenUsingContainsValueMethod_thenReturningTrue() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + map.put("key1", "value1"); + map.put("key2", "value2"); + + assertTrue(map.containsValue("value")); + } + + @Test + public void givenMultiValuesMap_whenUsingIsEmptyMethod_thenReturningFalse() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + map.put("key1", "value1"); + map.put("key2", "value2"); + + assertFalse(map.isEmpty()); + } + + @Test + public void givenMultiValuesMap_whenUsingSizeMethod_thenReturningElementCount() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value"); + map.put("key1", "value1"); + map.put("key2", "value2"); + + assertEquals(3, map.size()); + } + + @Test + public void givenArrayListValuedHashMap_whenPuttingDoubleValues_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("key", "value1"); + map.put("key", "value2"); + map.put("key", "value2"); + + assertThat((Collection) map.get("key")).containsExactly("value1", "value2", "value2"); + } + + @Test + public void givenHashSetValuedHashMap_whenPuttingTwiceTheSame_thenReturningOneValue() { + MultiValuedMap map = new HashSetValuedHashMap<>(); + + map.put("key1", "value1"); + map.put("key1", "value1"); + + assertThat((Collection) map.get("key1")).containsExactly("value1"); + } + + @Test(expected = UnsupportedOperationException.class) + public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key", "value1"); + map.put("key", "value2"); + MultiValuedMap immutableMap = MultiMapUtils.unmodifiableMultiValuedMap(map); + + immutableMap.put("key", "value3"); + } + + +} From f3faf9234e1d365c8bc9ac4a11316795b4b67b2b Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Mon, 28 Jan 2019 00:27:43 -0300 Subject: [PATCH 155/190] Initial Commit (#6202) --- .../validation/application/Application.java | 27 ++++++++ .../controllers/UserController.java | 52 ++++++++++++++ .../validation/application/entities/User.java | 50 ++++++++++++++ .../repositories/UserRepository.java | 8 +++ .../tests/UserControllerIntegrationTest.java | 69 +++++++++++++++++++ 5 files changed, 206 insertions(+) create mode 100644 spring-boot/src/main/java/com/baeldung/validation/application/Application.java create mode 100644 spring-boot/src/main/java/com/baeldung/validation/application/controllers/UserController.java create mode 100644 spring-boot/src/main/java/com/baeldung/validation/application/entities/User.java create mode 100644 spring-boot/src/main/java/com/baeldung/validation/application/repositories/UserRepository.java create mode 100644 spring-boot/src/test/java/com/baeldung/validation/tests/UserControllerIntegrationTest.java diff --git a/spring-boot/src/main/java/com/baeldung/validation/application/Application.java b/spring-boot/src/main/java/com/baeldung/validation/application/Application.java new file mode 100644 index 0000000000..af8f768193 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/validation/application/Application.java @@ -0,0 +1,27 @@ +package com.baeldung.validation.application; + +import com.baeldung.validation.application.entities.User; +import com.baeldung.validation.application.repositories.UserRepository; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + public CommandLineRunner run(UserRepository userRepository) throws Exception { + return (String[] args) -> { + User user1 = new User("Bob", "bob@domain.com"); + User user2 = new User("Jenny", "jenny@domain.com"); + userRepository.save(user1); + userRepository.save(user2); + userRepository.findAll().forEach(System.out::println); + }; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/validation/application/controllers/UserController.java b/spring-boot/src/main/java/com/baeldung/validation/application/controllers/UserController.java new file mode 100644 index 0000000000..a4aeefb70b --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/validation/application/controllers/UserController.java @@ -0,0 +1,52 @@ +package com.baeldung.validation.application.controllers; + +import com.baeldung.validation.application.entities.User; +import com.baeldung.validation.application.repositories.UserRepository; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class UserController { + + private final UserRepository userRepository; + + @Autowired + public UserController(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @GetMapping("/users") + public List getUsers() { + return (List) userRepository.findAll(); + } + + @PostMapping("/users") + ResponseEntity addUser(@Valid @RequestBody User user) { + return ResponseEntity.ok("User is valid"); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MethodArgumentNotValidException.class) + public Map handleValidationExceptions(MethodArgumentNotValidException ex) { + Map errors = new HashMap<>(); + ex.getBindingResult().getAllErrors().forEach((error) -> { + String fieldName = ((FieldError) error).getField(); + String errorMessage = error.getDefaultMessage(); + errors.put(fieldName, errorMessage); + }); + return errors; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/validation/application/entities/User.java b/spring-boot/src/main/java/com/baeldung/validation/application/entities/User.java new file mode 100644 index 0000000000..529368f132 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/validation/application/entities/User.java @@ -0,0 +1,50 @@ +package com.baeldung.validation.application.entities; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.validation.constraints.NotBlank; + +@Entity +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + @NotBlank(message = "Name is mandatory") + private String name; + + @NotBlank(message = "Email is mandatory") + private String email; + + public User(){} + + public User(String name, String email) { + this.name = name; + this.email = email; + } + + 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; + } + + @Override + public String toString() { + return "User{" + "id=" + id + ", name=" + name + ", email=" + email + '}'; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/validation/application/repositories/UserRepository.java b/spring-boot/src/main/java/com/baeldung/validation/application/repositories/UserRepository.java new file mode 100644 index 0000000000..b579addcaa --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/validation/application/repositories/UserRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.validation.application.repositories; + +import com.baeldung.validation.application.entities.User; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends CrudRepository {} diff --git a/spring-boot/src/test/java/com/baeldung/validation/tests/UserControllerIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/validation/tests/UserControllerIntegrationTest.java new file mode 100644 index 0000000000..265c4ec22c --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/validation/tests/UserControllerIntegrationTest.java @@ -0,0 +1,69 @@ +package com.baeldung.validation.tests; + +import com.baeldung.validation.application.controllers.UserController; +import com.baeldung.validation.application.repositories.UserRepository; +import java.nio.charset.Charset; +import static org.assertj.core.api.Assertions.assertThat; +import org.hamcrest.core.Is; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@RunWith(SpringRunner.class) +@WebMvcTest +@AutoConfigureMockMvc +public class UserControllerIntegrationTest { + + @MockBean + private UserRepository userRepository; + + @Autowired + UserController userController; + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenUserControllerInjected_thenNotNull() throws Exception { + assertThat(userController).isNotNull(); + } + + @Test + public void whenGetRequestToUsers_thenCorrectResponse() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/users") + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8)); + + } + + @Test + public void whenPostRequestToUsersAndValidUser_thenCorrectResponse() throws Exception { + MediaType textPlainUtf8 = new MediaType(MediaType.TEXT_PLAIN, Charset.forName("UTF-8")); + String user = "{\"name\": \"bob\", \"email\" : \"bob@domain.com\"}"; + mockMvc.perform(MockMvcRequestBuilders.post("/users") + .content(user) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().contentType(textPlainUtf8)); + } + + @Test + public void whenPostRequestToUsersAndInValidUser_thenCorrectReponse() throws Exception { + String user = "{\"name\": \"\", \"email\" : \"bob@domain.com\"}"; + mockMvc.perform(MockMvcRequestBuilders.post("/users") + .content(user) + .contentType(MediaType.APPLICATION_JSON_UTF8)) + .andExpect(MockMvcResultMatchers.status().isBadRequest()) + .andExpect(MockMvcResultMatchers.jsonPath("$.name", Is.is("Name is mandatory"))) + .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8)); + } +} From 13f9b875b8385bf875469d50f8dc7d5fa0aa7a2e Mon Sep 17 00:00:00 2001 From: Urvy Agrawal Date: Mon, 28 Jan 2019 13:17:30 +0530 Subject: [PATCH 156/190] Changes in test file --- .../test/BitwiseOperatorUnitTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java b/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java index d8af4b0833..74b8eb6bd2 100644 --- a/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java +++ b/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java @@ -10,7 +10,7 @@ public class BitwiseOperatorUnitTest { int value1 = 6; int value2 = 5; int result = value1 & value2; - assertEquals(result, 4); + assertEquals(4, result); } @Test @@ -18,7 +18,7 @@ public class BitwiseOperatorUnitTest { int value1 = 6; int value2 = 5; int result = value1 | value2; - assertEquals(result, 7); + assertEquals(7, result); } @Test @@ -26,7 +26,7 @@ public class BitwiseOperatorUnitTest { int value1 = 6; int value2 = 5; int result = value1 ^ value2; - assertEquals(result, 3); + assertEquals(3 result); } @Test @@ -40,42 +40,42 @@ public class BitwiseOperatorUnitTest { public void givenOnePositiveInteger_whenSignedRightShiftOperator_thenNewDecimalNumber() { int value = 12; int rightShift = value >> 2; - assertEquals(rightShift, 3); + assertEquals(3, rightShift); } @Test public void givenOneNegativeInteger_whenSignedRightShiftOperator_thenNewDecimalNumber() { int value = -12; int rightShift = value >> 2; - assertEquals(rightShift, -3); + assertEquals(-3, rightShift); } @Test public void givenOnePositiveInteger_whenLeftShiftOperator_thenNewDecimalNumber() { int value = 12; int leftShift = value << 2; - assertEquals(leftShift, 48); + assertEquals(48, leftShift); } @Test public void givenOneNegativeInteger_whenLeftShiftOperator_thenNewDecimalNumber() { int value = -12; int leftShift = value << 2; - assertEquals(leftShift, -48); + assertEquals(-48, leftShift); } @Test public void givenOnePositiveInteger_whenUnsignedRightShiftOperator_thenNewDecimalNumber() { int value = 12; int unsignedRightShift = value >>> 2; - assertEquals(unsignedRightShift, 3); + assertEquals(3, unsignedRightShift); } @Test public void givenOneNegativeInteger_whenUnsignedRightShiftOperator_thenNewDecimalNumber() { int value = -12; int unsignedRightShift = value >>> 2; - assertEquals(unsignedRightShift, 1073741821); + assertEquals(1073741821, unsignedRightShift); } } From e5c860192a84df1aee9e06bff059a5fd9cd22b91 Mon Sep 17 00:00:00 2001 From: Urvy Agrawal Date: Mon, 28 Jan 2019 13:28:22 +0530 Subject: [PATCH 157/190] Removed error line from the file --- .../baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java b/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java index 74b8eb6bd2..f74e181e36 100644 --- a/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java +++ b/core-java/src/test/java/com/baeldung/bitwiseoperator/test/BitwiseOperatorUnitTest.java @@ -26,7 +26,7 @@ public class BitwiseOperatorUnitTest { int value1 = 6; int value2 = 5; int result = value1 ^ value2; - assertEquals(3 result); + assertEquals(3, result); } @Test From 44d5be301ce9e69b69f4ef632250f6b8f07cd8c0 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Mon, 28 Jan 2019 15:15:05 +0400 Subject: [PATCH 158/190] remove performance test --- .../primitive/PrimitivesListPerformance.java | 76 ------------------- 1 file changed, 76 deletions(-) delete mode 100644 core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java diff --git a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java deleted file mode 100644 index f57c8d65a6..0000000000 --- a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.baeldung.list.primitive; - -import it.unimi.dsi.fastutil.ints.IntArrayList; -import gnu.trove.list.array.TIntArrayList; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@Warmup(iterations = 10) -public class PrimitivesListPerformance { - - @State(Scope.Thread) - public static class Initialize { - - List arrayList = new ArrayList<>(); - TIntArrayList tList = new TIntArrayList(); - cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList(); - IntArrayList fastUtilList = new IntArrayList(); - - int getValue = 10; - - final int iterations = 100000; - - @Setup(Level.Trial) - public void setUp() { - - for (int i = 0; i < iterations; i++) { - arrayList.add(i); - tList.add(i); - coltList.add(i); - fastUtilList.add(i); - } - - arrayList.add(getValue); - tList.add(getValue); - coltList.add(getValue); - fastUtilList.add(getValue); - } - } - - @Benchmark - public boolean containsArrayList(PrimitivesListPerformance.Initialize state) { - return state.arrayList.contains(state.getValue); - } - - @Benchmark - public boolean containsTIntList(PrimitivesListPerformance.Initialize state) { - return state.tList.contains(state.getValue); - } - - @Benchmark - public boolean containsColtIntList(PrimitivesListPerformance.Initialize state) { - return state.coltList.contains(state.getValue); - } - - @Benchmark - public boolean containsFastUtilIntList(PrimitivesListPerformance.Initialize state) { - return state.fastUtilList.contains(state.getValue); - } - - public static void main(String[] args) throws Exception { - Options options = new OptionsBuilder() - .include(PrimitivesListPerformance.class.getSimpleName()).threads(1) - .forks(1).shouldFailOnError(true) - .shouldDoGC(true) - .jvmArgs("-server").build(); - new Runner(options).run(); - } -} From d944b67c29a56d83ea31603238aa599de7cb212e Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Mon, 28 Jan 2019 15:23:01 +0400 Subject: [PATCH 159/190] remove JMH dependency --- core-java-collections-list/pom.xml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/core-java-collections-list/pom.xml b/core-java-collections-list/pom.xml index bc71882683..a7e711088a 100644 --- a/core-java-collections-list/pom.xml +++ b/core-java-collections-list/pom.xml @@ -37,17 +37,6 @@ provided - - org.openjdk.jmh - jmh-core - ${jmh-core.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh-generator-annprocess.version} - - net.sf.trove4j trove4j @@ -71,7 +60,5 @@ 1.7.0 3.11.1 1.16.12 - 1.19 - 1.19 From bb6c78f07b5b4e35101a59ea3203c1229cc44188 Mon Sep 17 00:00:00 2001 From: cror Date: Mon, 28 Jan 2019 18:20:21 +0100 Subject: [PATCH 160/190] BAEL-2702 fix: typo => failing SpringContextIntegrationTest --- .../src/main/resources/RedirectionWebSecurityConfig.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml b/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml index 231b5ab57e..0bb73d68ee 100644 --- a/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml +++ b/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml @@ -14,7 +14,7 @@ - + @@ -26,4 +26,3 @@ - From 7b9e72e6c97fdcfa3428294c8b98df51e3f972f2 Mon Sep 17 00:00:00 2001 From: cror Date: Mon, 28 Jan 2019 18:58:59 +0100 Subject: [PATCH 161/190] BAEL-2702 fix: added SecuredResourceController to the test context --- .../src/main/resources/RedirectionWebSecurityConfig.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml b/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml index 0bb73d68ee..cdee8dab43 100644 --- a/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml +++ b/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml @@ -15,6 +15,7 @@ + From d5e875a3f04794af04544bff6f8cb18b8c7ea2e8 Mon Sep 17 00:00:00 2001 From: cror Date: Mon, 28 Jan 2019 19:11:36 +0100 Subject: [PATCH 162/190] BAEL-2702 fix: added a NoOpPasswordEncoder to the test context --- .../src/main/resources/RedirectionWebSecurityConfig.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml b/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml index cdee8dab43..659347f610 100644 --- a/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml +++ b/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml @@ -16,6 +16,7 @@ + From 8f5f12519fc99f8f17848627c333f2f566fad25f Mon Sep 17 00:00:00 2001 From: eric-martin Date: Mon, 28 Jan 2019 20:37:45 -0600 Subject: [PATCH 163/190] BAEL-2328: Using isTrue() and isFalse() for assertions --- .../baeldung/string/MatchWordsUnitTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java b/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java index 1c2288068b..385aadaa5d 100644 --- a/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java +++ b/java-strings/src/test/java/com/baeldung/string/MatchWordsUnitTest.java @@ -13,54 +13,54 @@ public class MatchWordsUnitTest { @Test public void givenText_whenCallingStringContains_shouldMatchWords() { final boolean result = MatchWords.containsWords(inputString, words); - assertThat(result).isEqualTo(true); + assertThat(result).isTrue(); } @Test public void givenText_whenCallingJava8_shouldMatchWords() { final boolean result = MatchWords.containsWordsJava8(inputString, words); - assertThat(result).isEqualTo(true); + assertThat(result).isTrue(); } @Test public void givenText_whenCallingJava8_shouldNotMatchWords() { final boolean result = MatchWords.containsWordsJava8(wholeInput, words); - assertThat(result).isEqualTo(false); + assertThat(result).isFalse(); } @Test public void givenText_whenCallingPattern_shouldMatchWords() { final boolean result = MatchWords.containsWordsPatternMatch(inputString, words); - assertThat(result).isEqualTo(true); + assertThat(result).isTrue(); } @Test public void givenText_whenCallingAhoCorasick_shouldMatchWords() { final boolean result = MatchWords.containsWordsAhoCorasick(inputString, words); - assertThat(result).isEqualTo(true); + assertThat(result).isTrue(); } @Test public void givenText_whenCallingAhoCorasick_shouldNotMatchWords() { final boolean result = MatchWords.containsWordsAhoCorasick(wholeInput, words); - assertThat(result).isEqualTo(false); + assertThat(result).isFalse(); } @Test public void givenText_whenCallingIndexOf_shouldMatchWords() { final boolean result = MatchWords.containsWordsIndexOf(inputString, words); - assertThat(result).isEqualTo(true); + assertThat(result).isTrue(); } @Test public void givenText_whenCallingArrayList_shouldMatchWords() { final boolean result = MatchWords.containsWordsArray(inputString, words); - assertThat(result).isEqualTo(true); + assertThat(result).isTrue(); } @Test public void givenText_whenCallingArrayList_shouldNotMatchWords() { final boolean result = MatchWords.containsWordsArray(wholeInput, words); - assertThat(result).isEqualTo(false); + assertThat(result).isFalse(); } } From 0b988db96d1fa03768402b81360722d0606114b8 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Tue, 29 Jan 2019 17:04:33 -0200 Subject: [PATCH 164/190] Moved Building REST API article related code from spring-rest-full to spring-boot-rest module --- spring-boot-rest/pom.xml | 2 - .../com/baeldung/persistence/IOperations.java | 13 +++++ .../service/common/AbstractService.java | 34 ++++++++++++- .../persistence/service/impl/FooService.java | 11 +++++ .../web/controller/FooController.java | 48 +++++++++++++++---- .../event/SingleResourceRetrievedEvent.java | 22 +++++++++ ...ourceRetrievedDiscoverabilityListener.java | 34 +++++++++++++ spring-rest-full/.attach_pid28499 | 0 .../org/baeldung/persistence/IOperations.java | 6 +-- .../service/common/AbstractService.java | 10 ---- .../persistence/service/impl/FooService.java | 12 ----- .../web/controller/FooController.java | 14 ------ 12 files changed, 153 insertions(+), 53 deletions(-) create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/SingleResourceRetrievedEvent.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/SingleResourceRetrievedDiscoverabilityListener.java delete mode 100644 spring-rest-full/.attach_pid28499 diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index cf4ac0371b..3c8c4d7486 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -51,7 +51,6 @@ net.sourceforge.htmlunit htmlunit - ${htmlunit.version} test @@ -67,7 +66,6 @@ com.baeldung.SpringBootRestApplication - 2.32 27.0.1-jre diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java index d8996ca50d..1cc732ab08 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java @@ -1,16 +1,29 @@ package com.baeldung.persistence; import java.io.Serializable; +import java.util.List; import org.springframework.data.domain.Page; public interface IOperations { + // read - one + + T findOne(final long id); + // read - all + List findAll(); + Page findPaginated(int page, int size); // write T create(final T entity); + + T update(final T entity); + + void delete(final T entity); + + void deleteById(final long entityId); } diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java index 871f768895..5900c443b8 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java @@ -1,6 +1,7 @@ package com.baeldung.persistence.service.common; import java.io.Serializable; +import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -8,23 +9,54 @@ import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.transaction.annotation.Transactional; import com.baeldung.persistence.IOperations; +import com.google.common.collect.Lists; @Transactional public abstract class AbstractService implements IOperations { + // read - one + + @Override + @Transactional(readOnly = true) + public T findOne(final long id) { + return getDao().findById(id) + .get(); + } + // read - all + @Override + @Transactional(readOnly = true) + public List findAll() { + return Lists.newArrayList(getDao().findAll()); + } + @Override public Page findPaginated(final int page, final int size) { return getDao().findAll(PageRequest.of(page, size)); } // write - + @Override public T create(final T entity) { return getDao().save(entity); } + + @Override + public T update(final T entity) { + return getDao().save(entity); + } + + @Override + public void delete(final T entity) { + getDao().delete(entity); + } + + @Override + public void deleteById(final long entityId) { + getDao().deleteById(entityId); + } protected abstract PagingAndSortingRepository getDao(); diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java index 9d705f51d3..299e5ec214 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/impl/FooService.java @@ -1,5 +1,7 @@ package com.baeldung.persistence.service.impl; +import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -11,6 +13,7 @@ import com.baeldung.persistence.dao.IFooDao; import com.baeldung.persistence.model.Foo; import com.baeldung.persistence.service.IFooService; import com.baeldung.persistence.service.common.AbstractService; +import com.google.common.collect.Lists; @Service @Transactional @@ -36,5 +39,13 @@ public class FooService extends AbstractService implements IFooService { public Page findPaginated(Pageable pageable) { return dao.findAll(pageable); } + + // overridden to be secured + + @Override + @Transactional(readOnly = true) + public List findAll() { + return Lists.newArrayList(getDao().findAll()); + } } diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java index b35295cf99..59e33263db 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java @@ -9,14 +9,16 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.util.UriComponentsBuilder; import com.baeldung.persistence.model.Foo; @@ -24,9 +26,11 @@ import com.baeldung.persistence.service.IFooService; import com.baeldung.web.exception.MyResourceNotFoundException; import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; import com.baeldung.web.hateoas.event.ResourceCreatedEvent; +import com.baeldung.web.hateoas.event.SingleResourceRetrievedEvent; +import com.baeldung.web.util.RestPreconditions; import com.google.common.base.Preconditions; -@Controller +@RestController @RequestMapping(value = "/auth/foos") public class FooController { @@ -42,10 +46,24 @@ public class FooController { // API + // read - one + + @GetMapping(value = "/{id}") + public Foo findById(@PathVariable("id") final Long id, final HttpServletResponse response) { + final Foo resourceById = RestPreconditions.checkFound(service.findOne(id)); + + eventPublisher.publishEvent(new SingleResourceRetrievedEvent(this, response)); + return resourceById; + } + // read - all - @RequestMapping(params = { "page", "size" }, method = RequestMethod.GET) - @ResponseBody + @GetMapping + public List findAll() { + return service.findAll(); + } + + @GetMapping(params = { "page", "size" }) public List findPaginated(@RequestParam("page") final int page, @RequestParam("size") final int size, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) { final Page resultPage = service.findPaginated(page, size); @@ -59,7 +77,6 @@ public class FooController { } @GetMapping("/pageable") - @ResponseBody public List findPaginatedWithPageable(Pageable pageable, final UriComponentsBuilder uriBuilder, final HttpServletResponse response) { final Page resultPage = service.findPaginated(pageable); @@ -74,9 +91,8 @@ public class FooController { // write - @RequestMapping(method = RequestMethod.POST) + @PostMapping @ResponseStatus(HttpStatus.CREATED) - @ResponseBody public Foo create(@RequestBody final Foo resource, final HttpServletResponse response) { Preconditions.checkNotNull(resource); final Foo foo = service.create(resource); @@ -86,4 +102,18 @@ public class FooController { return foo; } + + @PutMapping(value = "/{id}") + @ResponseStatus(HttpStatus.OK) + public void update(@PathVariable("id") final Long id, @RequestBody final Foo resource) { + Preconditions.checkNotNull(resource); + RestPreconditions.checkFound(service.findOne(resource.getId())); + service.update(resource); + } + + @DeleteMapping(value = "/{id}") + @ResponseStatus(HttpStatus.OK) + public void delete(@PathVariable("id") final Long id) { + service.deleteById(id); + } } diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/SingleResourceRetrievedEvent.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/SingleResourceRetrievedEvent.java new file mode 100644 index 0000000000..70face083c --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/event/SingleResourceRetrievedEvent.java @@ -0,0 +1,22 @@ +package com.baeldung.web.hateoas.event; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.context.ApplicationEvent; + +public class SingleResourceRetrievedEvent extends ApplicationEvent { + private final HttpServletResponse response; + + public SingleResourceRetrievedEvent(final Object source, final HttpServletResponse response) { + super(source); + + this.response = response; + } + + // API + + public HttpServletResponse getResponse() { + return response; + } + +} \ No newline at end of file diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/SingleResourceRetrievedDiscoverabilityListener.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/SingleResourceRetrievedDiscoverabilityListener.java new file mode 100644 index 0000000000..d527c308b9 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/SingleResourceRetrievedDiscoverabilityListener.java @@ -0,0 +1,34 @@ +package com.baeldung.web.hateoas.listener; + +import javax.servlet.http.HttpServletResponse; + +import com.baeldung.web.hateoas.event.SingleResourceRetrievedEvent; +import com.baeldung.web.util.LinkUtil; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import com.google.common.base.Preconditions; +import com.google.common.net.HttpHeaders; + +@Component +class SingleResourceRetrievedDiscoverabilityListener implements ApplicationListener { + + @Override + public void onApplicationEvent(final SingleResourceRetrievedEvent resourceRetrievedEvent) { + Preconditions.checkNotNull(resourceRetrievedEvent); + + final HttpServletResponse response = resourceRetrievedEvent.getResponse(); + addLinkHeaderOnSingleResourceRetrieval(response); + } + + void addLinkHeaderOnSingleResourceRetrieval(final HttpServletResponse response) { + final String requestURL = ServletUriComponentsBuilder.fromCurrentRequestUri().build().toUri().toASCIIString(); + final int positionOfLastSlash = requestURL.lastIndexOf("/"); + final String uriForResourceCreation = requestURL.substring(0, positionOfLastSlash); + + final String linkHeaderValue = LinkUtil.createLinkHeader(uriForResourceCreation, "collection"); + response.addHeader(HttpHeaders.LINK, linkHeaderValue); + } + +} \ No newline at end of file diff --git a/spring-rest-full/.attach_pid28499 b/spring-rest-full/.attach_pid28499 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java b/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java index 8c5593c3e8..0b617bf7ab 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/IOperations.java @@ -16,11 +16,7 @@ public interface IOperations { // write T create(final T entity); - + T update(final T entity); - void delete(final T entity); - - void deleteById(final long entityId); - } diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java index 59ccea8b12..059516eeba 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java @@ -40,16 +40,6 @@ public abstract class AbstractService implements IOperat return getDao().save(entity); } - @Override - public void delete(final T entity) { - getDao().delete(entity); - } - - @Override - public void deleteById(final long entityId) { - getDao().delete(entityId); - } - protected abstract PagingAndSortingRepository getDao(); } diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java index d46f1bfe90..32fe1bd7e0 100644 --- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java +++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java @@ -1,7 +1,5 @@ package org.baeldung.persistence.service.impl; -import java.util.List; - import org.baeldung.persistence.dao.IFooDao; import org.baeldung.persistence.model.Foo; import org.baeldung.persistence.service.IFooService; @@ -11,8 +9,6 @@ import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import com.google.common.collect.Lists; - @Service @Transactional public class FooService extends AbstractService implements IFooService { @@ -38,12 +34,4 @@ public class FooService extends AbstractService implements IFooService { return dao.retrieveByName(name); } - // overridden to be secured - - @Override - @Transactional(readOnly = true) - public List findAll() { - return Lists.newArrayList(getDao().findAll()); - } - } diff --git a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java index 443d0908ee..2e4dbcacc9 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java +++ b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java @@ -80,20 +80,6 @@ public class FooController { return foo; } - @RequestMapping(value = "/{id}", method = RequestMethod.PUT) - @ResponseStatus(HttpStatus.OK) - public void update(@PathVariable("id") final Long id, @RequestBody final Foo resource) { - Preconditions.checkNotNull(resource); - RestPreconditions.checkFound(service.findOne(resource.getId())); - service.update(resource); - } - - @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) - @ResponseStatus(HttpStatus.OK) - public void delete(@PathVariable("id") final Long id) { - service.deleteById(id); - } - @RequestMapping(method = RequestMethod.HEAD) @ResponseStatus(HttpStatus.OK) public void head(final HttpServletResponse resp) { From e51d996ec1fab6f0239cd436e0739fd8f5d22bba Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Tue, 29 Jan 2019 17:05:09 -0200 Subject: [PATCH 165/190] Added spring boot related tests for building Rest API article --- .../web/FooControllerAppIntegrationTest.java | 36 +++++++++++ .../FooControllerWebLayerIntegrationTest.java | 60 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java create mode 100644 spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java new file mode 100644 index 0000000000..bd5b5eb58e --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java @@ -0,0 +1,36 @@ +package com.baeldung.web; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; + +/** + * + * We'll start the whole context, but not the server. We'll mock the REST calls instead. + * + */ +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class FooControllerAppIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenFindPaginatedRequest_thenEmptyResponse() throws Exception { + this.mockMvc.perform(get("/auth/foos").param("page", "0") + .param("size", "2")) + .andExpect(status().isOk()) + .andExpect(content().json("[]")); + } + +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java new file mode 100644 index 0000000000..7e41cf6393 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java @@ -0,0 +1,60 @@ +package com.baeldung.web; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.Collections; + +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IFooService; +import com.baeldung.web.controller.FooController; +import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; + +/** + * + * We'll start only the web layer. + * + */ +@RunWith(SpringRunner.class) +@WebMvcTest(FooController.class) +public class FooControllerWebLayerIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private IFooService service; + + @MockBean + private ApplicationEventPublisher publisher; + + @Test() + public void givenPresentFoo_whenFindPaginatedRequest_thenPageWithFooRetrieved() throws Exception { + Page page = new PageImpl<>(Collections.singletonList(new Foo("fooName"))); + when(service.findPaginated(0, 2)).thenReturn(page); + doNothing().when(publisher) + .publishEvent(any(PaginatedResultsRetrievedEvent.class)); + + this.mockMvc.perform(get("/auth/foos").param("page", "0") + .param("size", "2")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$",Matchers.hasSize(1))); + } + +} From 281432707993500042df7f02f1fa3b2310d9d401 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Tue, 29 Jan 2019 19:17:01 -0200 Subject: [PATCH 166/190] Moved article from Readme files --- spring-boot-rest/README.md | 3 ++- spring-rest-full/README.md | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index 2c89a64a00..ffc48126d3 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -2,4 +2,5 @@ Module for the articles that are part of the Spring REST E-book: 1. [Bootstrap a Web Application with Spring 5](https://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) 2. [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring) -3. [REST Pagination in Spring](http://www.baeldung.com/rest-api-pagination-in-spring) \ No newline at end of file +3. [REST Pagination in Spring](http://www.baeldung.com/rest-api-pagination-in-spring) +4. [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration) \ No newline at end of file diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md index 2ef3a09e37..5140c4b270 100644 --- a/spring-rest-full/README.md +++ b/spring-rest-full/README.md @@ -16,7 +16,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Project Configuration with Spring](http://www.baeldung.com/project-configuration-with-spring) - [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics) - [Bootstrap a Web Application with Spring 4](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) -- [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration) - [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic) From f1ea814185be1e0bf555bb49c737da27eed86b3f Mon Sep 17 00:00:00 2001 From: rodolforfq <31481067+rodolforfq@users.noreply.github.com> Date: Wed, 30 Jan 2019 11:40:24 -0400 Subject: [PATCH 167/190] New examples (#6242) Adding new examples. Improvement in existing method. --- .../baeldung/java8/lambda/methodreference/Bicycle.java | 5 +++++ .../methodreference/MethodReferenceExamples.java | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java index 760a24d7c2..26f9f8bc46 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java +++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java @@ -5,6 +5,11 @@ public class Bicycle { private String brand; private Integer frameSize; + public Bicycle(String brand) { + this.brand = brand; + this.frameSize = 0; + } + public Bicycle(String brand, Integer frameSize) { this.brand = brand; this.frameSize = frameSize; diff --git a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java index 3b9a5ec6ff..ede0ef9f70 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java +++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceExamples.java @@ -52,10 +52,18 @@ public class MethodReferenceExamples { bikes.add(bikeCreatorMethodReference.apply("GT", 40)); } + @Test + public void referenceToConstructorSimpleExample() { + List bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT"); + bikeBrands.stream() + .map(Bicycle::new) + .toArray(Bicycle[]::new); + } + @Test public void limitationsAndAdditionalExamples() { createBicyclesList().forEach(b -> System.out.printf("Bike brand is '%s' and frame size is '%d'%n", b.getBrand(), b.getFrameSize())); - createBicyclesList().forEach((o) -> this.doNothingAtAll(o)); + createBicyclesList().forEach((o) -> MethodReferenceExamples.doNothingAtAll(o)); } private List createBicyclesList() { From 4d1c8634facc2e9fb305c794c27e379bf7bb4aeb Mon Sep 17 00:00:00 2001 From: psevestre Date: Thu, 31 Jan 2019 00:16:26 -0200 Subject: [PATCH 168/190] Code for BAEL-1381 (#6214) * BAEL-1381 * [BAEL-1381] * [BAEL-1381] New module name * [BAEL-1381] software-security module --- pom.xml | 3 +- .../sql-injection-samples/.gitignore | 25 +++ .../sql-injection-samples/pom.xml | 61 +++++++ .../examples/security/sql/AccountDAO.java | 169 ++++++++++++++++++ .../examples/security/sql/AccountDTO.java | 16 ++ .../sql/SqlInjectionSamplesApplication.java | 14 ++ .../src/main/resources/application.properties | 0 .../resources/db/changelog/create-tables.xml | 19 ++ .../main/resources/db/master-changelog.xml | 8 + ...qlInjectionSamplesApplicationUnitTest.java | 60 +++++++ .../src/test/resources/application-test.yml | 6 + .../src/test/resources/data.sql | 4 + .../src/test/resources/schema.sql | 6 + 13 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 software-security/sql-injection-samples/.gitignore create mode 100644 software-security/sql-injection-samples/pom.xml create mode 100644 software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java create mode 100644 software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java create mode 100644 software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java create mode 100644 software-security/sql-injection-samples/src/main/resources/application.properties create mode 100644 software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml create mode 100644 software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml create mode 100644 software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java create mode 100644 software-security/sql-injection-samples/src/test/resources/application-test.yml create mode 100644 software-security/sql-injection-samples/src/test/resources/data.sql create mode 100644 software-security/sql-injection-samples/src/test/resources/schema.sql diff --git a/pom.xml b/pom.xml index 01cb86d103..787a03c2fb 100644 --- a/pom.xml +++ b/pom.xml @@ -567,7 +567,8 @@ rule-engines/rulebook rsocket rxjava - rxjava-2 + rxjava-2 + software-security/sql-injection-samples diff --git a/software-security/sql-injection-samples/.gitignore b/software-security/sql-injection-samples/.gitignore new file mode 100644 index 0000000000..82eca336e3 --- /dev/null +++ b/software-security/sql-injection-samples/.gitignore @@ -0,0 +1,25 @@ +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file diff --git a/software-security/sql-injection-samples/pom.xml b/software-security/sql-injection-samples/pom.xml new file mode 100644 index 0000000000..d5e64db6b3 --- /dev/null +++ b/software-security/sql-injection-samples/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + com.baeldung + sql-injection-samples + 0.0.1-SNAPSHOT + sql-injection-samples + Sample SQL Injection tests + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + org.apache.derby + derby + runtime + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.projectlombok + lombok + provided + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java new file mode 100644 index 0000000000..447dcc456d --- /dev/null +++ b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java @@ -0,0 +1,169 @@ +/** + * + */ +package com.baeldung.examples.security.sql; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.sql.DataSource; + +import org.springframework.stereotype.Component; + +/** + * @author Philippe + * + */ +@Component +public class AccountDAO { + + private final DataSource dataSource; + + public AccountDAO(DataSource dataSource) { + this.dataSource = dataSource; + } + + /** + * Return all accounts owned by a given customer,given his/her external id + * + * @param customerId + * @return + */ + public List unsafeFindAccountsByCustomerId(String customerId) { + + String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = '" + customerId + "'"; + + try (Connection c = dataSource.getConnection(); + ResultSet rs = c.createStatement() + .executeQuery(sql)) { + List accounts = new ArrayList<>(); + while (rs.next()) { + AccountDTO acc = AccountDTO.builder() + .customerId(rs.getString("customer_id")) + .branchId(rs.getString("branch_id")) + .accNumber(rs.getString("acc_number")) + .balance(rs.getBigDecimal("balance")) + .build(); + + accounts.add(acc); + } + + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Return all accounts owned by a given customer,given his/her external id + * + * @param customerId + * @return + */ + public List safeFindAccountsByCustomerId(String customerId) { + + String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = ?"; + + try (Connection c = dataSource.getConnection(); PreparedStatement p = c.prepareStatement(sql)) { + p.setString(1, customerId); + ResultSet rs = p.executeQuery(); + List accounts = new ArrayList<>(); + while (rs.next()) { + AccountDTO acc = AccountDTO.builder() + .customerId(rs.getString("customerId")) + .branchId(rs.getString("branch_id")) + .accNumber(rs.getString("acc_number")) + .balance(rs.getBigDecimal("balance")) + .build(); + + accounts.add(acc); + } + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + + private static final Set VALID_COLUMNS_FOR_ORDER_BY = Stream.of("acc_number", "branch_id", "balance") + .collect(Collectors.toCollection(HashSet::new)); + + /** + * Return all accounts owned by a given customer,given his/her external id + * + * @param customerId + * @return + */ + public List safeFindAccountsByCustomerId(String customerId, String orderBy) { + + String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = ? "; + + if (VALID_COLUMNS_FOR_ORDER_BY.contains(orderBy)) { + sql = sql + " order by " + orderBy; + } + else { + throw new IllegalArgumentException("Nice try!"); + } + + try (Connection c = dataSource.getConnection(); PreparedStatement p = c.prepareStatement(sql)) { + + p.setString(1, customerId); + ResultSet rs = p.executeQuery(); + List accounts = new ArrayList<>(); + while (rs.next()) { + AccountDTO acc = AccountDTO.builder() + .customerId(rs.getString("customerId")) + .branchId(rs.getString("branch_id")) + .accNumber(rs.getString("acc_number")) + .balance(rs.getBigDecimal("balance")) + .build(); + + accounts.add(acc); + } + + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Invalid placeholder usage example + * + * @param tableName + * @return + */ + public List wrongCountRecordsByTableName(String tableName) { + + try (Connection c = dataSource.getConnection(); + PreparedStatement p = c.prepareStatement("select count(*) from ?")) { + + p.setString(1, tableName); + ResultSet rs = p.executeQuery(); + List accounts = new ArrayList<>(); + while (rs.next()) { + AccountDTO acc = AccountDTO.builder() + .customerId(rs.getString("customerId")) + .branchId(rs.getString("branch_id")) + .accNumber(rs.getString("acc_number")) + .balance(rs.getBigDecimal("balance")) + .build(); + + accounts.add(acc); + } + + return accounts; + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + +} diff --git a/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java new file mode 100644 index 0000000000..2e6fa04af4 --- /dev/null +++ b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDTO.java @@ -0,0 +1,16 @@ +package com.baeldung.examples.security.sql; + +import java.math.BigDecimal; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class AccountDTO { + + private String customerId; + private String accNumber; + private String branchId; + private BigDecimal balance; +} diff --git a/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java new file mode 100644 index 0000000000..c1083ae3de --- /dev/null +++ b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.examples.security.sql; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SqlInjectionSamplesApplication { + + public static void main(String[] args) { + SpringApplication.run(SqlInjectionSamplesApplication.class, args); + } + +} + diff --git a/software-security/sql-injection-samples/src/main/resources/application.properties b/software-security/sql-injection-samples/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml b/software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml new file mode 100644 index 0000000000..a405c02049 --- /dev/null +++ b/software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml b/software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml new file mode 100644 index 0000000000..047ca2b314 --- /dev/null +++ b/software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java b/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java new file mode 100644 index 0000000000..1f37ba04b6 --- /dev/null +++ b/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.examples.security.sql; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.examples.security.sql.AccountDAO; +import com.baeldung.examples.security.sql.AccountDTO; + +@RunWith(SpringRunner.class) +@SpringBootTest +@ActiveProfiles({ "test" }) +public class SqlInjectionSamplesApplicationUnitTest { + + @Autowired + private AccountDAO target; + + @Test + public void givenAVulnerableMethod_whenValidCustomerId_thenReturnSingleAccount() { + + List accounts = target.unsafeFindAccountsByCustomerId("C1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isNotEmpty(); + assertThat(accounts).hasSize(1); + } + + @Test + public void givenAVulnerableMethod_whenHackedCustomerId_thenReturnAllAccounts() { + + List accounts = target.unsafeFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isNotEmpty(); + assertThat(accounts).hasSize(3); + } + + @Test + public void givenASafeMethod_whenHackedCustomerId_thenReturnNoAccounts() { + + List accounts = target.safeFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isEmpty(); + } + + @Test(expected = IllegalArgumentException.class) + public void givenASafeMethod_whenInvalidOrderBy_thenThroweException() { + target.safeFindAccountsByCustomerId("C1", "INVALID"); + } + + @Test(expected = RuntimeException.class) + public void givenWrongPlaceholderUsageMethod_whenNormalCall_thenThrowsException() { + target.wrongCountRecordsByTableName("Accounts"); + } +} diff --git a/software-security/sql-injection-samples/src/test/resources/application-test.yml b/software-security/sql-injection-samples/src/test/resources/application-test.yml new file mode 100644 index 0000000000..d07ee10aee --- /dev/null +++ b/software-security/sql-injection-samples/src/test/resources/application-test.yml @@ -0,0 +1,6 @@ +# +# Test profile configuration +# +spring: + datasource: + initialization-mode: always diff --git a/software-security/sql-injection-samples/src/test/resources/data.sql b/software-security/sql-injection-samples/src/test/resources/data.sql new file mode 100644 index 0000000000..586618a07f --- /dev/null +++ b/software-security/sql-injection-samples/src/test/resources/data.sql @@ -0,0 +1,4 @@ +insert into Accounts(customer_id,acc_number,branch_id,balance) values ('C1','0001',1,1000.00); +insert into Accounts(customer_id,acc_number,branch_id,balance) values ('C2','0002',1,500.00); +insert into Accounts(customer_id,acc_number,branch_id,balance) values ('C3','0003',1,501.00); + diff --git a/software-security/sql-injection-samples/src/test/resources/schema.sql b/software-security/sql-injection-samples/src/test/resources/schema.sql new file mode 100644 index 0000000000..bfb0ae8059 --- /dev/null +++ b/software-security/sql-injection-samples/src/test/resources/schema.sql @@ -0,0 +1,6 @@ +create table Accounts ( + customer_id varchar(16) not null, + acc_number varchar(16) not null, + branch_id decimal(8,0), + balance decimal(16,4) +); From ca98fbb7062c13129ee3193b679a64ad9da63f84 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Thu, 31 Jan 2019 16:18:59 +0400 Subject: [PATCH 169/190] Added Stream Api --- .../list/primitive/PrimitiveCollections.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java index 50f372e9c9..01372763e9 100644 --- a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java +++ b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitiveCollections.java @@ -7,15 +7,20 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import java.util.Arrays; import java.util.List; +import java.util.OptionalDouble; +import java.util.function.IntPredicate; +import java.util.stream.IntStream; public class PrimitiveCollections { public static void main(String[] args) { - int[] primitives = new int[] {5, 10, 0, 2}; + int[] primitives = new int[] {5, 10, 0, 2, -8}; guavaPrimitives(primitives); + intStream(primitives); + TIntArrayList tList = new TIntArrayList(primitives); cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList(primitives); @@ -29,6 +34,15 @@ public class PrimitiveCollections { System.out.println(fastUtilList); } + private static void intStream(int[] primitives) { + + IntStream stream = IntStream.of(5, 10, 0, 2, -8); + + IntStream newStream = IntStream.of(primitives); + + OptionalDouble average = stream.filter(i -> i > 0).average(); + } + private static void guavaPrimitives(int[] primitives) { From 56a832273e35c82da8d6de1b041ed518f11b53ce Mon Sep 17 00:00:00 2001 From: Dave Crane Date: Thu, 31 Jan 2019 12:48:35 +0000 Subject: [PATCH 170/190] Lombok SuperBuilder Issue: BAEL-2561 --- .../buildermethodname}/Child.java | 2 +- .../buildermethodname}/Parent.java | 2 +- .../buildermethodname/Student.java | 16 ++++ .../inheritance/superbuilder/Child.java | 11 +++ .../inheritance/superbuilder/Parent.java | 11 +++ .../inheritance/superbuilder/Student.java | 10 ++ .../lombok/builder/BuilderUnitTest.java | 16 ---- ...derInheritanceUsingMethodNameUnitTest.java | 40 ++++++++ ...rInheritanceUsingSuperBuilderUnitTest.java | 96 +++++++++++++++++++ 9 files changed, 186 insertions(+), 18 deletions(-) rename lombok/src/main/java/com/baeldung/lombok/builder/{ => inheritance/buildermethodname}/Child.java (86%) rename lombok/src/main/java/com/baeldung/lombok/builder/{ => inheritance/buildermethodname}/Parent.java (70%) create mode 100644 lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Student.java create mode 100644 lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Child.java create mode 100644 lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Parent.java create mode 100644 lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Student.java create mode 100644 lombok/src/test/java/com/baeldung/lombok/builder/inheritance/buildermethodname/BuilderInheritanceUsingMethodNameUnitTest.java create mode 100644 lombok/src/test/java/com/baeldung/lombok/builder/inheritance/superbuilder/BuilderInheritanceUsingSuperBuilderUnitTest.java diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/Child.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Child.java similarity index 86% rename from lombok/src/main/java/com/baeldung/lombok/builder/Child.java rename to lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Child.java index 70f6d9c46e..4cfcc22fb2 100644 --- a/lombok/src/main/java/com/baeldung/lombok/builder/Child.java +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Child.java @@ -1,4 +1,4 @@ -package com.baeldung.lombok.builder; +package com.baeldung.lombok.builder.inheritance.buildermethodname; import lombok.Builder; import lombok.Getter; diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/Parent.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Parent.java similarity index 70% rename from lombok/src/main/java/com/baeldung/lombok/builder/Parent.java rename to lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Parent.java index 0cf76d4b00..93e48ee44e 100644 --- a/lombok/src/main/java/com/baeldung/lombok/builder/Parent.java +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Parent.java @@ -1,4 +1,4 @@ -package com.baeldung.lombok.builder; +package com.baeldung.lombok.builder.inheritance.buildermethodname; import lombok.Builder; import lombok.Getter; diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Student.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Student.java new file mode 100644 index 0000000000..c8eea84b97 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/buildermethodname/Student.java @@ -0,0 +1,16 @@ +package com.baeldung.lombok.builder.inheritance.buildermethodname; + +import lombok.Builder; +import lombok.Getter; + +@Getter +public class Student extends Child { + + private final String schoolName; + + @Builder(builderMethodName = "studentBuilder") + public Student(String parentName, int parentAge, String childName, int childAge, String schoolName) { + super(parentName, parentAge, childName, childAge); + this.schoolName = schoolName; + } +} diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Child.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Child.java new file mode 100644 index 0000000000..92285ebdc3 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Child.java @@ -0,0 +1,11 @@ +package com.baeldung.lombok.builder.inheritance.superbuilder; + +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@Getter +@SuperBuilder(toBuilder = true) +public class Child extends Parent { + private final String childName; + private final int childAge; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Parent.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Parent.java new file mode 100644 index 0000000000..b8e0934520 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Parent.java @@ -0,0 +1,11 @@ +package com.baeldung.lombok.builder.inheritance.superbuilder; + +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@Getter +@SuperBuilder(toBuilder = true) +public class Parent { + private final String parentName; + private final int parentAge; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Student.java b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Student.java new file mode 100644 index 0000000000..db43bacafa --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/inheritance/superbuilder/Student.java @@ -0,0 +1,10 @@ +package com.baeldung.lombok.builder.inheritance.superbuilder; + +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +@Getter +@SuperBuilder(toBuilder = true) +public class Student extends Child { + private final String schoolName; +} diff --git a/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java index 56a380569d..546c38f140 100644 --- a/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java +++ b/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java @@ -40,20 +40,4 @@ public class BuilderUnitTest { assertThat(testImmutableClient.getName()).isEqualTo("foo"); assertThat(testImmutableClient.getId()).isEqualTo(1); } - - @Test - public void givenBuilderAtMethodLevel_ChildInheritingParentIsBuilt() { - Child child = Child.childBuilder() - .parentName("Andrea") - .parentAge(38) - .childName("Emma") - .childAge(6) - .build(); - - assertThat(child.getChildName()).isEqualTo("Emma"); - assertThat(child.getChildAge()).isEqualTo(6); - assertThat(child.getParentName()).isEqualTo("Andrea"); - assertThat(child.getParentAge()).isEqualTo(38); - } - } diff --git a/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/buildermethodname/BuilderInheritanceUsingMethodNameUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/buildermethodname/BuilderInheritanceUsingMethodNameUnitTest.java new file mode 100644 index 0000000000..cf50b2577b --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/buildermethodname/BuilderInheritanceUsingMethodNameUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.lombok.builder.inheritance.buildermethodname; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class BuilderInheritanceUsingMethodNameUnitTest { + + @Test + public void givenBuilderAtMethodLevel_ChildInheritingParentIsBuilt() { + Child child = Child.childBuilder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .build(); + + assertThat(child.getChildName()).isEqualTo("Emma"); + assertThat(child.getChildAge()).isEqualTo(6); + assertThat(child.getParentName()).isEqualTo("Andrea"); + assertThat(child.getParentAge()).isEqualTo(38); + } + + @Test + public void givenSuperBuilderOnAllThreeLevels_StudentInheritingChildAndParentIsBuilt() { + Student student = Student.studentBuilder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .schoolName("Baeldung High School") + .build(); + + assertThat(student.getChildName()).isEqualTo("Emma"); + assertThat(student.getChildAge()).isEqualTo(6); + assertThat(student.getParentName()).isEqualTo("Andrea"); + assertThat(student.getParentAge()).isEqualTo(38); + assertThat(student.getSchoolName()).isEqualTo("Baeldung High School"); + } +} diff --git a/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/superbuilder/BuilderInheritanceUsingSuperBuilderUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/superbuilder/BuilderInheritanceUsingSuperBuilderUnitTest.java new file mode 100644 index 0000000000..72bfa6567b --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/builder/inheritance/superbuilder/BuilderInheritanceUsingSuperBuilderUnitTest.java @@ -0,0 +1,96 @@ +package com.baeldung.lombok.builder.inheritance.superbuilder; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class BuilderInheritanceUsingSuperBuilderUnitTest { + + @Test + public void givenSuperBuilderOnParentAndOnChild_ChildInheritingParentIsBuilt() { + Child child = Child.builder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .build(); + + assertThat(child.getChildName()).isEqualTo("Emma"); + assertThat(child.getChildAge()).isEqualTo(6); + assertThat(child.getParentName()).isEqualTo("Andrea"); + assertThat(child.getParentAge()).isEqualTo(38); + } + + @Test + public void givenSuperBuilderOnParent_StandardBuilderIsBuilt() { + Parent parent = Parent.builder() + .parentName("Andrea") + .parentAge(38) + .build(); + + assertThat(parent.getParentName()).isEqualTo("Andrea"); + assertThat(parent.getParentAge()).isEqualTo(38); + } + + @Test + public void givenToBuilderIsSetToTrueOnParentAndChild_DeepCopyViaBuilderIsPossible() { + Child child1 = Child.builder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .build(); + + Child child2 = child1.toBuilder() + .childName("Anna") + .build(); + + assertThat(child2.getChildName()).isEqualTo("Anna"); + assertThat(child2.getChildAge()).isEqualTo(6); + assertThat(child2.getParentName()).isEqualTo("Andrea"); + assertThat(child2.getParentAge()).isEqualTo(38); + + } + + @Test + public void givenSuperBuilderOnAllThreeLevels_StudentInheritingChildAndParentIsBuilt() { + Student student = Student.builder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .schoolName("Baeldung High School") + .build(); + + assertThat(student.getChildName()).isEqualTo("Emma"); + assertThat(student.getChildAge()).isEqualTo(6); + assertThat(student.getParentName()).isEqualTo("Andrea"); + assertThat(student.getParentAge()).isEqualTo(38); + assertThat(student.getSchoolName()).isEqualTo("Baeldung High School"); + } + + @Test + public void givenToBuilderIsSetToTrueOnParentChildAndStudent_DeepCopyViaBuilderIsPossible() { + Student student1 = Student.builder() + .parentName("Andrea") + .parentAge(38) + .childName("Emma") + .childAge(6) + .schoolName("School 1") + .build(); + + Student student2 = student1.toBuilder() + .childName("Anna") + .schoolName("School 2") + .build(); + + assertThat(student2.getChildName()).isEqualTo("Anna"); + assertThat(student2.getChildAge()).isEqualTo(6); + assertThat(student2.getParentName()).isEqualTo("Andrea"); + assertThat(student2.getParentAge()).isEqualTo(38); + assertThat(student2.getSchoolName()).isEqualTo("School 2"); + + } + + +} From bd166ed82f02a49b7c1eadec210b0c1459745c33 Mon Sep 17 00:00:00 2001 From: Andrey Shcherbakov Date: Thu, 31 Jan 2019 22:18:07 +0100 Subject: [PATCH 171/190] Fix the integration test in module spring-4 --- .../org/baeldung/SpringContextIntegrationTest.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java index 9dfac2bd9e..d646e22511 100644 --- a/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-4/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -2,13 +2,16 @@ package org.baeldung; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; import com.baeldung.flips.ApplicationConfig; -@RunWith(SpringRunner.class) -@SpringBootTest(classes = ApplicationConfig.class) + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ApplicationConfig.class) +@WebAppConfiguration public class SpringContextIntegrationTest { @Test From 1c556fe4fc9192eef90e0c60e084b202fd004a9e Mon Sep 17 00:00:00 2001 From: Andrey Shcherbakov Date: Thu, 31 Jan 2019 22:28:46 +0100 Subject: [PATCH 172/190] Fix the integration test in module springboot-autoconfiguration This test requires that MySQL engine is up. --- .../SpringContextIntegrationTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 spring-boot-autoconfiguration/src/test/java/com/baeldung/SpringContextIntegrationTest.java diff --git a/spring-boot-autoconfiguration/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-boot-autoconfiguration/src/test/java/com/baeldung/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..a0138bec8d --- /dev/null +++ b/spring-boot-autoconfiguration/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +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.web.WebAppConfiguration; + +import com.baeldung.autoconfiguration.MySQLAutoconfiguration; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = MySQLAutoconfiguration.class) +@WebAppConfiguration +public class SpringContextIntegrationTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} \ No newline at end of file From 191039ffc60afc3b39ef09be79a54887a8e9d164 Mon Sep 17 00:00:00 2001 From: Andrey Shcherbakov Date: Fri, 1 Feb 2019 07:19:07 +0100 Subject: [PATCH 173/190] Add code for issue BAEL-2574 (#6249) * Add code for issue BAEL-2574 This is a code for article "Access Spring MVC Model object in JS" Set up the project Add a test * Rename the test class --- spring-boot-mvc/pom.xml | 10 ++++++ .../java/com/baeldung/accessparamsjs/App.java | 13 ++++++++ .../baeldung/accessparamsjs/Controller.java | 32 +++++++++++++++++++ .../src/main/resources/application.properties | 4 ++- .../src/main/webapp/WEB-INF/jsp/index.jsp | 27 ++++++++++++++++ spring-boot-mvc/src/main/webapp/js/jquery.js | 2 ++ .../src/main/webapp/js/script-async-jquery.js | 6 ++++ .../src/main/webapp/js/script-async.js | 6 ++++ spring-boot-mvc/src/main/webapp/js/script.js | 4 +++ .../accessparamsjs/ControllerUnitTest.java | 28 ++++++++++++++++ 10 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/App.java create mode 100644 spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/Controller.java create mode 100644 spring-boot-mvc/src/main/webapp/WEB-INF/jsp/index.jsp create mode 100644 spring-boot-mvc/src/main/webapp/js/jquery.js create mode 100644 spring-boot-mvc/src/main/webapp/js/script-async-jquery.js create mode 100644 spring-boot-mvc/src/main/webapp/js/script-async.js create mode 100644 spring-boot-mvc/src/main/webapp/js/script.js create mode 100644 spring-boot-mvc/src/test/java/com/baeldung/accessparamsjs/ControllerUnitTest.java diff --git a/spring-boot-mvc/pom.xml b/spring-boot-mvc/pom.xml index b219e53431..bb3e6312ab 100644 --- a/spring-boot-mvc/pom.xml +++ b/spring-boot-mvc/pom.xml @@ -72,6 +72,16 @@ ${spring.fox.version} + + org.apache.tomcat.embed + tomcat-embed-jasper + provided + + + javax.servlet + jstl + + diff --git a/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/App.java b/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/App.java new file mode 100644 index 0000000000..2ffbb354c3 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/App.java @@ -0,0 +1,13 @@ +package com.baeldung.accessparamsjs; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class App { + + public static void main(String[] args) { + SpringApplication.run(App.class, args); + } + +} diff --git a/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/Controller.java b/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/Controller.java new file mode 100644 index 0000000000..cc838eb6a5 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/accessparamsjs/Controller.java @@ -0,0 +1,32 @@ +package com.baeldung.accessparamsjs; + +import java.util.Map; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.ModelAndView; + +/** + * Sample rest controller for the tutorial article + * "Access Spring MVC Model object in JavaScript". + * + * @author Andrew Shcherbakov + * + */ +@RestController +public class Controller { + + /** + * Define two model objects (one integer and one string) and pass them to the view. + * + * @param model + * @return + */ + @RequestMapping("/index") + public ModelAndView index(Map model) { + model.put("number", 1234); + model.put("message", "Hello from Spring MVC"); + return new ModelAndView("/index"); + } + +} diff --git a/spring-boot-mvc/src/main/resources/application.properties b/spring-boot-mvc/src/main/resources/application.properties index 709574239b..00362e2588 100644 --- a/spring-boot-mvc/src/main/resources/application.properties +++ b/spring-boot-mvc/src/main/resources/application.properties @@ -1 +1,3 @@ -spring.main.allow-bean-definition-overriding=true \ No newline at end of file +spring.main.allow-bean-definition-overriding=true +spring.mvc.view.prefix=/WEB-INF/jsp/ +spring.mvc.view.suffix=.jsp \ No newline at end of file diff --git a/spring-boot-mvc/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-boot-mvc/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 0000000000..d9f3966e82 --- /dev/null +++ b/spring-boot-mvc/src/main/webapp/WEB-INF/jsp/index.jsp @@ -0,0 +1,27 @@ + +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> + + +Access Spring MVC params + + + + + + +

Data from the external JS file (due to loading order)

+
+
+

Asynchronous loading from external JS file (plain JS)

+
+
+

Asynchronous loading from external JS file (jQuery)

+
+
+ + + + \ No newline at end of file diff --git a/spring-boot-mvc/src/main/webapp/js/jquery.js b/spring-boot-mvc/src/main/webapp/js/jquery.js new file mode 100644 index 0000000000..4d9b3a2587 --- /dev/null +++ b/spring-boot-mvc/src/main/webapp/js/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";var n=[],r=e.document,i=Object.getPrototypeOf,o=n.slice,a=n.concat,s=n.push,u=n.indexOf,l={},c=l.toString,f=l.hasOwnProperty,p=f.toString,d=p.call(Object),h={},g=function e(t){return"function"==typeof t&&"number"!=typeof t.nodeType},y=function e(t){return null!=t&&t===t.window},v={type:!0,src:!0,noModule:!0};function m(e,t,n){var i,o=(t=t||r).createElement("script");if(o.text=e,n)for(i in v)n[i]&&(o[i]=n[i]);t.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[c.call(e)]||"object":typeof e}var b="3.3.1",w=function(e,t){return new w.fn.init(e,t)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;w.fn=w.prototype={jquery:"3.3.1",constructor:w,length:0,toArray:function(){return o.call(this)},get:function(e){return null==e?o.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=w.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return w.each(this,e)},map:function(e){return this.pushStack(w.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(o.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n0&&t-1 in e)}var E=function(e){var t,n,r,i,o,a,s,u,l,c,f,p,d,h,g,y,v,m,x,b="sizzle"+1*new Date,w=e.document,T=0,C=0,E=ae(),k=ae(),S=ae(),D=function(e,t){return e===t&&(f=!0),0},N={}.hasOwnProperty,A=[],j=A.pop,q=A.push,L=A.push,H=A.slice,O=function(e,t){for(var n=0,r=e.length;n+~]|"+M+")"+M+"*"),z=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),X=new RegExp(W),U=new RegExp("^"+R+"$"),V={ID:new RegExp("^#("+R+")"),CLASS:new RegExp("^\\.("+R+")"),TAG:new RegExp("^("+R+"|[*])"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Q=/^[^{]+\{\s*\[native \w/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,K=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ee=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},te=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ne=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},re=function(){p()},ie=me(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{L.apply(A=H.call(w.childNodes),w.childNodes),A[w.childNodes.length].nodeType}catch(e){L={apply:A.length?function(e,t){q.apply(e,H.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function oe(e,t,r,i){var o,s,l,c,f,h,v,m=t&&t.ownerDocument,T=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==T&&9!==T&&11!==T)return r;if(!i&&((t?t.ownerDocument||t:w)!==d&&p(t),t=t||d,g)){if(11!==T&&(f=J.exec(e)))if(o=f[1]){if(9===T){if(!(l=t.getElementById(o)))return r;if(l.id===o)return r.push(l),r}else if(m&&(l=m.getElementById(o))&&x(t,l)&&l.id===o)return r.push(l),r}else{if(f[2])return L.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return L.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!S[e+" "]&&(!y||!y.test(e))){if(1!==T)m=t,v=e;else if("object"!==t.nodeName.toLowerCase()){(c=t.getAttribute("id"))?c=c.replace(te,ne):t.setAttribute("id",c=b),s=(h=a(e)).length;while(s--)h[s]="#"+c+" "+ve(h[s]);v=h.join(","),m=K.test(e)&&ge(t.parentNode)||t}if(v)try{return L.apply(r,m.querySelectorAll(v)),r}catch(e){}finally{c===b&&t.removeAttribute("id")}}}return u(e.replace(B,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ue(e){var t=d.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function ce(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function pe(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&ie(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function he(e){return se(function(t){return t=+t,se(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function ge(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}n=oe.support={},o=oe.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},p=oe.setDocument=function(e){var t,i,a=e?e.ownerDocument||e:w;return a!==d&&9===a.nodeType&&a.documentElement?(d=a,h=d.documentElement,g=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",re,!1):i.attachEvent&&i.attachEvent("onunload",re)),n.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ue(function(e){return e.appendChild(d.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Q.test(d.getElementsByClassName),n.getById=ue(function(e){return h.appendChild(e).id=b,!d.getElementsByName||!d.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(Z,ee);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&g)return t.getElementsByClassName(e)},v=[],y=[],(n.qsa=Q.test(d.querySelectorAll))&&(ue(function(e){h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||y.push("~="),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||y.push(".#.+[+~]")}),ue(function(e){e.innerHTML="";var t=d.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(n.matchesSelector=Q.test(m=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ue(function(e){n.disconnectedMatch=m.call(e,"*"),m.call(e,"[s!='']:x"),v.push("!=",W)}),y=y.length&&new RegExp(y.join("|")),v=v.length&&new RegExp(v.join("|")),t=Q.test(h.compareDocumentPosition),x=t||Q.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===d||e.ownerDocument===w&&x(w,e)?-1:t===d||t.ownerDocument===w&&x(w,t)?1:c?O(c,e)-O(c,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===d?-1:t===d?1:i?-1:o?1:c?O(c,e)-O(c,t):0;if(i===o)return ce(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?ce(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},oe.matches=function(e,t){return oe(e,null,null,t)},oe.matchesSelector=function(e,t){if((e.ownerDocument||e)!==d&&p(e),t=t.replace(z,"='$1']"),n.matchesSelector&&g&&!S[t+" "]&&(!v||!v.test(t))&&(!y||!y.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return oe(t,d,null,[e]).length>0},oe.contains=function(e,t){return(e.ownerDocument||e)!==d&&p(e),x(e,t)},oe.attr=function(e,t){(e.ownerDocument||e)!==d&&p(e);var i=r.attrHandle[t.toLowerCase()],o=i&&N.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},oe.escape=function(e){return(e+"").replace(te,ne)},oe.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},oe.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,c=!n.sortStable&&e.slice(0),e.sort(D),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return c=null,e},i=oe.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=oe.selectors={cacheLength:50,createPseudo:se,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Z,ee),e[3]=(e[3]||e[4]||e[5]||"").replace(Z,ee),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||oe.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&oe.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=a(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Z,ee).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=oe.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace($," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",y=t.parentNode,v=s&&t.nodeName.toLowerCase(),m=!u&&!s,x=!1;if(y){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?y.firstChild:y.lastChild],a&&m){x=(d=(l=(c=(f=(p=y)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1])&&l[2],p=d&&y.childNodes[d];while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if(1===p.nodeType&&++x&&p===t){c[e]=[T,d,x];break}}else if(m&&(x=d=(l=(c=(f=(p=t)[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]||[])[0]===T&&l[1]),!1===x)while(p=++d&&p&&p[g]||(x=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===v:1===p.nodeType)&&++x&&(m&&((c=(f=p[b]||(p[b]={}))[p.uniqueID]||(f[p.uniqueID]={}))[e]=[T,x]),p===t))break;return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||oe.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?se(function(e,n){var r,o=i(e,t),a=o.length;while(a--)e[r=O(e,o[a])]=!(n[r]=o[a])}):function(e){return i(e,0,n)}):i}},pseudos:{not:se(function(e){var t=[],n=[],r=s(e.replace(B,"$1"));return r[b]?se(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:se(function(e){return function(t){return oe(e,t).length>0}}),contains:se(function(e){return e=e.replace(Z,ee),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:se(function(e){return U.test(e||"")||oe.error("unsupported lang: "+e),e=e.replace(Z,ee).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return Y.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:he(function(){return[0]}),last:he(function(e,t){return[t-1]}),eq:he(function(e,t,n){return[n<0?n+t:n]}),even:he(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:he(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function be(e,t,n){for(var r=0,i=t.length;r-1&&(o[l]=!(a[l]=f))}}else v=we(v===a?v.splice(h,v.length):v),i?i(null,a,v,u):L.apply(a,v)})}function Ce(e){for(var t,n,i,o=e.length,a=r.relative[e[0].type],s=a||r.relative[" "],u=a?1:0,c=me(function(e){return e===t},s,!0),f=me(function(e){return O(t,e)>-1},s,!0),p=[function(e,n,r){var i=!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):f(e,n,r));return t=null,i}];u1&&xe(p),u>1&&ve(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(B,"$1"),n,u0,i=e.length>0,o=function(o,a,s,u,c){var f,h,y,v=0,m="0",x=o&&[],b=[],w=l,C=o||i&&r.find.TAG("*",c),E=T+=null==w?1:Math.random()||.1,k=C.length;for(c&&(l=a===d||a||c);m!==k&&null!=(f=C[m]);m++){if(i&&f){h=0,a||f.ownerDocument===d||(p(f),s=!g);while(y=e[h++])if(y(f,a||d,s)){u.push(f);break}c&&(T=E)}n&&((f=!y&&f)&&v--,o&&x.push(f))}if(v+=m,n&&m!==v){h=0;while(y=t[h++])y(x,b,a,s);if(o){if(v>0)while(m--)x[m]||b[m]||(b[m]=j.call(u));b=we(b)}L.apply(u,b),c&&!o&&b.length>0&&v+t.length>1&&oe.uniqueSort(u)}return c&&(T=E,l=w),x};return n?se(o):o}return s=oe.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=a(e)),n=t.length;while(n--)(o=Ce(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ee(i,r))).selector=e}return o},u=oe.select=function(e,t,n,i){var o,u,l,c,f,p="function"==typeof e&&e,d=!i&&a(e=p.selector||e);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(l=u[0]).type&&9===t.nodeType&&g&&r.relative[u[1].type]){if(!(t=(r.find.ID(l.matches[0].replace(Z,ee),t)||[])[0]))return n;p&&(t=t.parentNode),e=e.slice(u.shift().value.length)}o=V.needsContext.test(e)?0:u.length;while(o--){if(l=u[o],r.relative[c=l.type])break;if((f=r.find[c])&&(i=f(l.matches[0].replace(Z,ee),K.test(u[0].type)&&ge(t.parentNode)||t))){if(u.splice(o,1),!(e=i.length&&ve(u)))return L.apply(n,i),n;break}}}return(p||s(e,d))(i,t,!g,n,!t||K.test(e)&&ge(t.parentNode)||t),n},n.sortStable=b.split("").sort(D).join("")===b,n.detectDuplicates=!!f,p(),n.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(d.createElement("fieldset"))}),ue(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||le("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ue(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||le("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||le(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),oe}(e);w.find=E,w.expr=E.selectors,w.expr[":"]=w.expr.pseudos,w.uniqueSort=w.unique=E.uniqueSort,w.text=E.getText,w.isXMLDoc=E.isXML,w.contains=E.contains,w.escapeSelector=E.escape;var k=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&w(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},D=w.expr.match.needsContext;function N(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var A=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,t,n){return g(t)?w.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?w.grep(e,function(e){return e===t!==n}):"string"!=typeof t?w.grep(e,function(e){return u.call(t,e)>-1!==n}):w.filter(t,e,n)}w.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?w.find.matchesSelector(r,e)?[r]:[]:w.find.matches(e,w.grep(t,function(e){return 1===e.nodeType}))},w.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(w(e).filter(function(){for(t=0;t1?w.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&D.test(e)?w(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(w.fn.init=function(e,t,n){var i,o;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(i="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:L.exec(e))||!i[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(i[1]){if(t=t instanceof w?t[0]:t,w.merge(this,w.parseHTML(i[1],t&&t.nodeType?t.ownerDocument||t:r,!0)),A.test(i[1])&&w.isPlainObject(t))for(i in t)g(this[i])?this[i](t[i]):this.attr(i,t[i]);return this}return(o=r.getElementById(i[2]))&&(this[0]=o,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==n.ready?n.ready(e):e(w):w.makeArray(e,this)}).prototype=w.fn,q=w(r);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};w.fn.extend({has:function(e){var t=w(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&w.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?w.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?u.call(w(e),this[0]):u.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(w.uniqueSort(w.merge(this.get(),w(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}w.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return k(e,"parentNode")},parentsUntil:function(e,t,n){return k(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return k(e,"nextSibling")},prevAll:function(e){return k(e,"previousSibling")},nextUntil:function(e,t,n){return k(e,"nextSibling",n)},prevUntil:function(e,t,n){return k(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return N(e,"iframe")?e.contentDocument:(N(e,"template")&&(e=e.content||e),w.merge([],e.childNodes))}},function(e,t){w.fn[e]=function(n,r){var i=w.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=w.filter(r,i)),this.length>1&&(O[e]||w.uniqueSort(i),H.test(e)&&i.reverse()),this.pushStack(i)}});var M=/[^\x20\t\r\n\f]+/g;function R(e){var t={};return w.each(e.match(M)||[],function(e,n){t[n]=!0}),t}w.Callbacks=function(e){e="string"==typeof e?R(e):w.extend({},e);var t,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||e.once,r=t=!0;a.length;s=-1){n=a.shift();while(++s-1)o.splice(n,1),n<=s&&s--}),this},has:function(e){return e?w.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=[e,(n=n||[]).slice?n.slice():n],a.push(n),t||u()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l};function I(e){return e}function W(e){throw e}function $(e,t,n,r){var i;try{e&&g(i=e.promise)?i.call(e).done(t).fail(n):e&&g(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}w.extend({Deferred:function(t){var n=[["notify","progress",w.Callbacks("memory"),w.Callbacks("memory"),2],["resolve","done",w.Callbacks("once memory"),w.Callbacks("once memory"),0,"resolved"],["reject","fail",w.Callbacks("once memory"),w.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return w.Deferred(function(t){w.each(n,function(n,r){var i=g(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t=o&&(r!==W&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(w.Deferred.getStackHook&&(c.stackTrace=w.Deferred.getStackHook()),e.setTimeout(c))}}return w.Deferred(function(e){n[0][3].add(a(0,e,g(i)?i:I,e.notifyWith)),n[1][3].add(a(0,e,g(t)?t:I)),n[2][3].add(a(0,e,g(r)?r:W))}).promise()},promise:function(e){return null!=e?w.extend(e,i):i}},o={};return w.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=o.call(arguments),a=w.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?o.call(arguments):n,--t||a.resolveWith(r,i)}};if(t<=1&&($(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||g(i[n]&&i[n].then)))return a.then();while(n--)$(i[n],s(n),a.reject);return a.promise()}});var B=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;w.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&B.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},w.readyException=function(t){e.setTimeout(function(){throw t})};var F=w.Deferred();w.fn.ready=function(e){return F.then(e)["catch"](function(e){w.readyException(e)}),this},w.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--w.readyWait:w.isReady)||(w.isReady=!0,!0!==e&&--w.readyWait>0||F.resolveWith(r,[w]))}}),w.ready.then=F.then;function _(){r.removeEventListener("DOMContentLoaded",_),e.removeEventListener("load",_),w.ready()}"complete"===r.readyState||"loading"!==r.readyState&&!r.documentElement.doScroll?e.setTimeout(w.ready):(r.addEventListener("DOMContentLoaded",_),e.addEventListener("load",_));var z=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n)){i=!0;for(s in n)z(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,g(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(w(e),n)})),t))for(;s1,null,!0)},removeData:function(e){return this.each(function(){K.remove(this,e)})}}),w.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=J.get(e,t),n&&(!r||Array.isArray(n)?r=J.access(e,t,w.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=w.queue(e,t),r=n.length,i=n.shift(),o=w._queueHooks(e,t),a=function(){w.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return J.get(e,n)||J.access(e,n,{empty:w.Callbacks("once memory").add(function(){J.remove(e,[t+"queue",n])})})}}),w.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&N(e,t)?w.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n-1)i&&i.push(o);else if(l=w.contains(o.ownerDocument,o),a=ye(f.appendChild(o),"script"),l&&ve(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}!function(){var e=r.createDocumentFragment().appendChild(r.createElement("div")),t=r.createElement("input");t.setAttribute("type","radio"),t.setAttribute("checked","checked"),t.setAttribute("name","t"),e.appendChild(t),h.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="",h.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var be=r.documentElement,we=/^key/,Te=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ce=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function ke(){return!1}function Se(){try{return r.activeElement}catch(e){}}function De(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)De(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=ke;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return w().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=w.guid++)),e.each(function(){w.event.add(this,t,i,r,n)})}w.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.get(e);if(y){n.handler&&(n=(o=n).handler,i=o.selector),i&&w.find.matchesSelector(be,i),n.guid||(n.guid=w.guid++),(u=y.events)||(u=y.events={}),(a=y.handle)||(a=y.handle=function(t){return"undefined"!=typeof w&&w.event.triggered!==t.type?w.event.dispatch.apply(e,arguments):void 0}),l=(t=(t||"").match(M)||[""]).length;while(l--)d=g=(s=Ce.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=w.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=w.event.special[d]||{},c=w.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&w.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,a)||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),w.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,y=J.hasData(e)&&J.get(e);if(y&&(u=y.events)){l=(t=(t||"").match(M)||[""]).length;while(l--)if(s=Ce.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){f=w.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,y.handle)||w.removeEvent(e,d,y.handle),delete u[d])}else for(d in u)w.event.remove(e,d+t[l],n,r,!0);w.isEmptyObject(u)&&J.remove(e,"handle events")}},dispatch:function(e){var t=w.event.fix(e),n,r,i,o,a,s,u=new Array(arguments.length),l=(J.get(this,"events")||{})[t.type]||[],c=w.event.special[t.type]||{};for(u[0]=t,n=1;n=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n-1:w.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,Ae=/\s*$/g;function Le(e,t){return N(e,"table")&&N(11!==t.nodeType?t:t.firstChild,"tr")?w(e).children("tbody")[0]||e:e}function He(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Oe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Pe(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(J.hasData(e)&&(o=J.access(e),a=J.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n1&&"string"==typeof y&&!h.checkClone&&je.test(y))return e.each(function(i){var o=e.eq(i);v&&(t[0]=y.call(this,i,o.html())),Re(o,t,n,r)});if(p&&(i=xe(t,e[0].ownerDocument,!1,e,r),o=i.firstChild,1===i.childNodes.length&&(i=o),o||r)){for(u=(s=w.map(ye(i,"script"),He)).length;f")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=w.contains(e.ownerDocument,e);if(!(h.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||w.isXMLDoc(e)))for(a=ye(s),r=0,i=(o=ye(e)).length;r0&&ve(a,!u&&ye(e,"script")),s},cleanData:function(e){for(var t,n,r,i=w.event.special,o=0;void 0!==(n=e[o]);o++)if(Y(n)){if(t=n[J.expando]){if(t.events)for(r in t.events)i[r]?w.event.remove(n,r):w.removeEvent(n,r,t.handle);n[J.expando]=void 0}n[K.expando]&&(n[K.expando]=void 0)}}}),w.fn.extend({detach:function(e){return Ie(this,e,!0)},remove:function(e){return Ie(this,e)},text:function(e){return z(this,function(e){return void 0===e?w.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Re(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Le(this,e).appendChild(e)})},prepend:function(){return Re(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Le(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Re(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(w.cleanData(ye(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return w.clone(this,e,t)})},html:function(e){return z(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ae.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=w.htmlPrefilter(e);try{for(;n=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))),u}function et(e,t,n){var r=$e(e),i=Fe(e,t,r),o="border-box"===w.css(e,"boxSizing",!1,r),a=o;if(We.test(i)){if(!n)return i;i="auto"}return a=a&&(h.boxSizingReliable()||i===e.style[t]),("auto"===i||!parseFloat(i)&&"inline"===w.css(e,"display",!1,r))&&(i=e["offset"+t[0].toUpperCase()+t.slice(1)],a=!0),(i=parseFloat(i)||0)+Ze(e,t,n||(o?"border":"content"),a,r,i)+"px"}w.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Fe(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=G(t),u=Xe.test(t),l=e.style;if(u||(t=Je(s)),a=w.cssHooks[t]||w.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"==(o=typeof n)&&(i=ie.exec(n))&&i[1]&&(n=ue(e,t,i),o="number"),null!=n&&n===n&&("number"===o&&(n+=i&&i[3]||(w.cssNumber[s]?"":"px")),h.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=G(t);return Xe.test(t)||(t=Je(s)),(a=w.cssHooks[t]||w.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Fe(e,t,r)),"normal"===i&&t in Ve&&(i=Ve[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),w.each(["height","width"],function(e,t){w.cssHooks[t]={get:function(e,n,r){if(n)return!ze.test(w.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?et(e,t,r):se(e,Ue,function(){return et(e,t,r)})},set:function(e,n,r){var i,o=$e(e),a="border-box"===w.css(e,"boxSizing",!1,o),s=r&&Ze(e,t,r,a,o);return a&&h.scrollboxSize()===o.position&&(s-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(o[t])-Ze(e,t,"border",!1,o)-.5)),s&&(i=ie.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=w.css(e,t)),Ke(e,n,s)}}}),w.cssHooks.marginLeft=_e(h.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Fe(e,"marginLeft"))||e.getBoundingClientRect().left-se(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),w.each({margin:"",padding:"",border:"Width"},function(e,t){w.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+oe[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(w.cssHooks[e+t].set=Ke)}),w.fn.extend({css:function(e,t){return z(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=$e(e),i=t.length;a1)}});function tt(e,t,n,r,i){return new tt.prototype.init(e,t,n,r,i)}w.Tween=tt,tt.prototype={constructor:tt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||w.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(w.cssNumber[n]?"":"px")},cur:function(){var e=tt.propHooks[this.prop];return e&&e.get?e.get(this):tt.propHooks._default.get(this)},run:function(e){var t,n=tt.propHooks[this.prop];return this.options.duration?this.pos=t=w.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tt.propHooks._default.set(this),this}},tt.prototype.init.prototype=tt.prototype,tt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=w.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){w.fx.step[e.prop]?w.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[w.cssProps[e.prop]]&&!w.cssHooks[e.prop]?e.elem[e.prop]=e.now:w.style(e.elem,e.prop,e.now+e.unit)}}},tt.propHooks.scrollTop=tt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},w.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},w.fx=tt.prototype.init,w.fx.step={};var nt,rt,it=/^(?:toggle|show|hide)$/,ot=/queueHooks$/;function at(){rt&&(!1===r.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(at):e.setTimeout(at,w.fx.interval),w.fx.tick())}function st(){return e.setTimeout(function(){nt=void 0}),nt=Date.now()}function ut(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=oe[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function lt(e,t,n){for(var r,i=(pt.tweeners[t]||[]).concat(pt.tweeners["*"]),o=0,a=i.length;o1)},removeAttr:function(e){return this.each(function(){w.removeAttr(this,e)})}}),w.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?w.prop(e,t,n):(1===o&&w.isXMLDoc(e)||(i=w.attrHooks[t.toLowerCase()]||(w.expr.match.bool.test(t)?dt:void 0)),void 0!==n?null===n?void w.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=w.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!h.radioValue&&"radio"===t&&N(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(M);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),dt={set:function(e,t,n){return!1===t?w.removeAttr(e,n):e.setAttribute(n,n),n}},w.each(w.expr.match.bool.source.match(/\w+/g),function(e,t){var n=ht[t]||w.find.attr;ht[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=ht[a],ht[a]=i,i=null!=n(e,t,r)?a:null,ht[a]=o),i}});var gt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;w.fn.extend({prop:function(e,t){return z(this,w.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[w.propFix[e]||e]})}}),w.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&w.isXMLDoc(e)||(t=w.propFix[t]||t,i=w.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=w.find.attr(e,"tabindex");return t?parseInt(t,10):gt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),h.optSelected||(w.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),w.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){w.propFix[this.toLowerCase()]=this});function vt(e){return(e.match(M)||[]).join(" ")}function mt(e){return e.getAttribute&&e.getAttribute("class")||""}function xt(e){return Array.isArray(e)?e:"string"==typeof e?e.match(M)||[]:[]}w.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).addClass(e.call(this,t,mt(this)))});if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(g(e))return this.each(function(t){w(this).removeClass(e.call(this,t,mt(this)))});if(!arguments.length)return this.attr("class","");if((t=xt(e)).length)while(n=this[u++])if(i=mt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=t[a++])while(r.indexOf(" "+o+" ")>-1)r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e,r="string"===n||Array.isArray(e);return"boolean"==typeof t&&r?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(n){w(this).toggleClass(e.call(this,n,mt(this),t),t)}):this.each(function(){var t,i,o,a;if(r){i=0,o=w(this),a=xt(e);while(t=a[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else void 0!==e&&"boolean"!==n||((t=mt(this))&&J.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":J.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&(" "+vt(mt(n))+" ").indexOf(t)>-1)return!0;return!1}});var bt=/\r/g;w.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=g(e),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,w(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=w.map(i,function(e){return null==e?"":e+""})),(t=w.valHooks[this.type]||w.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))});if(i)return(t=w.valHooks[i.type]||w.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(bt,""):null==n?"":n}}}),w.extend({valHooks:{option:{get:function(e){var t=w.find.attr(e,"value");return null!=t?t:vt(w.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),w.each(["radio","checkbox"],function(){w.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=w.inArray(w(e).val(),t)>-1}},h.checkOn||(w.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),h.focusin="onfocusin"in e;var wt=/^(?:focusinfocus|focusoutblur)$/,Tt=function(e){e.stopPropagation()};w.extend(w.event,{trigger:function(t,n,i,o){var a,s,u,l,c,p,d,h,v=[i||r],m=f.call(t,"type")?t.type:t,x=f.call(t,"namespace")?t.namespace.split("."):[];if(s=h=u=i=i||r,3!==i.nodeType&&8!==i.nodeType&&!wt.test(m+w.event.triggered)&&(m.indexOf(".")>-1&&(m=(x=m.split(".")).shift(),x.sort()),c=m.indexOf(":")<0&&"on"+m,t=t[w.expando]?t:new w.Event(m,"object"==typeof t&&t),t.isTrigger=o?2:3,t.namespace=x.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+x.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:w.makeArray(n,[t]),d=w.event.special[m]||{},o||!d.trigger||!1!==d.trigger.apply(i,n))){if(!o&&!d.noBubble&&!y(i)){for(l=d.delegateType||m,wt.test(l+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(i.ownerDocument||r)&&v.push(u.defaultView||u.parentWindow||e)}a=0;while((s=v[a++])&&!t.isPropagationStopped())h=s,t.type=a>1?l:d.bindType||m,(p=(J.get(s,"events")||{})[t.type]&&J.get(s,"handle"))&&p.apply(s,n),(p=c&&s[c])&&p.apply&&Y(s)&&(t.result=p.apply(s,n),!1===t.result&&t.preventDefault());return t.type=m,o||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(v.pop(),n)||!Y(i)||c&&g(i[m])&&!y(i)&&((u=i[c])&&(i[c]=null),w.event.triggered=m,t.isPropagationStopped()&&h.addEventListener(m,Tt),i[m](),t.isPropagationStopped()&&h.removeEventListener(m,Tt),w.event.triggered=void 0,u&&(i[c]=u)),t.result}},simulate:function(e,t,n){var r=w.extend(new w.Event,n,{type:e,isSimulated:!0});w.event.trigger(r,null,t)}}),w.fn.extend({trigger:function(e,t){return this.each(function(){w.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return w.event.trigger(e,t,n,!0)}}),h.focusin||w.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){w.event.simulate(t,e.target,w.event.fix(e))};w.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=J.access(r,t);i||r.addEventListener(e,n,!0),J.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=J.access(r,t)-1;i?J.access(r,t,i):(r.removeEventListener(e,n,!0),J.remove(r,t))}}});var Ct=e.location,Et=Date.now(),kt=/\?/;w.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||w.error("Invalid XML: "+t),n};var St=/\[\]$/,Dt=/\r?\n/g,Nt=/^(?:submit|button|image|reset|file)$/i,At=/^(?:input|select|textarea|keygen)/i;function jt(e,t,n,r){var i;if(Array.isArray(t))w.each(t,function(t,i){n||St.test(e)?r(e,i):jt(e+"["+("object"==typeof i&&null!=i?t:"")+"]",i,n,r)});else if(n||"object"!==x(t))r(e,t);else for(i in t)jt(e+"["+i+"]",t[i],n,r)}w.param=function(e,t){var n,r=[],i=function(e,t){var n=g(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!w.isPlainObject(e))w.each(e,function(){i(this.name,this.value)});else for(n in e)jt(n,e[n],t,i);return r.join("&")},w.fn.extend({serialize:function(){return w.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=w.prop(this,"elements");return e?w.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!w(this).is(":disabled")&&At.test(this.nodeName)&&!Nt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=w(this).val();return null==n?null:Array.isArray(n)?w.map(n,function(e){return{name:t.name,value:e.replace(Dt,"\r\n")}}):{name:t.name,value:n.replace(Dt,"\r\n")}}).get()}});var qt=/%20/g,Lt=/#.*$/,Ht=/([?&])_=[^&]*/,Ot=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Mt=/^(?:GET|HEAD)$/,Rt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Bt=r.createElement("a");Bt.href=Ct.href;function Ft(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(M)||[];if(g(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function _t(e,t,n,r){var i={},o=e===Wt;function a(s){var u;return i[s]=!0,w.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function zt(e,t){var n,r,i=w.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&w.extend(!0,e,r),e}function Xt(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}function Ut(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}w.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Pt.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":w.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,w.ajaxSettings),t):zt(w.ajaxSettings,e)},ajaxPrefilter:Ft(It),ajaxTransport:Ft(Wt),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=w.ajaxSetup({},n),g=h.context||h,y=h.context&&(g.nodeType||g.jquery)?w(g):w.event,v=w.Deferred(),m=w.Callbacks("once memory"),x=h.statusCode||{},b={},T={},C="canceled",E={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s){s={};while(t=Ot.exec(a))s[t[1].toLowerCase()]=t[2]}t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=T[e.toLowerCase()]=T[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)E.always(e[E.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return i&&i.abort(t),k(0,t),this}};if(v.promise(E),h.url=((t||h.url||Ct.href)+"").replace(Rt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(M)||[""],null==h.crossDomain){l=r.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Bt.protocol+"//"+Bt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=w.param(h.data,h.traditional)),_t(It,h,n,E),c)return E;(f=w.event&&h.global)&&0==w.active++&&w.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Mt.test(h.type),o=h.url.replace(Lt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(qt,"+")):(d=h.url.slice(o.length),h.data&&(h.processData||"string"==typeof h.data)&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(Ht,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et+++d),h.url=o+d),h.ifModified&&(w.lastModified[o]&&E.setRequestHeader("If-Modified-Since",w.lastModified[o]),w.etag[o]&&E.setRequestHeader("If-None-Match",w.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&E.setRequestHeader("Content-Type",h.contentType),E.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+$t+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)E.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(g,E,h)||c))return E.abort();if(C="abort",m.add(h.complete),E.done(h.success),E.fail(h.error),i=_t(Wt,h,n,E)){if(E.readyState=1,f&&y.trigger("ajaxSend",[E,h]),c)return E;h.async&&h.timeout>0&&(u=e.setTimeout(function(){E.abort("timeout")},h.timeout));try{c=!1,i.send(b,k)}catch(e){if(c)throw e;k(-1,e)}}else k(-1,"No Transport");function k(t,n,r,s){var l,p,d,b,T,C=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",E.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=Xt(h,E,r)),b=Ut(h,b,E,l),l?(h.ifModified&&((T=E.getResponseHeader("Last-Modified"))&&(w.lastModified[o]=T),(T=E.getResponseHeader("etag"))&&(w.etag[o]=T)),204===t||"HEAD"===h.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,l=!(d=b.error))):(d=C,!t&&C||(C="error",t<0&&(t=0))),E.status=t,E.statusText=(n||C)+"",l?v.resolveWith(g,[p,C,E]):v.rejectWith(g,[E,C,d]),E.statusCode(x),x=void 0,f&&y.trigger(l?"ajaxSuccess":"ajaxError",[E,h,l?p:d]),m.fireWith(g,[E,C]),f&&(y.trigger("ajaxComplete",[E,h]),--w.active||w.event.trigger("ajaxStop")))}return E},getJSON:function(e,t,n){return w.get(e,t,n,"json")},getScript:function(e,t){return w.get(e,void 0,t,"script")}}),w.each(["get","post"],function(e,t){w[t]=function(e,n,r,i){return g(n)&&(i=i||r,r=n,n=void 0),w.ajax(w.extend({url:e,type:t,dataType:i,data:n,success:r},w.isPlainObject(e)&&e))}}),w._evalUrl=function(e){return w.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},w.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=w(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){w(this).wrapInner(e.call(this,t))}):this.each(function(){var t=w(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(n){w(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){w(this).replaceWith(this.childNodes)}),this}}),w.expr.pseudos.hidden=function(e){return!w.expr.pseudos.visible(e)},w.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},w.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Vt={0:200,1223:204},Gt=w.ajaxSettings.xhr();h.cors=!!Gt&&"withCredentials"in Gt,h.ajax=Gt=!!Gt,w.ajaxTransport(function(t){var n,r;if(h.cors||Gt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(Vt[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=s.ontimeout=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),w.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),w.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return w.globalEval(e),e}}}),w.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),w.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(i,o){t=w("