diff --git a/apache-shiro/pom.xml b/apache-shiro/pom.xml
index 97ed872a26..711ddb5cee 100644
--- a/apache-shiro/pom.xml
+++ b/apache-shiro/pom.xml
@@ -9,9 +9,9 @@
1.0-SNAPSHOT
- com.baeldung
- parent-modules
- 1.0.0-SNAPSHOT
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.2.RELEASE
@@ -21,6 +21,19 @@
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-freemarker
+
+
+ org.apache.shiro
+ shiro-spring-boot-web-starter
+ ${apache-shiro-core-version}
+
org.apache.shiro
shiro-core
diff --git a/apache-shiro/src/main/java/com/baeldung/ShiroSpringApplication.java b/apache-shiro/src/main/java/com/baeldung/ShiroSpringApplication.java
new file mode 100644
index 0000000000..e12d3ebffa
--- /dev/null
+++ b/apache-shiro/src/main/java/com/baeldung/ShiroSpringApplication.java
@@ -0,0 +1,45 @@
+package com.baeldung;
+
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
+import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * Created by smatt on 21/08/2017.
+ */
+@SpringBootApplication
+public class ShiroSpringApplication {
+
+ private static final transient Logger log = LoggerFactory.getLogger(ShiroSpringApplication.class);
+
+ public static void main(String... args) {
+ SpringApplication.run(ShiroSpringApplication.class, args);
+ }
+
+
+ @Bean
+ public Realm realm() {
+ return new MyCustomRealm();
+ }
+
+
+ @Bean
+ public ShiroFilterChainDefinition shiroFilterChainDefinition() {
+ DefaultShiroFilterChainDefinition filter
+ = new DefaultShiroFilterChainDefinition();
+
+ filter.addPathDefinition("/secure", "authc");
+ filter.addPathDefinition("/**", "anon");
+
+ return filter;
+ }
+
+
+
+
+}
diff --git a/apache-shiro/src/main/java/com/baeldung/controllers/ShiroSpringController.java b/apache-shiro/src/main/java/com/baeldung/controllers/ShiroSpringController.java
new file mode 100644
index 0000000000..e6e72b2579
--- /dev/null
+++ b/apache-shiro/src/main/java/com/baeldung/controllers/ShiroSpringController.java
@@ -0,0 +1,105 @@
+package com.baeldung.controllers;
+
+import com.baeldung.models.UserCredentials;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.subject.Subject;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+@Controller
+public class ShiroSpringController {
+
+
+
+ @GetMapping("/")
+ public String index() {
+ return "index";
+ }
+
+
+ @RequestMapping( value = "/login", method = {RequestMethod.GET, RequestMethod.POST})
+ public String login(HttpServletRequest req, UserCredentials cred, RedirectAttributes attr) {
+
+ if(req.getMethod().equals(RequestMethod.GET.toString())) {
+ return "login";
+ }
+ else {
+
+ Subject subject = SecurityUtils.getSubject();
+
+ if(!subject.isAuthenticated()) {
+ UsernamePasswordToken token = new UsernamePasswordToken(
+ cred.getUsername(), cred.getPassword(), cred.isRememberMe());
+ try {
+ subject.login(token);
+ } catch (AuthenticationException ae) {
+ ae.printStackTrace();
+ attr.addFlashAttribute("error", "Invalid Credentials");
+ return "redirect:/login";
+ }
+ }
+
+ return "redirect:/secure";
+ }
+ }
+
+
+ @GetMapping("/secure")
+ public String secure(ModelMap modelMap) {
+
+ Subject currentUser = SecurityUtils.getSubject();
+ String role = "", permission = "";
+
+ if(currentUser.hasRole("admin")) {
+ role = role + "You are an Admin";
+ }
+ else if(currentUser.hasRole("editor")) {
+ role = role + "You are an Editor";
+ }
+ else if(currentUser.hasRole("author")) {
+ role = role + "You are an Author";
+ }
+
+ if(currentUser.isPermitted("articles:compose")) {
+ permission = permission + "You can compose an article, ";
+ } else {
+ permission = permission + "You are not permitted to compose an article!, ";
+ }
+
+ if(currentUser.isPermitted("articles:save")) {
+ permission = permission + "You can save articles, ";
+ } else {
+ permission = permission + "\nYou can not save articles, ";
+ }
+
+ if(currentUser.isPermitted("articles:publish")) {
+ permission = permission + "\nYou can publish articles";
+ } else {
+ permission = permission + "\nYou can not publish articles";
+ }
+
+ modelMap.addAttribute("username", currentUser.getPrincipal());
+ modelMap.addAttribute("permission", permission);
+ modelMap.addAttribute("role", role);
+
+ return "secure";
+ }
+
+
+ @PostMapping("/logout")
+ public String logout() {
+ Subject subject = SecurityUtils.getSubject();
+ subject.logout();
+ return "redirect:/";
+ }
+
+}
diff --git a/apache-shiro/src/main/java/com/baeldung/models/UserCredentials.java b/apache-shiro/src/main/java/com/baeldung/models/UserCredentials.java
new file mode 100644
index 0000000000..51b429046a
--- /dev/null
+++ b/apache-shiro/src/main/java/com/baeldung/models/UserCredentials.java
@@ -0,0 +1,40 @@
+package com.baeldung.models;
+
+public class UserCredentials {
+
+ private String username;
+ private String password;
+ private boolean rememberMe = false;
+
+ public UserCredentials() {}
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public boolean isRememberMe() {
+ return rememberMe;
+ }
+
+ public void setRememberMe(boolean rememberMe) {
+ this.rememberMe = rememberMe;
+ }
+
+ @Override
+ public String toString() {
+ return "username = " + getUsername()
+ + "\nrememberMe = " + isRememberMe();
+ }
+}
diff --git a/apache-shiro/src/main/resources/application.properties b/apache-shiro/src/main/resources/application.properties
new file mode 100644
index 0000000000..5bcb6b3352
--- /dev/null
+++ b/apache-shiro/src/main/resources/application.properties
@@ -0,0 +1,11 @@
+server.port=9000
+server.servlet-path=/
+server.context-path=/
+
+#shiro-spring-boot-config
+shiro.loginUrl = /login
+shiro.successUrl = /secure
+shiro.unauthorizedUrl = /login
+
+#freemarker
+spring.freemarker.suffix=.ftl
diff --git a/apache-shiro/src/main/resources/templates/index.ftl b/apache-shiro/src/main/resources/templates/index.ftl
new file mode 100644
index 0000000000..0210d656fc
--- /dev/null
+++ b/apache-shiro/src/main/resources/templates/index.ftl
@@ -0,0 +1,10 @@
+
+
+ Index
+
+
+ Welcome Guest!
+
+ Login
+
+
\ No newline at end of file
diff --git a/apache-shiro/src/main/resources/templates/login.ftl b/apache-shiro/src/main/resources/templates/login.ftl
new file mode 100644
index 0000000000..3a0552dc2e
--- /dev/null
+++ b/apache-shiro/src/main/resources/templates/login.ftl
@@ -0,0 +1,27 @@
+
+
+ Login
+
+
+Login
+
+
+
+
\ No newline at end of file
diff --git a/apache-shiro/src/main/resources/templates/secure.ftl b/apache-shiro/src/main/resources/templates/secure.ftl
new file mode 100644
index 0000000000..4466a0162f
--- /dev/null
+++ b/apache-shiro/src/main/resources/templates/secure.ftl
@@ -0,0 +1,15 @@
+
+
+ Secure
+
+
+Welcome ${username}!
+Role: ${role}
+Permissions
+${permission}
+
+
+
+
\ No newline at end of file
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
index 38633011bf..e3a1629ce1 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithLock.java
@@ -3,11 +3,11 @@ package com.baeldung.concurrent.atomic;
public class SafeCounterWithLock {
private volatile int counter;
- public int getValue() {
+ int getValue() {
return counter;
}
- public synchronized void increment() {
+ synchronized void increment() {
counter++;
}
}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
index 41e10789a6..18ade35efb 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/SafeCounterWithoutLock.java
@@ -5,11 +5,11 @@ import java.util.concurrent.atomic.AtomicInteger;
public class SafeCounterWithoutLock {
private final AtomicInteger counter = new AtomicInteger(0);
- public int getValue() {
+ int getValue() {
return counter.get();
}
- public void increment() {
+ void increment() {
while(true) {
int existingValue = getValue();
int newValue = existingValue + 1;
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java
index 8a72788842..500ef5bd7e 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/atomic/UnsafeCounter.java
@@ -1,13 +1,13 @@
package com.baeldung.concurrent.atomic;
public class UnsafeCounter {
- int counter;
+ private int counter;
- public int getValue() {
+ int getValue() {
return counter;
}
- public void increment() {
+ void increment() {
counter++;
}
}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/Context.java b/core-java-concurrency/src/main/java/com/baeldung/threadlocal/Context.java
index 241fb2f1e0..88b78fb259 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/Context.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/threadlocal/Context.java
@@ -4,14 +4,14 @@ package com.baeldung.threadlocal;
public class Context {
private final String userName;
- public Context(String userName) {
+ Context(String userName) {
this.userName = userName;
}
@Override
public String toString() {
return "Context{" +
- "userNameSecret='" + userName + '\'' +
- '}';
+ "userNameSecret='" + userName + '\'' +
+ '}';
}
}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java b/core-java-concurrency/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java
index e5854e218a..8cb4b3968f 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java
@@ -5,11 +5,11 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SharedMapWithUserContext implements Runnable {
- public final static Map userContextPerUserId = new ConcurrentHashMap<>();
+ final static Map userContextPerUserId = new ConcurrentHashMap<>();
private final Integer userId;
private UserRepository userRepository = new UserRepository();
- public SharedMapWithUserContext(Integer userId) {
+ SharedMapWithUserContext(Integer userId) {
this.userId = userId;
}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java b/core-java-concurrency/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java
index de7e4a0369..d4ab906c30 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java
@@ -10,7 +10,7 @@ public class ThreadLocalWithUserContext implements Runnable {
private final Integer userId;
private UserRepository userRepository = new UserRepository();
- public ThreadLocalWithUserContext(Integer userId) {
+ ThreadLocalWithUserContext(Integer userId) {
this.userId = userId;
}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/UserRepository.java b/core-java-concurrency/src/main/java/com/baeldung/threadlocal/UserRepository.java
index 3fe76f75c0..2597594940 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/threadlocal/UserRepository.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/threadlocal/UserRepository.java
@@ -4,7 +4,7 @@ import java.util.UUID;
public class UserRepository {
- public String getUserNameForUserId(Integer userId) {
+ String getUserNameForUserId(Integer userId) {
return UUID.randomUUID().toString();
}
}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/threadpool/CountingTask.java b/core-java-concurrency/src/main/java/com/baeldung/threadpool/CountingTask.java
index effdf54916..a7447d040f 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/threadpool/CountingTask.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/threadpool/CountingTask.java
@@ -2,19 +2,21 @@ package com.baeldung.threadpool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
-import java.util.stream.Collectors;
public class CountingTask extends RecursiveTask {
private final TreeNode node;
- public CountingTask(TreeNode node) {
+ CountingTask(TreeNode node) {
this.node = node;
}
@Override
protected Integer compute() {
- return node.value + node.children.stream().map(childNode -> new CountingTask(childNode).fork()).collect(Collectors.summingInt(ForkJoinTask::join));
+ return node.getValue() + node.getChildren().stream()
+ .map(childNode -> new CountingTask(childNode).fork())
+ .mapToInt(ForkJoinTask::join)
+ .sum();
}
}
diff --git a/core-java-concurrency/src/main/java/com/baeldung/transferqueue/Consumer.java b/core-java-concurrency/src/main/java/com/baeldung/transferqueue/Consumer.java
index a5f70d9df5..f3be6a030e 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/transferqueue/Consumer.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/transferqueue/Consumer.java
@@ -11,10 +11,10 @@ public class Consumer implements Runnable {
private final TransferQueue transferQueue;
private final String name;
- private final int numberOfMessagesToConsume;
- public final AtomicInteger numberOfConsumedMessages = new AtomicInteger();
+ final int numberOfMessagesToConsume;
+ final AtomicInteger numberOfConsumedMessages = new AtomicInteger();
- public Consumer(TransferQueue transferQueue, String name, int numberOfMessagesToConsume) {
+ Consumer(TransferQueue transferQueue, String name, int numberOfMessagesToConsume) {
this.transferQueue = transferQueue;
this.name = name;
this.numberOfMessagesToConsume = numberOfMessagesToConsume;
diff --git a/core-java-concurrency/src/main/java/com/baeldung/transferqueue/Producer.java b/core-java-concurrency/src/main/java/com/baeldung/transferqueue/Producer.java
index c7df7c410a..b73cf5ac19 100644
--- a/core-java-concurrency/src/main/java/com/baeldung/transferqueue/Producer.java
+++ b/core-java-concurrency/src/main/java/com/baeldung/transferqueue/Producer.java
@@ -12,10 +12,10 @@ public class Producer implements Runnable {
private final TransferQueue transferQueue;
private final String name;
- private final Integer numberOfMessagesToProduce;
- public final AtomicInteger numberOfProducedMessages = new AtomicInteger();
+ final Integer numberOfMessagesToProduce;
+ final AtomicInteger numberOfProducedMessages = new AtomicInteger();
- public Producer(TransferQueue transferQueue, String name, Integer numberOfMessagesToProduce) {
+ Producer(TransferQueue transferQueue, String name, Integer numberOfMessagesToProduce) {
this.transferQueue = transferQueue;
this.name = name;
this.numberOfMessagesToProduce = numberOfMessagesToProduce;
diff --git a/core-java-concurrency/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java b/core-java-concurrency/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java
index 0a6d94e126..45d2ec68e4 100644
--- a/core-java-concurrency/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java
+++ b/core-java-concurrency/src/test/java/com/baeldung/completablefuture/CompletableFutureLongRunningUnitTest.java
@@ -4,7 +4,11 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.concurrent.*;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.stream.Stream;
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java b/core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java
index fc343e4cee..d49a8b8590 100644
--- a/core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java
+++ b/core-java-concurrency/src/test/java/com/baeldung/concurrent/countdownlatch/CountdownLatchExampleIntegrationTest.java
@@ -18,7 +18,9 @@ public class CountdownLatchExampleIntegrationTest {
// Given
List outputScraper = Collections.synchronizedList(new ArrayList<>());
CountDownLatch countDownLatch = new CountDownLatch(5);
- List workers = Stream.generate(() -> new Thread(new Worker(outputScraper, countDownLatch))).limit(5).collect(toList());
+ List workers = Stream.generate(() -> new Thread(new Worker(outputScraper, countDownLatch)))
+ .limit(5)
+ .collect(toList());
// When
workers.forEach(Thread::start);
@@ -26,7 +28,6 @@ public class CountdownLatchExampleIntegrationTest {
outputScraper.add("Latch released");
// Then
- outputScraper.forEach(Object::toString);
assertThat(outputScraper).containsExactly("Counted down", "Counted down", "Counted down", "Counted down", "Counted down", "Latch released");
}
@@ -35,7 +36,9 @@ public class CountdownLatchExampleIntegrationTest {
// Given
List outputScraper = Collections.synchronizedList(new ArrayList<>());
CountDownLatch countDownLatch = new CountDownLatch(5);
- List workers = Stream.generate(() -> new Thread(new BrokenWorker(outputScraper, countDownLatch))).limit(5).collect(toList());
+ List workers = Stream.generate(() -> new Thread(new BrokenWorker(outputScraper, countDownLatch)))
+ .limit(5)
+ .collect(toList());
// When
workers.forEach(Thread::start);
@@ -63,7 +66,6 @@ public class CountdownLatchExampleIntegrationTest {
outputScraper.add("Workers complete");
// Then
- outputScraper.forEach(Object::toString);
assertThat(outputScraper).containsExactly("Workers ready", "Counted down", "Counted down", "Counted down", "Counted down", "Counted down", "Workers complete");
}
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java b/core-java-concurrency/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java
index 5f8b05a974..c2513f38c1 100644
--- a/core-java-concurrency/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java
+++ b/core-java-concurrency/src/test/java/com/baeldung/concurrent/future/SquareCalculatorIntegrationTest.java
@@ -22,7 +22,6 @@ public class SquareCalculatorIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(SquareCalculatorIntegrationTest.class);
-
@Rule
public TestName name = new TestName();
diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java b/core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java
index 3014ae38b2..f3ced219f7 100644
--- a/core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java
+++ b/core-java-concurrency/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java
@@ -49,9 +49,7 @@ public class SynchronizedHashMapWithRWLockManualTest {
private void executeReaderThreads(SynchronizedHashMapWithRWLock object, int threadCount, ExecutorService service) {
for (int i = 0; i < threadCount; i++)
- service.execute(() -> {
- object.get("key" + threadCount);
- });
+ service.execute(() -> object.get("key" + threadCount));
}
}
diff --git a/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java b/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java
index 33e3326427..cbac6e7f4c 100644
--- a/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java
+++ b/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java
@@ -12,7 +12,7 @@ import static org.junit.Assert.assertNull;
public class ConcurrentMapNullKeyValueManualTest {
- ConcurrentMap concurrentMap;
+ private ConcurrentMap concurrentMap;
@Before
public void setup() {
diff --git a/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTest.java b/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTest.java
index 768c31ee80..c0753db513 100644
--- a/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTest.java
+++ b/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTest.java
@@ -18,7 +18,7 @@ public class ConcurrentNavigableMapManualTest {
public void givenSkipListMap_whenAccessInMultiThreads_thenOrderingStable() throws InterruptedException {
NavigableMap skipListMap = new ConcurrentSkipListMap<>();
- updateMapConcurrently(skipListMap, 4);
+ updateMapConcurrently(skipListMap);
Iterator skipListIter = skipListMap.keySet().iterator();
int previous = skipListIter.next();
@@ -28,9 +28,9 @@ public class ConcurrentNavigableMapManualTest {
}
}
- private void updateMapConcurrently(NavigableMap navigableMap, int concurrencyLevel) throws InterruptedException {
- ExecutorService executorService = Executors.newFixedThreadPool(concurrencyLevel);
- for (int i = 0; i < concurrencyLevel; i++) {
+ private void updateMapConcurrently(NavigableMap navigableMap) throws InterruptedException {
+ ExecutorService executorService = Executors.newFixedThreadPool(4);
+ for (int i = 0; i < 4; i++) {
executorService.execute(() -> {
ThreadLocalRandom random = ThreadLocalRandom.current();
for (int j = 0; j < 10000; j++) {
@@ -45,26 +45,26 @@ public class ConcurrentNavigableMapManualTest {
@Test
public void givenSkipListMap_whenNavConcurrently_thenCountCorrect() throws InterruptedException {
NavigableMap skipListMap = new ConcurrentSkipListMap<>();
- int count = countMapElementByPollingFirstEntry(skipListMap, 10000, 4);
+ int count = countMapElementByPollingFirstEntry(skipListMap);
assertEquals(10000 * 4, count);
}
@Test
public void givenTreeMap_whenNavConcurrently_thenCountError() throws InterruptedException {
NavigableMap treeMap = new TreeMap<>();
- int count = countMapElementByPollingFirstEntry(treeMap, 10000, 4);
+ int count = countMapElementByPollingFirstEntry(treeMap);
assertNotEquals(10000 * 4, count);
}
- private int countMapElementByPollingFirstEntry(NavigableMap navigableMap, int elementCount, int concurrencyLevel) throws InterruptedException {
- for (int i = 0; i < elementCount * concurrencyLevel; i++) {
+ private int countMapElementByPollingFirstEntry(NavigableMap navigableMap) throws InterruptedException {
+ for (int i = 0; i < 10000 * 4; i++) {
navigableMap.put(i, i);
}
AtomicInteger counter = new AtomicInteger(0);
- ExecutorService executorService = Executors.newFixedThreadPool(concurrencyLevel);
- for (int j = 0; j < concurrencyLevel; j++) {
+ ExecutorService executorService = Executors.newFixedThreadPool(4);
+ for (int j = 0; j < 4; j++) {
executorService.execute(() -> {
- for (int i = 0; i < elementCount; i++) {
+ for (int i = 0; i < 10000; i++) {
if (navigableMap.pollFirstEntry() != null) {
counter.incrementAndGet();
}
diff --git a/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java b/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java
index f7a7bd5fe0..9cdac72d59 100644
--- a/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java
+++ b/core-java-concurrency/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java
@@ -2,7 +2,6 @@ package com.baeldung.java.concurrentmodification;
import org.junit.Test;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
@@ -28,9 +27,9 @@ public class ConcurrentModificationUnitTest {
List integers = newArrayList(1, 2, 3);
- for (Iterator iterator = integers.iterator(); iterator.hasNext();) {
+ for (Iterator iterator = integers.iterator(); iterator.hasNext(); ) {
Integer integer = iterator.next();
- if(integer == 2) {
+ if (integer == 2) {
iterator.remove();
}
}
@@ -45,7 +44,7 @@ public class ConcurrentModificationUnitTest {
List toRemove = newArrayList();
for (Integer integer : integers) {
- if(integer == 2) {
+ if (integer == 2) {
toRemove.add(integer);
}
}
@@ -69,10 +68,10 @@ public class ConcurrentModificationUnitTest {
Collection integers = newArrayList(1, 2, 3);
List collected = integers
- .stream()
- .filter(i -> i != 2)
- .map(Object::toString)
- .collect(toList());
+ .stream()
+ .filter(i -> i != 2)
+ .map(Object::toString)
+ .collect(toList());
assertThat(collected).containsExactly("1", "3");
}
diff --git a/core-java-concurrency/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java b/core-java-concurrency/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java
index 41eb864fd9..a1f5b6f1e2 100644
--- a/core-java-concurrency/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java
+++ b/core-java-concurrency/src/test/java/com/baeldung/java8/Java8ExecutorServiceIntegrationTest.java
@@ -72,7 +72,7 @@ public class Java8ExecutorServiceIntegrationTest {
assertTrue(threadPoolExecutor.isShutdown());
assertFalse(notExecutedTasks.isEmpty());
- assertTrue(notExecutedTasks.size() > 0 && notExecutedTasks.size() < 98);
+ assertTrue(notExecutedTasks.size() < 98);
}
private List smartShutdown(ExecutorService executorService) {
diff --git a/core-java-concurrency/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamIntegrationTest.java b/core-java-concurrency/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamIntegrationTest.java
index 42e85fc586..502672dea1 100644
--- a/core-java-concurrency/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamIntegrationTest.java
+++ b/core-java-concurrency/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamIntegrationTest.java
@@ -23,7 +23,10 @@ public class ThreadPoolInParallelStreamIntegrationTest {
List aList = LongStream.rangeClosed(firstNum, lastNum).boxed().collect(Collectors.toList());
ForkJoinPool customThreadPool = new ForkJoinPool(4);
- long actualTotal = customThreadPool.submit(() -> aList.parallelStream().reduce(0L, Long::sum)).get();
+ long actualTotal = customThreadPool
+ .submit(() -> aList.parallelStream()
+ .reduce(0L, Long::sum))
+ .get();
assertEquals((lastNum + firstNum) * lastNum / 2, actualTotal);
}
diff --git a/core-java/README.md b/core-java/README.md
index 3f67b718f2..ef63ac81e9 100644
--- a/core-java/README.md
+++ b/core-java/README.md
@@ -119,3 +119,6 @@
- [Guide to UUID in Java](http://www.baeldung.com/java-uuid)
- [How to Get the Last Element of a Stream in Java?](http://www.baeldung.com/java-stream-last-element)
- [Guide to Escaping Characters in Java RegExps](http://www.baeldung.com/java-regexp-escape-char)
+- [Period and Duration in Java](http://www.baeldung.com/java-period-duration)
+- [Introduction to the Java 8 Date/Time API](http://www.baeldung.com/java-8-date-time-intro)
+- [Migrating to the New Java 8 Date Time API](http://www.baeldung.com/migrating-to-java-8-date-time-api)
diff --git a/core-java/pom.xml b/core-java/pom.xml
index 422965a0ed..586486027a 100644
--- a/core-java/pom.xml
+++ b/core-java/pom.xml
@@ -186,6 +186,16 @@
fscontext
${fscontext.version}
+
+ joda-time
+ joda-time
+ ${joda-time.version}
+
+
+ com.darwinsys
+ hirondelle-date4j
+ ${hirondelle-date4j.version}
+
@@ -408,6 +418,8 @@
1.8.7
1.16.12
4.6-b01
+ 2.9.9
+ 1.5.1
1.3
@@ -416,9 +428,9 @@
3.6.1
1.7.0
+
3.6.0
2.19.1
-
diff --git a/core-java/src/main/java/com/baeldung/numberofdigits/Benchmarking.java b/core-java/src/main/java/com/baeldung/numberofdigits/Benchmarking.java
new file mode 100644
index 0000000000..fbd9af2c30
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/numberofdigits/Benchmarking.java
@@ -0,0 +1,131 @@
+package com.baeldung.numberofdigits;
+
+import static com.baeldung.designpatterns.util.LogerUtil.LOG;;
+
+public class Benchmarking {;
+
+ private static final int LOWER_BOUND = 1;
+ private static final int UPPER_BOUND = 999999999;
+
+
+ public static void main(String[] args) {
+ LOG.info("Testing all methods...");
+
+ long length = test_stringBasedSolution();
+ LOG.info("String Based Solution : " + length);
+
+ length = test_logarithmicApproach();
+ LOG.info("Logarithmic Approach : " + length);
+
+ length = test_repeatedMultiplication();
+ LOG.info("Repeated Multiplication : " + length);
+
+ length = test_shiftOperators();
+ LOG.info("Shift Operators : " + length);
+
+ length = test_dividingWithPowersOf2();
+ LOG.info("Dividing with Powers of 2 : " + length);
+
+ length = test_divideAndConquer();
+ LOG.info("Divide And Conquer : " + length);
+
+ }
+
+ private static long test_stringBasedSolution() {
+
+ long startTime, stopTime, elapsedTime;
+ startTime = System.currentTimeMillis();
+
+ int total = 0;
+ for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
+ total += NumberOfDigits.stringBasedSolution(i);
+ }
+
+ stopTime = System.currentTimeMillis();
+ elapsedTime = stopTime - startTime;
+
+ return elapsedTime;
+ }
+
+ private static long test_logarithmicApproach() {
+
+ long startTime, stopTime, elapsedTime;
+ startTime = System.currentTimeMillis();
+
+ int total = 0;
+ for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
+ total += NumberOfDigits.logarithmicApproach(i);
+ }
+
+ stopTime = System.currentTimeMillis();
+ elapsedTime = stopTime - startTime;
+
+ return elapsedTime;
+ }
+
+ private static long test_repeatedMultiplication() {
+
+ long startTime, stopTime, elapsedTime;
+ startTime = System.currentTimeMillis();
+
+ int total = 0;
+ for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
+ total += NumberOfDigits.repeatedMultiplication(i);
+ }
+
+ stopTime = System.currentTimeMillis();
+ elapsedTime = stopTime - startTime;
+
+ return elapsedTime;
+ }
+
+ private static long test_shiftOperators() {
+
+ long startTime, stopTime, elapsedTime;
+ startTime = System.currentTimeMillis();
+
+ int total = 0;
+ for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
+ total += NumberOfDigits.shiftOperators(i);
+ }
+
+ stopTime = System.currentTimeMillis();
+ elapsedTime = stopTime - startTime;
+
+ return elapsedTime;
+ }
+
+ private static long test_dividingWithPowersOf2() {
+
+ long startTime, stopTime, elapsedTime;
+ startTime = System.currentTimeMillis();
+
+ int total = 0;
+ for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
+ total += NumberOfDigits.dividingWithPowersOf2(i);
+ }
+
+ stopTime = System.currentTimeMillis();
+ elapsedTime = stopTime - startTime;
+
+ return elapsedTime;
+ }
+
+ private static long test_divideAndConquer() {
+
+ long startTime, stopTime, elapsedTime;
+ startTime = System.currentTimeMillis();
+
+ int total = 0;
+ for (int i = LOWER_BOUND; i <= UPPER_BOUND; i++) {
+ total += NumberOfDigits.divideAndConquer(i);
+ }
+
+ stopTime = System.currentTimeMillis();
+ elapsedTime = stopTime - startTime;
+
+ return elapsedTime;
+ }
+
+
+}
diff --git a/core-java/src/main/java/com/baeldung/numberofdigits/NumberOfDigits.java b/core-java/src/main/java/com/baeldung/numberofdigits/NumberOfDigits.java
new file mode 100644
index 0000000000..f455430750
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/numberofdigits/NumberOfDigits.java
@@ -0,0 +1,97 @@
+package com.baeldung.numberofdigits;
+
+public class NumberOfDigits {
+ public static int stringBasedSolution(int number) {
+ int length = String.valueOf(number).length();
+ return length;
+ }
+
+ public static int logarithmicApproach(int number) {
+ int length = (int) Math.log10(number) + 1;
+ return length;
+ }
+
+ public static int repeatedMultiplication(int number) {
+ int length = 0;
+ long temp = 1;
+ while(temp <= number) {
+ length++;
+ temp *= 10;
+ }
+ return length;
+ }
+
+ public static int shiftOperators(int number) {
+ int length = 0;
+ long temp = 1;
+ while(temp <= number) {
+ length++;
+ temp = (temp << 3) + (temp << 1);
+ }
+ return length;
+ }
+
+ public static int dividingWithPowersOf2(int number) {
+ int length = 1;
+ if (number >= 100000000) {
+ length += 8;
+ number /= 100000000;
+ }
+ if (number >= 10000) {
+ length += 4;
+ number /= 10000;
+ }
+ if (number >= 100) {
+ length += 2;
+ number /= 100;
+ }
+ if (number >= 10) {
+ length += 1;
+ }
+ return length;
+ }
+
+ public static int divideAndConquer(int number) {
+ if (number < 100000){
+ // 5 digits or less
+ if (number < 100){
+ // 1 or 2
+ if (number < 10)
+ return 1;
+ else
+ return 2;
+ }else{
+ // 3 to 5 digits
+ if (number < 1000)
+ return 3;
+ else{
+ // 4 or 5 digits
+ if (number < 10000)
+ return 4;
+ else
+ return 5;
+ }
+ }
+ } else {
+ // 6 digits or more
+ if (number < 10000000) {
+ // 6 or 7 digits
+ if (number < 1000000)
+ return 6;
+ else
+ return 7;
+ } else {
+ // 8 to 10 digits
+ if (number < 100000000)
+ return 8;
+ else {
+ // 9 or 10 digits
+ if (number < 1000000000)
+ return 9;
+ else
+ return 10;
+ }
+ }
+ }
+ }
+}
diff --git a/core-java/src/main/java/com/baeldung/numberofdigits/NumberOfDigitsDriver.java b/core-java/src/main/java/com/baeldung/numberofdigits/NumberOfDigitsDriver.java
new file mode 100644
index 0000000000..4d76a5d677
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/numberofdigits/NumberOfDigitsDriver.java
@@ -0,0 +1,27 @@
+package com.baeldung.numberofdigits;
+
+import static com.baeldung.designpatterns.util.LogerUtil.LOG;
+
+public class NumberOfDigitsDriver {
+ public static void main(String[] args) {
+ LOG.info("Testing all methods...");
+
+ long length = NumberOfDigits.stringBasedSolution(602);
+ LOG.info("String Based Solution : " + length);
+
+ length = NumberOfDigits.logarithmicApproach(602);
+ LOG.info("Logarithmic Approach : " + length);
+
+ length = NumberOfDigits.repeatedMultiplication(602);
+ LOG.info("Repeated Multiplication : " + length);
+
+ length = NumberOfDigits.shiftOperators(602);
+ LOG.info("Shift Operators : " + length);
+
+ length = NumberOfDigits.dividingWithPowersOf2(602);
+ LOG.info("Dividing with Powers of 2 : " + length);
+
+ length = NumberOfDigits.divideAndConquer(602);
+ LOG.info("Divide And Conquer : " + length);
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java b/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java
new file mode 100644
index 0000000000..324a0d4587
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/DateDiffUnitTest.java
@@ -0,0 +1,82 @@
+package com.baeldung;
+
+import org.junit.Test;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+
+public class DateDiffUnitTest {
+
+ @Test
+ public void givenTwoDatesBeforeJava8_whenDifferentiating_thenWeGetSix() throws ParseException {
+ SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
+ Date firstDate = sdf.parse("06/24/2017");
+ Date secondDate = sdf.parse("06/30/2017");
+
+ long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime());
+ long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
+
+ assertEquals(diff, 6);
+ }
+
+ @Test
+ public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() {
+ LocalDate now = LocalDate.now();
+ LocalDate sixDaysBehind = now.minusDays(6);
+
+ Duration duration = Duration.between(now, sixDaysBehind);
+ long diff = Math.abs(duration.toDays());
+
+ assertEquals(diff, 6);
+ }
+
+ @Test
+ public void givenTwoDateTimesInJava8_whenDifferentiating_thenWeGetSix() {
+ LocalDateTime now = LocalDateTime.now();
+ LocalDateTime sixMinutesBehind = now.minusMinutes(6);
+
+ Duration duration = Duration.between(now, sixMinutesBehind);
+ long diff = Math.abs(duration.toMinutes());
+
+ assertEquals(diff, 6);
+ }
+
+ @Test
+ public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() {
+ org.joda.time.LocalDate now = org.joda.time.LocalDate.now();
+ org.joda.time.LocalDate sixDaysBehind = now.minusDays(6);
+
+ org.joda.time.Period period = new org.joda.time.Period(now, sixDaysBehind);
+ long diff = Math.abs(period.getDays());
+
+ assertEquals(diff, 6);
+ }
+
+ @Test
+ public void givenTwoDateTimesInJodaTime_whenDifferentiating_thenWeGetSix() {
+ org.joda.time.LocalDateTime now = org.joda.time.LocalDateTime.now();
+ org.joda.time.LocalDateTime sixMinutesBehind = now.minusMinutes(6);
+
+ org.joda.time.Period period = new org.joda.time.Period(now, sixMinutesBehind);
+ long diff = Math.abs(period.getDays());
+ }
+
+ @Test
+ public void givenTwoDatesInDate4j_whenDifferentiating_thenWeGetSix() {
+ hirondelle.date4j.DateTime now = hirondelle.date4j.DateTime.now(TimeZone.getDefault());
+ hirondelle.date4j.DateTime sixDaysBehind = now.minusDays(6);
+
+ long diff = Math.abs(now.numDaysFrom(sixDaysBehind));
+
+ assertEquals(diff, 6);
+ }
+}
\ No newline at end of file
diff --git a/core-java/src/test/java/com/baeldung/numberofdigits/NumberOfDigitsIntegrationTest.java b/core-java/src/test/java/com/baeldung/numberofdigits/NumberOfDigitsIntegrationTest.java
new file mode 100644
index 0000000000..01b874622e
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/numberofdigits/NumberOfDigitsIntegrationTest.java
@@ -0,0 +1,100 @@
+package com.baeldung.numberofdigits;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+
+@RunWith(Theories.class)
+public class NumberOfDigitsIntegrationTest {
+
+ @DataPoints
+ public static int[][] lowestIntegers()
+ {
+ return new int[][]{
+ {1, 1},
+ {2, 10},
+ {3, 100},
+ {4, 1000},
+ {5, 10000},
+ {6, 100000},
+ {7, 1000000},
+ {8, 10000000},
+ {9, 100000000},
+ {10, 1000000000}
+ };
+ }
+
+ @DataPoints
+ public static int[][] highestIntegers()
+ {
+ return new int[][]{
+ {1, 9},
+ {2, 99},
+ {3, 999},
+ {4, 9999},
+ {5, 99999},
+ {6, 999999},
+ {7, 9999999},
+ {8, 99999999},
+ {9, 999999999},
+ {10, Integer.MAX_VALUE}
+ };
+ }
+
+ @DataPoints
+ public static int[][] randomIntegers()
+ {
+ return new int[][]{
+ {1, 1},
+ {2, 14},
+ {3, 549},
+ {4, 1136},
+ {5, 25340},
+ {6, 134321},
+ {7, 1435432},
+ {8, 54234129},
+ {9, 113683912},
+ {10, 1534031982}
+ };
+ }
+
+ @Theory
+ public void givenDataPoints_whenStringBasedSolutionInvoked_thenAllPointsMatch(final int[] entry) {
+ Assume.assumeTrue(entry[0] > 0 && entry[1] > 0);
+ Assert.assertEquals(entry[0], NumberOfDigits.stringBasedSolution(entry[1]));
+ }
+
+ @Theory
+ public void givenDataPoints_whenLogarithmicApproachInvoked_thenAllPointsMatch(final int[] entry) {
+ Assume.assumeTrue(entry[0] > 0 && entry[1] > 0);
+ Assert.assertEquals(entry[0], NumberOfDigits.logarithmicApproach(entry[1]));
+ }
+
+ @Theory
+ public void givenDataPoints_whenRepeatedMultiplicationInvoked_thenAllPointsMatch(final int[] entry) {
+ Assume.assumeTrue(entry[0] > 0 && entry[1] > 0);
+ Assert.assertEquals(entry[0], NumberOfDigits.repeatedMultiplication(entry[1]));
+ }
+
+ @Theory
+ public void givenDataPoints_whenShiftOperatorsInvoked_thenAllPointsMatch(final int[] entry) {
+ Assume.assumeTrue(entry[0] > 0 && entry[1] > 0);
+ Assert.assertEquals(entry[0], NumberOfDigits.shiftOperators(entry[1]));
+ }
+
+ @Theory
+ public void givenDataPoints_whenDividingWithPowersOf2Invoked_thenAllPointsMatch(final int[] entry) {
+ Assume.assumeTrue(entry[0] > 0 && entry[1] > 0);
+ Assert.assertEquals(entry[0], NumberOfDigits.dividingWithPowersOf2(entry[1]));
+ }
+
+ @Theory
+ public void givenDataPoints_whenDivideAndConquerInvoked_thenAllPointsMatch(final int[] entry) {
+ Assume.assumeTrue(entry[0] > 0 && entry[1] > 0);
+ Assert.assertEquals(entry[0], NumberOfDigits.divideAndConquer(entry[1]));
+ }
+
+}
\ No newline at end of file
diff --git a/java-difference-date/README.md b/java-difference-date/README.md
new file mode 100644
index 0000000000..2a024c27a2
--- /dev/null
+++ b/java-difference-date/README.md
@@ -0,0 +1,5 @@
+## Relevant articles:
+
+- [Period and Duration in Java](http://www.baeldung.com/java-period-duration)
+- [Introduction to the Java 8 Date/Time API](http://www.baeldung.com/java-8-date-time-intro)
+- [Migrating to the New Java 8 Date Time API](http://www.baeldung.com/migrating-to-java-8-date-time-api)
\ No newline at end of file
diff --git a/java-difference-date/pom.xml b/java-difference-date/pom.xml
new file mode 100644
index 0000000000..388753de90
--- /dev/null
+++ b/java-difference-date/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ java-difference-date
+ 0.0.1-SNAPSHOT
+ jar
+
+ java-difference-date
+ Difference between two dates in java
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ joda-time
+ joda-time
+ ${joda-time.version}
+
+
+ com.darwinsys
+ hirondelle-date4j
+ ${hirondelle-date4j.version}
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+
+
+
+
+
+
+ 1.8
+ 4.12
+ 2.9.9
+ 1.5.1
+
+
diff --git a/java-difference-date/src/test/java/com/baeldung/DateDiffTest.java b/java-difference-date/src/test/java/com/baeldung/DateDiffTest.java
new file mode 100644
index 0000000000..4203f7ef38
--- /dev/null
+++ b/java-difference-date/src/test/java/com/baeldung/DateDiffTest.java
@@ -0,0 +1,61 @@
+package com.baeldung;
+
+import org.joda.time.DateTime;
+import org.junit.Test;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.Duration;
+import java.time.ZonedDateTime;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+
+public class DateDiffTest {
+ @Test
+ public void givenTwoDatesBeforeJava8_whenDifferentiating_thenWeGetSix() throws ParseException {
+ SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
+ Date firstDate = sdf.parse("06/24/2017");
+ Date secondDate = sdf.parse("06/30/2017");
+
+ long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime());
+ long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
+
+ assertEquals(diff, 6);
+ }
+
+ @Test
+ public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() {
+ ZonedDateTime now = ZonedDateTime.now();
+ ZonedDateTime sixDaysBehind = now.minusDays(6);
+
+ Duration duration = Duration.between(now, sixDaysBehind);
+ long diff = Math.abs(duration.toDays());
+
+ assertEquals(diff, 6);
+ }
+
+ @Test
+ public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() {
+ DateTime now = DateTime.now();
+ DateTime sixDaysBehind = now.minusDays(6);
+
+ org.joda.time.Duration duration = new org.joda.time.Duration(now, sixDaysBehind);
+ long diff = Math.abs(duration.getStandardDays());
+
+ assertEquals(diff, 6);
+ }
+
+ @Test
+ public void givenTwoDatesInDate4j_whenDifferentiating_thenWeGetSix() {
+ hirondelle.date4j.DateTime now = hirondelle.date4j.DateTime.now(TimeZone.getDefault());
+ hirondelle.date4j.DateTime sixDaysBehind = now.minusDays(6);
+
+ long diff = Math.abs(now.numDaysFrom(sixDaysBehind));
+
+ assertEquals(diff, 6);
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index f2dd0ae48c..da38d65df3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -43,6 +43,7 @@
cdi
core-java
+ core-java-concurrency
couchbase-sdk
deltaspike
diff --git a/spring-5/src/main/java/com/baeldung/functional/MyService.java b/spring-5/src/main/java/com/baeldung/functional/MyService.java
new file mode 100644
index 0000000000..d85a860f06
--- /dev/null
+++ b/spring-5/src/main/java/com/baeldung/functional/MyService.java
@@ -0,0 +1,13 @@
+package com.baeldung.functional;
+
+import java.util.Random;
+
+import org.springframework.stereotype.Component;
+
+public class MyService {
+
+ public int getRandomNumber(){
+ return (new Random().nextInt(10));
+ }
+
+}
diff --git a/spring-5/src/test/java/com/baeldung/functional/BeanRegistrationTest.java b/spring-5/src/test/java/com/baeldung/functional/BeanRegistrationTest.java
new file mode 100644
index 0000000000..0b1542dbbc
--- /dev/null
+++ b/spring-5/src/test/java/com/baeldung/functional/BeanRegistrationTest.java
@@ -0,0 +1,42 @@
+package com.baeldung.functional;
+
+import static org.junit.Assert.*;
+
+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.junit4.SpringRunner;
+import org.springframework.web.context.support.GenericWebApplicationContext;
+
+import com.baeldung.Spring5Application;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Spring5Application.class)
+public class BeanRegistrationTest {
+
+ @Autowired
+ private GenericWebApplicationContext context;
+
+ @Test
+ public void whenRegisterBean_thenOk() {
+ context.registerBean(MyService.class, () -> new MyService());
+ MyService myService = (MyService) context.getBean("com.baeldung.functional.MyService");
+ assertTrue(myService.getRandomNumber() < 10);
+ }
+
+ @Test
+ public void whenRegisterBeanWithName_thenOk() {
+ context.registerBean("mySecondService", MyService.class, () -> new MyService());
+ MyService mySecondService = (MyService) context.getBean("mySecondService");
+ assertTrue(mySecondService.getRandomNumber() < 10);
+ }
+
+ @Test
+ public void whenRegisterBeanWithCallback_thenOk() {
+ context.registerBean("myCallbackService", MyService.class, () -> new MyService(), bd -> bd.setAutowireCandidate(false));
+ MyService myCallbackService = (MyService) context.getBean("myCallbackService");
+ assertTrue(myCallbackService.getRandomNumber() < 10);
+ }
+
+}
diff --git a/spring-mvc-kotlin/pom.xml b/spring-mvc-kotlin/pom.xml
index 5375ecae7c..264cf49817 100644
--- a/spring-mvc-kotlin/pom.xml
+++ b/spring-mvc-kotlin/pom.xml
@@ -35,9 +35,15 @@
4.3.10.RELEASE
- javax.servlet
- jstl
- 1.2
+ org.thymeleaf
+ thymeleaf
+ 3.0.7.RELEASE
+
+
+
+ org.thymeleaf
+ thymeleaf-spring4
+ 3.0.7.RELEASE
diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebConfig.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebConfig.kt
index 4907e46efb..ec1c4e9511 100644
--- a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebConfig.kt
+++ b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebConfig.kt
@@ -1,13 +1,16 @@
package com.baeldung.kotlin.mvc
+import org.springframework.context.ApplicationContext
+import org.springframework.context.ApplicationContextAware
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
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
-import org.springframework.web.servlet.view.InternalResourceViewResolver
-import org.springframework.web.servlet.view.JstlView
+import org.thymeleaf.spring4.SpringTemplateEngine
+import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver
+import org.thymeleaf.spring4.view.ThymeleafViewResolver
+import org.thymeleaf.templatemode.TemplateMode
@@ -15,7 +18,13 @@ import org.springframework.web.servlet.view.JstlView
@EnableWebMvc
@Configuration
-open class ApplicationWebConfig: WebMvcConfigurerAdapter() {
+open class ApplicationWebConfig: WebMvcConfigurerAdapter(), ApplicationContextAware {
+
+ private var applicationContext: ApplicationContext? = null
+
+ override fun setApplicationContext(applicationContext: ApplicationContext?) {
+ this.applicationContext = applicationContext
+ }
override fun addViewControllers(registry: ViewControllerRegistry?) {
super.addViewControllers(registry)
@@ -24,14 +33,28 @@ open class ApplicationWebConfig: WebMvcConfigurerAdapter() {
}
@Bean
- open fun viewResolver(): ViewResolver {
- val bean = InternalResourceViewResolver()
+ open fun templateResolver(): SpringResourceTemplateResolver {
+ val templateResolver = SpringResourceTemplateResolver()
+ templateResolver.prefix = "/WEB-INF/view/"
+ templateResolver.suffix = ".html"
+ templateResolver.templateMode = TemplateMode.HTML
+ templateResolver.setApplicationContext(this.applicationContext);
+ return templateResolver
+ }
- bean.setViewClass(JstlView::class.java)
- bean.setPrefix("/WEB-INF/view/")
- bean.setSuffix(".jsp")
+ @Bean
+ open fun templateEngine(): SpringTemplateEngine {
+ val templateEngine = SpringTemplateEngine()
+ templateEngine.setTemplateResolver(templateResolver())
+ return templateEngine
+ }
- return bean
+ @Bean
+ open fun viewResolver(): ThymeleafViewResolver {
+ val viewResolver = ThymeleafViewResolver()
+ viewResolver.templateEngine = templateEngine()
+ viewResolver.order = 1
+ return viewResolver
}
}
\ No newline at end of file
diff --git a/spring-mvc-kotlin/src/main/webapp/WEB-INF/spring-web-config.xml b/spring-mvc-kotlin/src/main/webapp/WEB-INF/spring-web-config.xml
index ffe83a66fa..c7f110ea94 100644
--- a/spring-mvc-kotlin/src/main/webapp/WEB-INF/spring-web-config.xml
+++ b/spring-mvc-kotlin/src/main/webapp/WEB-INF/spring-web-config.xml
@@ -12,13 +12,26 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vavr/pom.xml b/vavr/pom.xml
index 426155263c..53cd07ddf7 100644
--- a/vavr/pom.xml
+++ b/vavr/pom.xml
@@ -40,6 +40,13 @@
org.springframework.boot
spring-boot-starter-test
+
+
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
@@ -69,6 +76,7 @@
1.8
0.9.0
4.12
+ 3.0.0
diff --git a/vavr/src/test/java/com/baeldung/vavr/future/FutureUnitTest.java b/vavr/src/test/java/com/baeldung/vavr/future/FutureUnitTest.java
new file mode 100644
index 0000000000..84621e3a68
--- /dev/null
+++ b/vavr/src/test/java/com/baeldung/vavr/future/FutureUnitTest.java
@@ -0,0 +1,203 @@
+package com.baeldung.vavr.future;
+
+import static io.vavr.API.$;
+import static io.vavr.API.Case;
+import static io.vavr.API.Match;
+import static io.vavr.Predicates.exists;
+import static io.vavr.Predicates.forAll;
+import static org.awaitility.Awaitility.await;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.concurrent.CancellationException;
+import java.util.function.Predicate;
+
+import org.junit.Test;
+
+import io.vavr.collection.List;
+import io.vavr.concurrent.Future;
+
+public class FutureUnitTest {
+
+ private final String SUCCESS = "Success";
+ private final String FAILURE = "Failure";
+
+ @Test
+ public void givenFunctionReturnInteger_WhenCallWithFuture_ShouldReturnFunctionValue() {
+ Future future = Future.of(() -> 1);
+
+ assertEquals(1, future.get()
+ .intValue());
+ }
+
+ @Test
+ public void givenFunctionGetRemoteHttpResourceAsString_WhenCallSuccessWithFuture_ShouldReturnContentValueAsString() {
+ String url = "http://resource";
+ String content = "Content from " + url;
+ Future future = Future.of(() -> getResource(url));
+
+ assertEquals(content, future.get());
+ }
+
+ @Test
+ public void givenFunctionThrowException_WhenCallWithFuture_ShouldReturnFailure() {
+ Future future = Future.of(() -> getResourceThrowException(""));
+ future.await();
+
+ assertTrue(future.isFailure());
+ }
+
+ @Test
+ public void givenAFutureReturnZero_WhenCheckFutureWithExistEvenValue_ShouldReturnRight() {
+ Future future = Future.of(() -> 2);
+ boolean result = future.exists(i -> i % 2 == 0);
+
+ assertTrue(result);
+ }
+
+ @Test
+ public void givenFunction_WhenCallWithFutureAndRegisterConsumerForSuccess_ShouldCallConsumerToStoreValue() {
+ final int[] store = new int[] { 0 };
+ Future future = Future.of(() -> 1);
+ future.onSuccess(i -> {
+ store[0] = i;
+ });
+ await().until(() -> store[0] == 1);
+ }
+
+ @Test
+ public void givenFunctionThrowException_WhenCallWithFutureAndRegisterConsumerForFailer_ShouldCallConsumerToStoreException() {
+ final Throwable[] store = new Throwable[] { null };
+ Future future = Future.of(() -> getResourceThrowException(""));
+ future.onFailure(err -> store[0] = err);
+ await().until(() -> RuntimeException.class.isInstance(store[0]));
+ }
+
+ @Test
+ public void givenAFuture_WhenAddAndThenConsumer_ShouldCallConsumerWithResultOfFutureAction() {
+ int[] store1 = new int[1];
+ int[] store2 = new int[1];
+ Future future = Future.of(() -> 1);
+ Future andThenFuture = future.andThen(i -> store1[0] = i.get() + 1)
+ .andThen(i -> store2[0] = store1[0] + 1);
+ andThenFuture.await();
+
+ assertEquals(2, store1[0]);
+ assertEquals(3, store2[0]);
+ }
+
+ @Test
+ public void givenAFailureFuture_WhenCallOrElseFunction_ShouldReturnNewFuture() {
+ Future future = Future.failed(new RuntimeException());
+ Future future2 = future.orElse(Future.of(() -> 2));
+
+ assertEquals(2, future2.get()
+ .intValue());
+ }
+
+ @Test(expected = CancellationException.class)
+ public void givenAFuture_WhenCallCancel_ShouldReturnCancellationException() {
+ long waitTime = 1000;
+ Future future = Future.of(() -> {
+ Thread.sleep(waitTime);
+ return 1;
+ });
+ future.cancel();
+ future.await();
+ future.get();
+ }
+
+ @Test
+ public void givenAFuture_WhenCallFallBackWithSuccessFuture_ShouldReturnFutureResult() {
+ String expectedResult = "take this";
+ Future future = Future.of(() -> expectedResult);
+ Future secondFuture = Future.of(() -> "take that");
+ Future futureResult = future.fallbackTo(secondFuture);
+ futureResult.await();
+
+ assertEquals(expectedResult, futureResult.get());
+ }
+
+ @Test
+ public void givenAFuture_WhenCallFallBackWithFailureFuture_ShouldReturnValueOfFallBackFuture() {
+ String expectedResult = "take that";
+ Future future = Future.failed(new RuntimeException());
+ Future fallbackFuture = Future.of(() -> expectedResult);
+ Future futureResult = future.fallbackTo(fallbackFuture);
+ futureResult.await();
+
+ assertEquals(expectedResult, futureResult.get());
+ }
+
+ @Test
+ public void givenGetResourceWithFuture_WhenWaitAndMatchWithPredicate_ShouldReturnSuccess() {
+ String url = "http://resource";
+ Future future = Future.of(() -> getResource(url));
+ future.await();
+ String s = Match(future).of(Case($(future0 -> future0.isSuccess()), SUCCESS), Case($(), FAILURE));
+
+ assertEquals(SUCCESS, s);
+ }
+
+ @Test
+ public void givenAFailedFuture_WhenWaitAndMatchWithPredicateCheckSuccess_ShouldReturnFailed() {
+ Future future = Future.failed(new RuntimeException());
+ future.await();
+ String s = Match(future).of(Case($(future0 -> future0.isSuccess()), SUCCESS), Case($(), FAILURE));
+
+ assertEquals(FAILURE, s);
+ }
+
+ @Test
+ public void givenAFuture_WhenMatchWithFuturePredicate_ShouldReturnSuccess() {
+ Future future = Future.of(() -> {
+ Thread.sleep(10);
+ return 1;
+ });
+ Predicate> predicate = f -> f.exists(i -> i % 2 == 1);
+ String s = Match(future).of(Case($(predicate), "Even"), Case($(), "Odd"));
+
+ assertEquals("Even", s);
+ }
+
+ @Test
+ public void givenAListOfFutureReturnFist3Integers_WhenMatchWithExistEvenNumberPredicate_ShouldReturnSuccess() {
+ List> futures = getFutureOfFirst3Number();
+ Predicate> predicate0 = future -> future.exists(i -> i % 2 == 0);
+ String s = Match(futures).of(Case($(exists(predicate0)), "Even"), Case($(), "Odd"));
+
+ assertEquals("Even", s);
+ }
+
+ @Test
+ public void givenAListOfFutureReturnFist3Integers_WhenMatchWithForAllNumberBiggerThanZeroPredicate_ShouldReturnSuccess() {
+ List> futures = getFutureOfFirst3Number();
+ Predicate> predicate0 = future -> future.exists(i -> i > 0);
+ String s = Match(futures).of(Case($(forAll(predicate0)), "Positive numbers"), Case($(), "None"));
+
+ assertEquals("Positive numbers", s);
+ }
+
+ @Test
+ public void givenAListOfFutureReturnFist3Integers_WhenMatchWithForAllNumberSmallerThanZeroPredicate_ShouldReturnFailed() {
+ List> futures = getFutureOfFirst3Number();
+ Predicate> predicate0 = future -> future.exists(i -> i < 0);
+ String s = Match(futures).of(Case($(forAll(predicate0)), "Negative numbers"), Case($(), "None"));
+
+ assertEquals("None", s);
+ }
+
+ private String getResource(String url) throws InterruptedException {
+ Thread.sleep(10);
+ return "Content from " + url;
+ }
+
+ private String getResourceThrowException(String url) {
+ throw new RuntimeException("Exception when get resource " + url);
+ }
+
+ private List> getFutureOfFirst3Number() {
+ List> futures = List.of(Future.of(() -> 1), Future.of(() -> 2), Future.of(() -> 3));
+ return futures;
+ }
+}