Merge remote-tracking branch 'upstream/master' into JAVA-22_spring_boot_rest_refactoring
This commit is contained in:
@@ -73,8 +73,6 @@ ninja/devDb.mv.db
|
||||
**/out-tsc
|
||||
**/nbproject/
|
||||
**/nb-configuration.xml
|
||||
core-scala/.cache-main
|
||||
core-scala/.cache-tests
|
||||
|
||||
|
||||
persistence-modules/hibernate5/transaction.log
|
||||
|
||||
@@ -22,10 +22,38 @@ This project is **a collection of small and focused tutorials** - each covering
|
||||
A strong focus of these is, of course, the Spring Framework - Spring, Spring Boot and Spring Security.
|
||||
In additional to Spring, the modules here are covering a number of aspects in Java.
|
||||
|
||||
Profile based segregation
|
||||
====================
|
||||
|
||||
We are using maven build profiles to segregate the huge list of individual projects we have in our repository.
|
||||
|
||||
The projects are broadly divided into 3 list: first, second and heavy.
|
||||
|
||||
Next, they are segregated further on the basis of tests that we want to execute.
|
||||
|
||||
Therefore, we have a total of 6 profiles:
|
||||
|
||||
| Profile | Includes | Type of test enabled |
|
||||
| ----------------------- | --------------------------- | -------------------- |
|
||||
| default-first | First set of projects | *UnitTest |
|
||||
| integration-lite-first | First set of projects | *IntegrationTest |
|
||||
| default-second | Second set of projects | *UnitTest |
|
||||
| integration-lite-second | Second set of projects | *IntegrationTest |
|
||||
| default-heavy | Heavy/long running projects | *UnitTest |
|
||||
| integration-heavy | Heavy/long running projects | *IntegrationTest |
|
||||
|
||||
Building the project
|
||||
====================
|
||||
To do the full build, do: `mvn clean install`
|
||||
|
||||
Though it should not be needed often to build the entire repository at once because we are usually concerned with a specific module.
|
||||
|
||||
But if we want to, we can invoke the below command from the root of the repository if we want to build the entire repository with only Unit Tests enabled:
|
||||
|
||||
`mvn clean install -Pdefault-first,default-second,default-heavy`
|
||||
|
||||
or if we want to build the entire repository with Integration Tests enabled, we can do:
|
||||
|
||||
`mvn clean install -Pintegration-lite-first,integration-lite-second,integration-heavy`
|
||||
|
||||
|
||||
Building a single module
|
||||
@@ -46,8 +74,18 @@ When you're working with an individual module, there's no need to import all of
|
||||
|
||||
Running Tests
|
||||
=============
|
||||
The command `mvn clean install` will run the unit tests in a module.
|
||||
To run the integration tests, use the command `mvn clean install -Pintegration-lite-first`
|
||||
The command `mvn clean install` from within a module will run the unit tests in that module.
|
||||
For Spring modules this will also run the `SpringContextTest` if present.
|
||||
|
||||
To run the integration tests, use the command:
|
||||
|
||||
`mvn clean install -Pintegration-lite-first` or
|
||||
|
||||
`mvn clean install -Pintegration-lite-second` or
|
||||
|
||||
`mvn clean install -Pintegration-heavy`
|
||||
|
||||
depending on the list where our module exists
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,3 +10,4 @@ This module contains articles about searching algorithms.
|
||||
- [String Search Algorithms for Large Texts](https://www.baeldung.com/java-full-text-search-algorithms)
|
||||
- [Monte Carlo Tree Search for Tic-Tac-Toe Game](https://www.baeldung.com/java-monte-carlo-tree-search)
|
||||
- [Range Search Algorithm in Java](https://www.baeldung.com/java-range-search)
|
||||
- [Fast Pattern Matching of Strings Using Suffix Tree](https://www.baeldung.com/java-pattern-matching-suffix-tree)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
### Relevant Articles:
|
||||
|
||||
- [Introduction to Apache Beam](https://www.baeldung.com/apache-beam)
|
||||
@@ -16,12 +16,6 @@
|
||||
<name>aws-reactive</name>
|
||||
<description>AWS Reactive Sample</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<spring.version>2.2.1.RELEASE</spring.version>
|
||||
<awssdk.version>2.10.27</awssdk.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
@@ -105,4 +99,9 @@
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<spring.version>2.2.1.RELEASE</spring.version>
|
||||
<awssdk.version>2.10.27</awssdk.version>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
@@ -5,3 +5,5 @@ This module contains articles about Java 14.
|
||||
### Relevant articles
|
||||
|
||||
- [Guide to the @Serial Annotation in Java 14](https://www.baeldung.com/java-14-serial-annotation)
|
||||
- [Java Text Blocks](https://www.baeldung.com/java-text-blocks)
|
||||
- [Pattern Matching for instanceof in Java 14](https://www.baeldung.com/java-pattern-matching-instanceof)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
### Relevant Articles:
|
||||
|
||||
- [Arrays.deepEquals](https://www.baeldung.com/java-arrays-deepequals)
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
package com.baeldung.concurrent.atomic;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicMarkableReference;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class AtomicMarkableReferenceUnitTest {
|
||||
|
||||
class Employee {
|
||||
private int id;
|
||||
private String name;
|
||||
|
||||
Employee(int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenMarkValueAsTrue_whenUsingIsMarkedMethod_thenMarkValueShouldBeTrue() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
|
||||
Assertions.assertTrue(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenMarkValueAsFalse_whenUsingIsMarkedMethod_thenMarkValueShouldBeFalse() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, false);
|
||||
|
||||
Assertions.assertFalse(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingGetReferenceMethod_thenCurrentReferenceShouldBeReturned() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
|
||||
Assertions.assertEquals(employee, employeeNode.getReference());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingGetMethod_thenCurrentReferenceAndMarkShouldBeReturned() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
|
||||
boolean[] markHolder = new boolean[1];
|
||||
Employee currentEmployee = employeeNode.get(markHolder);
|
||||
|
||||
Assertions.assertEquals(employee, currentEmployee);
|
||||
Assertions.assertTrue(markHolder[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNewReferenceAndMark_whenUsingSetMethod_thenCurrentReferenceAndMarkShouldBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
|
||||
Employee newEmployee = new Employee(124, "John");
|
||||
employeeNode.set(newEmployee, false);
|
||||
|
||||
Assertions.assertEquals(newEmployee, employeeNode.getReference());
|
||||
Assertions.assertFalse(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenTheSameObjectReference_whenUsingAttemptMarkMethod_thenMarkShouldBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
|
||||
Assertions.assertTrue(employeeNode.attemptMark(employee, false));
|
||||
Assertions.assertFalse(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenDifferentObjectReference_whenUsingAttemptMarkMethod_thenMarkShouldNotBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
Employee expectedEmployee = new Employee(123, "Mike");
|
||||
|
||||
Assertions.assertFalse(employeeNode.attemptMark(expectedEmployee, false));
|
||||
Assertions.assertTrue(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenCurrentReferenceAndCurrentMark_whenUsingCompareAndSet_thenReferenceAndMarkShouldBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
Employee newEmployee = new Employee(124, "John");
|
||||
|
||||
Assertions.assertTrue(employeeNode.compareAndSet(employee, newEmployee, true, false));
|
||||
Assertions.assertEquals(newEmployee, employeeNode.getReference());
|
||||
Assertions.assertFalse(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNotCurrentReferenceAndCurrentMark_whenUsingCompareAndSet_thenReferenceAndMarkShouldNotBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
Employee newEmployee = new Employee(124, "John");
|
||||
|
||||
Assertions.assertFalse(employeeNode.compareAndSet(new Employee(1234, "Steve"), newEmployee, true, false));
|
||||
Assertions.assertEquals(employee, employeeNode.getReference());
|
||||
Assertions.assertTrue(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenCurrentReferenceAndNotCurrentMark_whenUsingCompareAndSet_thenReferenceAndMarkShouldNotBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
Employee newEmployee = new Employee(124, "John");
|
||||
|
||||
Assertions.assertFalse(employeeNode.compareAndSet(employee, newEmployee, false, true));
|
||||
Assertions.assertEquals(employee, employeeNode.getReference());
|
||||
Assertions.assertTrue(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNotCurrentReferenceAndNotCurrentMark_whenUsingCompareAndSet_thenReferenceAndMarkShouldNotBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
Employee newEmployee = new Employee(124, "John");
|
||||
|
||||
Assertions.assertFalse(employeeNode.compareAndSet(new Employee(1234, "Steve"), newEmployee, false, true));
|
||||
Assertions.assertEquals(employee, employeeNode.getReference());
|
||||
Assertions.assertTrue(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenCurrentReferenceAndCurrentMark_whenUsingWeakCompareAndSet_thenReferenceAndMarkShouldBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
Employee newEmployee = new Employee(124, "John");
|
||||
|
||||
Assertions.assertTrue(employeeNode.weakCompareAndSet(employee, newEmployee, true, false));
|
||||
Assertions.assertEquals(newEmployee, employeeNode.getReference());
|
||||
Assertions.assertFalse(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNotCurrentReferenceAndCurrentMark_whenUsingWeakCompareAndSet_thenReferenceAndMarkShouldNotBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
Employee newEmployee = new Employee(124, "John");
|
||||
|
||||
Assertions.assertFalse(employeeNode.weakCompareAndSet(new Employee(1234, "Steve"), newEmployee, true, false));
|
||||
Assertions.assertEquals(employee, employeeNode.getReference());
|
||||
Assertions.assertTrue(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenCurrentReferenceAndNotCurrentMark_whenUsingWeakCompareAndSet_thenReferenceAndMarkShouldNotBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
Employee newEmployee = new Employee(124, "John");
|
||||
|
||||
Assertions.assertFalse(employeeNode.weakCompareAndSet(employee, newEmployee, false, true));
|
||||
Assertions.assertEquals(employee, employeeNode.getReference());
|
||||
Assertions.assertTrue(employeeNode.isMarked());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNotCurrentReferenceAndNotCurrentMark_whenUsingWeakCompareAndSet_thenReferenceAndMarkShouldNotBeUpdated() {
|
||||
Employee employee = new Employee(123, "Mike");
|
||||
AtomicMarkableReference<Employee> employeeNode = new AtomicMarkableReference<Employee>(employee, true);
|
||||
Employee newEmployee = new Employee(124, "John");
|
||||
|
||||
Assertions.assertFalse(employeeNode.weakCompareAndSet(new Employee(1234, "Steve"), newEmployee, false, true));
|
||||
Assertions.assertEquals(employee, employeeNode.getReference());
|
||||
Assertions.assertTrue(employeeNode.isMarked());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<project
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.concurrent.lock</groupId>
|
||||
<artifactId>core-java-concurrency-collections-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
<version>${jmh.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<jmh.version>1.21</jmh.version>
|
||||
<guava.version>28.2-jre</guava.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.baeldung.concurrent.lock;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
|
||||
@State(Scope.Thread)
|
||||
@Fork(value = 2)
|
||||
@Warmup(iterations = 0)
|
||||
public class ConcurrentAccessBenchmark {
|
||||
static final int SLOTS = 4;
|
||||
static final int THREADS = 10000;
|
||||
static final int BUCKETS = Runtime.getRuntime().availableProcessors() * SLOTS;
|
||||
SingleLock singleLock = new SingleLock();
|
||||
StripedLock stripedLock = new StripedLock(BUCKETS);
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.Throughput)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
public Map<String,String> singleLockHashMap() throws InterruptedException {
|
||||
return singleLock.doWork(new HashMap<String,String>(), THREADS, SLOTS);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.Throughput)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
public Map<String,String> stripedLockHashMap() throws InterruptedException {
|
||||
return stripedLock.doWork(new HashMap<String,String>(), THREADS, SLOTS);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.Throughput)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
public Map<String,String> singleLockConcurrentHashMap() throws InterruptedException {
|
||||
return singleLock.doWork(new ConcurrentHashMap<String,String>(), THREADS, SLOTS);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode(Mode.Throughput)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
public Map<String,String> stripedLockConcurrentHashMap() throws InterruptedException {
|
||||
return stripedLock.doWork(new ConcurrentHashMap<String,String>(), THREADS, SLOTS);
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.concurrent.lock;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
public abstract class ConcurrentAccessExperiment {
|
||||
|
||||
public final Map<String,String> doWork(Map<String,String> map, int threads, int slots) {
|
||||
CompletableFuture<?>[] requests = new CompletableFuture<?>[threads * slots];
|
||||
|
||||
for (int i = 0; i < threads; i++) {
|
||||
requests[slots * i + 0] = CompletableFuture.supplyAsync(putSupplier(map, i));
|
||||
requests[slots * i + 1] = CompletableFuture.supplyAsync(getSupplier(map, i));
|
||||
requests[slots * i + 2] = CompletableFuture.supplyAsync(getSupplier(map, i));
|
||||
requests[slots * i + 3] = CompletableFuture.supplyAsync(getSupplier(map, i));
|
||||
}
|
||||
CompletableFuture.allOf(requests).join();
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
protected abstract Supplier<?> putSupplier(Map<String,String> map, int key);
|
||||
protected abstract Supplier<?> getSupplier(Map<String,String> map, int key);
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.concurrent.lock;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
public class SingleLock extends ConcurrentAccessExperiment {
|
||||
ReentrantLock lock;
|
||||
|
||||
public SingleLock() {
|
||||
lock = new ReentrantLock();
|
||||
}
|
||||
|
||||
protected Supplier<?> putSupplier(Map<String,String> map, int key) {
|
||||
return (()-> {
|
||||
lock.lock();
|
||||
try {
|
||||
return map.put("key" + key, "value" + key);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected Supplier<?> getSupplier(Map<String,String> map, int key) {
|
||||
return (()-> {
|
||||
lock.lock();
|
||||
try {
|
||||
return map.get("key" + key);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.concurrent.lock;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.util.concurrent.Striped;
|
||||
|
||||
public class StripedLock extends ConcurrentAccessExperiment {
|
||||
Striped<Lock> stripedLock;
|
||||
|
||||
public StripedLock(int buckets) {
|
||||
stripedLock = Striped.lock(buckets);
|
||||
}
|
||||
|
||||
protected Supplier<?> putSupplier(Map<String,String> map, int key) {
|
||||
return (()-> {
|
||||
int bucket = key % stripedLock.size();
|
||||
Lock lock = stripedLock.get(bucket);
|
||||
lock.lock();
|
||||
try {
|
||||
return map.put("key" + key, "value" + key);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected Supplier<?> getSupplier(Map<String,String> map, int key) {
|
||||
return (()-> {
|
||||
int bucket = key % stripedLock.size();
|
||||
Lock lock = stripedLock.get(bucket);
|
||||
lock.lock();
|
||||
try {
|
||||
return map.get("key" + key);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -7,3 +7,5 @@ This module contains articles about core java exceptions
|
||||
- [Is It a Bad Practice to Catch Throwable?](https://www.baeldung.com/java-catch-throwable-bad-practice)
|
||||
- [Wrapping vs Rethrowing Exceptions in Java](https://www.baeldung.com/java-wrapping-vs-rethrowing-exceptions)
|
||||
- [java.net.UnknownHostException: Invalid Hostname for Server](https://www.baeldung.com/java-unknownhostexception)
|
||||
- [How to Handle Java SocketException](https://www.baeldung.com/java-socketexception)
|
||||
- [Java Suppressed Exceptions](https://www.baeldung.com/java-suppressed-exceptions)
|
||||
|
||||
@@ -47,6 +47,14 @@
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.github.tomakehurst/wiremock -->
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
<version>2.26.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.baeldung.blockingnonblocking;
|
||||
|
||||
import com.github.tomakehurst.wiremock.junit.WireMockRule;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.*;
|
||||
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class BlockingClientUnitTest {
|
||||
private static final String REQUESTED_RESOURCE = "/test.json";
|
||||
|
||||
@Rule public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort());
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
stubFor(get(urlEqualTo(REQUESTED_RESOURCE)).willReturn(aResponse()
|
||||
.withStatus(200)
|
||||
.withBody("{ \"response\" : \"It worked!\" }\r\n\r\n")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJavaIOSocket_whenReadingAndWritingWithStreams_thenSuccess() throws IOException {
|
||||
// given an IO socket and somewhere to store our result
|
||||
Socket socket = new Socket("localhost", wireMockRule.port());
|
||||
StringBuilder ourStore = new StringBuilder();
|
||||
|
||||
// when we write and read (using try-with-resources so our resources are auto-closed)
|
||||
try (InputStream serverInput = socket.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(serverInput));
|
||||
OutputStream clientOutput = socket.getOutputStream();
|
||||
PrintWriter writer = new PrintWriter(new OutputStreamWriter(clientOutput))) {
|
||||
writer.print("GET " + REQUESTED_RESOURCE + " HTTP/1.0\r\n\r\n");
|
||||
writer.flush(); // important - without this the request is never sent, and the test will hang on readLine()
|
||||
|
||||
for (String line; (line = reader.readLine()) != null; ) {
|
||||
ourStore.append(line);
|
||||
ourStore.append(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
|
||||
// then we read and saved our data
|
||||
assertTrue(ourStore
|
||||
.toString()
|
||||
.contains("It worked!"));
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
package com.baeldung.blockingnonblocking;
|
||||
|
||||
import com.github.tomakehurst.wiremock.junit.WireMockRule;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.*;
|
||||
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class NonBlockingClientUnitTest {
|
||||
private String REQUESTED_RESOURCE = "/test.json";
|
||||
|
||||
@Rule public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort());
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
stubFor(get(urlEqualTo(REQUESTED_RESOURCE)).willReturn(aResponse()
|
||||
.withStatus(200)
|
||||
.withBody("{ \"response\" : \"It worked!\" }")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJavaNIOSocketChannel_whenReadingAndWritingWithBuffers_thenSuccess() throws IOException {
|
||||
// given a NIO SocketChannel and a charset
|
||||
InetSocketAddress address = new InetSocketAddress("localhost", wireMockRule.port());
|
||||
SocketChannel socketChannel = SocketChannel.open(address);
|
||||
Charset charset = StandardCharsets.UTF_8;
|
||||
|
||||
// when we write and read using buffers
|
||||
socketChannel.write(charset.encode(CharBuffer.wrap("GET " + REQUESTED_RESOURCE + " HTTP/1.0\r\n\r\n")));
|
||||
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(8192); // or allocateDirect if we need direct memory access
|
||||
CharBuffer charBuffer = CharBuffer.allocate(8192);
|
||||
CharsetDecoder charsetDecoder = charset.newDecoder();
|
||||
StringBuilder ourStore = new StringBuilder();
|
||||
while (socketChannel.read(byteBuffer) != -1 || byteBuffer.position() > 0) {
|
||||
byteBuffer.flip();
|
||||
storeBufferContents(byteBuffer, charBuffer, charsetDecoder, ourStore);
|
||||
byteBuffer.compact();
|
||||
}
|
||||
socketChannel.close();
|
||||
|
||||
// then we read and saved our data
|
||||
assertTrue(ourStore
|
||||
.toString()
|
||||
.contains("It worked!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJavaNIOSocketChannel_whenReadingAndWritingWithSmallBuffers_thenSuccess() throws IOException {
|
||||
// given a NIO SocketChannel and a charset
|
||||
InetSocketAddress address = new InetSocketAddress("localhost", wireMockRule.port());
|
||||
SocketChannel socketChannel = SocketChannel.open(address);
|
||||
Charset charset = StandardCharsets.UTF_8;
|
||||
|
||||
// when we write and read using buffers that are too small for our message
|
||||
socketChannel.write(charset.encode(CharBuffer.wrap("GET " + REQUESTED_RESOURCE + " HTTP/1.0\r\n\r\n")));
|
||||
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(8); // or allocateDirect if we need direct memory access
|
||||
CharBuffer charBuffer = CharBuffer.allocate(8);
|
||||
CharsetDecoder charsetDecoder = charset.newDecoder();
|
||||
StringBuilder ourStore = new StringBuilder();
|
||||
while (socketChannel.read(byteBuffer) != -1 || byteBuffer.position() > 0) {
|
||||
byteBuffer.flip();
|
||||
storeBufferContents(byteBuffer, charBuffer, charsetDecoder, ourStore);
|
||||
byteBuffer.compact();
|
||||
}
|
||||
socketChannel.close();
|
||||
|
||||
// then we read and saved our data
|
||||
assertTrue(ourStore
|
||||
.toString()
|
||||
.contains("It worked!"));
|
||||
}
|
||||
|
||||
void storeBufferContents(ByteBuffer byteBuffer, CharBuffer charBuffer, CharsetDecoder charsetDecoder, StringBuilder ourStore) {
|
||||
charsetDecoder.decode(byteBuffer, charBuffer, true);
|
||||
charBuffer.flip();
|
||||
ourStore.append(charBuffer);
|
||||
charBuffer.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,4 +9,5 @@ This module contains articles about core features in the Java language
|
||||
- [Java Default Parameters Using Method Overloading](https://www.baeldung.com/java-default-parameters-method-overloading)
|
||||
- [How to Return Multiple Values From a Java Method](https://www.baeldung.com/java-method-return-multiple-values)
|
||||
- [Guide to the Java finally Keyword](https://www.baeldung.com/java-finally-keyword)
|
||||
- [The Java Headless Mode](https://www.baeldung.com/java-headless-mode)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-lang)
|
||||
|
||||
@@ -8,4 +8,5 @@ This module contains articles about core Java non-blocking input and output (IO)
|
||||
- [Create a Symbolic Link with Java](https://www.baeldung.com/java-symlink)
|
||||
- [Introduction to the Java NIO Selector](https://www.baeldung.com/java-nio-selector)
|
||||
- [Using Java MappedByteBuffer](https://www.baeldung.com/java-mapped-byte-buffer)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-nio)
|
||||
- [How to Lock a File in Java](https://www.baeldung.com/java-lock-files)
|
||||
- [[<-- Prev]](/core-java-modules/core-java-nio)
|
||||
|
||||
@@ -10,3 +10,4 @@ This module contains articles about performance of Java applications
|
||||
- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions)
|
||||
- [Monitoring Java Applications with Flight Recorder](https://www.baeldung.com/java-flight-recorder-monitoring)
|
||||
- [Branch Prediction in Java](https://www.baeldung.com/java-branch-prediction)
|
||||
- [Capturing a Java Thread Dump](https://www.baeldung.com/java-thread-dump)
|
||||
|
||||
@@ -8,3 +8,4 @@
|
||||
- [Guide to Escaping Characters in Java RegExps](http://www.baeldung.com/java-regexp-escape-char)
|
||||
- [Pre-compile Regex Patterns Into Pattern Objects](https://www.baeldung.com/java-regex-pre-compile)
|
||||
- [Difference Between Java Matcher find() and matches()](https://www.baeldung.com/java-matcher-find-vs-matches)
|
||||
- [How to Use Regular Expressions to Replace Tokens in Strings](https://www.baeldung.com/java-regex-token-replacement)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
### Relevant Articles:
|
||||
|
||||
- [Guide To The Java Authentication And Authorization Service (JAAS)](https://www.baeldung.com/java-authentication-authorization-service)
|
||||
@@ -10,4 +10,5 @@ This module contains articles about string operations.
|
||||
- [Java String equalsIgnoreCase()](https://www.baeldung.com/java-string-equalsignorecase)
|
||||
- [Case-Insensitive String Matching in Java](https://www.baeldung.com/java-case-insensitive-string-matching)
|
||||
- [L-Trim and R-Trim in Java](https://www.baeldung.com/l-trim-and-r-trim-in-java)
|
||||
- [L-Trim and R-Trim Alternatives in Java](https://www.baeldung.com/java-trim-alternatives)
|
||||
- More articles: [[<-- prev]](../core-java-string-operations)
|
||||
|
||||
@@ -64,6 +64,11 @@
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh-generator.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons-codec.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
@@ -113,6 +118,7 @@
|
||||
<hibernate-validator.version>6.0.2.Final</hibernate-validator.version>
|
||||
<javax.el-api.version>3.0.0</javax.el-api.version>
|
||||
<javax.el.version>2.2.6</javax.el.version>
|
||||
<commons-codec.version>1.14</commons-codec.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" 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">
|
||||
<project
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.core-kotlin-modules</groupId>
|
||||
<artifactId>core-kotlin-modules</artifactId>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
## Core Scala
|
||||
|
||||
This module contains articles about Scala's core features
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [Introduction to Scala](https://www.baeldung.com/scala-intro)
|
||||
- [Regular Expressions in Scala](https://www.baeldung.com/scala/regular-expressions)
|
||||
+5
-3
@@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" 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">
|
||||
<project
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>core-scala</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
@@ -51,5 +53,5 @@
|
||||
<scala.version>2.12.7</scala.version>
|
||||
<scala.plugin.version>3.3.2</scala.plugin.version>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.baeldung.scala
|
||||
|
||||
/**
|
||||
* Sample code demonstrating the various control structured.
|
||||
*
|
||||
* @author Chandra Prakash
|
||||
*
|
||||
*/
|
||||
object ControlStructuresDemo {
|
||||
def gcd(x : Int, y : Int) : Int = {
|
||||
if (y == 0) x else gcd(y, x % y)
|
||||
}
|
||||
|
||||
def gcdIter(x : Int, y : Int) : Int = {
|
||||
var a = x
|
||||
var b = y
|
||||
while (b > 0) {
|
||||
a = a % b
|
||||
val t = a
|
||||
a = b
|
||||
b = t
|
||||
}
|
||||
a
|
||||
}
|
||||
|
||||
def rangeSum(a : Int, b : Int) = {
|
||||
var sum = 0;
|
||||
for (i <- a to b) {
|
||||
sum += i
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
def factorial(a : Int) : Int = {
|
||||
var result = 1;
|
||||
var i = 1;
|
||||
do {
|
||||
result *= i
|
||||
i = i + 1
|
||||
} while (i <= a)
|
||||
result
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user