Merge remote-tracking branch 'eugenp/master'

This commit is contained in:
DOHA 2019-07-31 17:18:54 +03:00
commit 31d74aa6a4
398 changed files with 7105 additions and 652 deletions

View File

@ -1,12 +1,16 @@
The "REST with Spring" Classes
The Courses
==============================
Here's the Master Class of REST With Spring (along with the newly announced Boot 2 material): <br/>
**[>> THE REST WITH SPRING - MASTER CLASS](http://www.baeldung.com/rest-with-spring-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=rws#master-class)**
And here's the Master Class of Learn Spring Security: <br/>
**[>> LEARN SPRING SECURITY - MASTER CLASS](http://www.baeldung.com/learn-spring-security-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=lss#master-class)**
Here's the new "Learn Spring" course: <br/>
**[>> LEARN SPRING - THE MASTER CLASS](https://www.baeldung.com/learn-spring-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=ls#master-class)**
Here's the Master Class of "REST With Spring" (along with the new announced Boot 2 material): <br/>
**[>> THE REST WITH SPRING - MASTER CLASS](https://www.baeldung.com/rest-with-spring-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=rws#master-class)**
And here's the Master Class of "Learn Spring Security": <br/>
**[>> LEARN SPRING SECURITY - MASTER CLASS](https://www.baeldung.com/learn-spring-security-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=lss#master-class)**
@ -15,7 +19,7 @@ Java and Spring Tutorials
This project is **a collection of small and focused tutorials** - each covering a single and well defined area of development in the Java ecosystem.
A strong focus of these is, of course, the Spring Framework - Spring, Spring Boot and Spring Security.
In additional to Spring, the following technologies are in focus: `core Java`, `Jackson`, `HttpClient`, `Guava`.
In additional to Spring, the modules here are covering a number of aspects in Java.
Building the project
@ -32,8 +36,15 @@ Running a Spring Boot module
====================
To run a Spring Boot module run the command: `mvn spring-boot:run` in the module directory
###Running Tests
Working with the IDE
====================
This repo contains a large number of modules.
When you're working with an individual module, there's no need to import all of them (or build all of them) - you can simply import that particular module in either Eclipse or IntelliJ.
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`

View File

@ -0,0 +1,30 @@
package com.baeldung.algorithms.stringsortingbynumber;
import java.util.Comparator;
public final class NaturalOrderComparators {
private static final String DIGIT_AND_DECIMAL_REGEX = "[^\\d.]";
private NaturalOrderComparators() {
throw new AssertionError("Let's keep this static");
}
public static Comparator<String> createNaturalOrderRegexComparator() {
return Comparator.comparingDouble(NaturalOrderComparators::parseStringToNumber);
}
private static double parseStringToNumber(String input){
final String digitsOnly = input.replaceAll(DIGIT_AND_DECIMAL_REGEX, "");
if("".equals(digitsOnly)) return 0;
try{
return Double.parseDouble(digitsOnly);
}catch (NumberFormatException nfe){
return 0;
}
}
}

View File

@ -0,0 +1,79 @@
package com.baeldung.algorithms.stringsortingbynumber;
import com.baeldung.algorithms.stringsortingbynumber.NaturalOrderComparators;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.*;
public class NaturalOrderComparatorsUnitTest {
@Test
public void givenSimpleStringsContainingIntsAndDoubles_whenSortedByRegex_checkSortingCorrect() {
List<String> testStrings = Arrays.asList("a1", "b3", "c4", "d2.2", "d2.4", "d2.3d");
testStrings.sort(NaturalOrderComparators.createNaturalOrderRegexComparator());
List<String> expected = Arrays.asList("a1", "d2.2", "d2.3d", "d2.4", "b3", "c4");
assertEquals(expected, testStrings);
}
@Test
public void givenSimpleStringsContainingIntsAndDoublesWithAnInvalidNumber_whenSortedByRegex_checkSortingCorrect() {
List<String> testStrings = Arrays.asList("a1", "b3", "c4", "d2.2", "d2.4", "d2.3.3d");
testStrings.sort(NaturalOrderComparators.createNaturalOrderRegexComparator());
List<String> expected = Arrays.asList("d2.3.3d", "a1", "d2.2", "d2.4", "b3", "c4");
assertEquals(expected, testStrings);
}
@Test
public void givenAllForseenProblems_whenSortedByRegex_checkSortingCorrect() {
List<String> testStrings = Arrays.asList("a1", "b3", "c4", "d2.2", "d2.f4", "d2.3.3d");
testStrings.sort(NaturalOrderComparators.createNaturalOrderRegexComparator());
List<String> expected = Arrays.asList("d2.3.3d", "a1", "d2.2", "d2.f4", "b3", "c4");
assertEquals(expected, testStrings);
}
@Test
public void givenComplexStringsContainingSeparatedNumbers_whenSortedByRegex_checkNumbersCondensedAndSorted() {
List<String> testStrings = Arrays.asList("a1b2c5", "b3ght3.2", "something65.thensomething5"); //125, 33.2, 65.5
List<String> expected = Arrays.asList("b3ght3.2", "something65.thensomething5", "a1b2c5" );
testStrings.sort(NaturalOrderComparators.createNaturalOrderRegexComparator());
assertEquals(expected, testStrings);
}
@Test
public void givenStringsNotContainingNumbers_whenSortedByRegex_checkOrderNotChanged() {
List<String> testStrings = Arrays.asList("a", "c", "d", "e");
List<String> expected = new ArrayList<>(testStrings);
testStrings.sort(NaturalOrderComparators.createNaturalOrderRegexComparator());
assertEquals(expected, testStrings);
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.algorithms.shellsort;
public class ShellSort {
public static void sort(int arrayToSort[]) {
int n = arrayToSort.length;
for (int gap = n / 2; gap > 0; gap /= 2) {
for (int i = gap; i < n; i++) {
int key = arrayToSort[i];
int j = i;
while (j >= gap && arrayToSort[j - gap] > key) {
arrayToSort[j] = arrayToSort[j - gap];
j -= gap;
}
arrayToSort[j] = key;
}
}
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.algorithms.shellsort;
import static org.junit.Assert.*;
import static org.junit.Assert.assertArrayEquals;
import org.junit.Test;
public class ShellSortUnitTest {
@Test
public void givenUnsortedArray_whenShellSort_thenSortedAsc() {
int[] input = {41, 15, 82, 5, 65, 19, 32, 43, 8};
ShellSort.sort(input);
int[] expected = {5, 8, 15, 19, 32, 41, 43, 65, 82};
assertArrayEquals("the two arrays are not equal", expected, input);
}
}

View File

@ -18,12 +18,6 @@
<groupId>org.axonframework</groupId>
<artifactId>axon-spring-boot-starter</artifactId>
<version>${axon.version}</version>
<exclusions>
<exclusion>
<groupId>org.axonframework</groupId>
<artifactId>axon-server-connector</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -58,7 +52,7 @@
</dependencies>
<properties>
<axon.version>4.0.3</axon.version>
<axon.version>4.1.2</axon.version>
</properties>
</project>

View File

@ -13,6 +13,7 @@ import com.baeldung.axon.coreapi.commands.ShipOrderCommand;
import com.baeldung.axon.coreapi.events.OrderConfirmedEvent;
import com.baeldung.axon.coreapi.events.OrderPlacedEvent;
import com.baeldung.axon.coreapi.events.OrderShippedEvent;
import com.baeldung.axon.coreapi.exceptions.UnconfirmedOrderException;
@Aggregate
public class OrderAggregate {
@ -34,7 +35,7 @@ public class OrderAggregate {
@CommandHandler
public void handle(ShipOrderCommand command) {
if (!orderConfirmed) {
throw new IllegalStateException("Cannot ship an order which has not been confirmed yet.");
throw new UnconfirmedOrderException();
}
apply(new OrderShippedEvent(orderId));
@ -43,12 +44,12 @@ public class OrderAggregate {
@EventSourcingHandler
public void on(OrderPlacedEvent event) {
this.orderId = event.getOrderId();
orderConfirmed = false;
this.orderConfirmed = false;
}
@EventSourcingHandler
public void on(OrderConfirmedEvent event) {
orderConfirmed = true;
this.orderConfirmed = true;
}
protected OrderAggregate() {

View File

@ -0,0 +1,8 @@
package com.baeldung.axon.coreapi.exceptions;
public class UnconfirmedOrderException extends IllegalStateException {
public UnconfirmedOrderException() {
super("Cannot ship an order which has not been confirmed yet.");
}
}

View File

@ -5,6 +5,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.axonframework.config.ProcessingGroup;
import org.axonframework.eventhandling.EventHandler;
import org.axonframework.queryhandling.QueryHandler;
import org.springframework.stereotype.Service;
@ -16,6 +17,7 @@ import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery;
import com.baeldung.axon.coreapi.queries.OrderedProduct;
@Service
@ProcessingGroup("ordered-products")
public class OrderedProductsEventHandler {
private final Map<String, OrderedProduct> orderedProducts = new HashMap<>();

View File

@ -0,0 +1 @@
spring.application.name=Order Management Service

View File

@ -2,6 +2,7 @@ package com.baeldung.axon.commandmodel;
import java.util.UUID;
import com.baeldung.axon.coreapi.exceptions.UnconfirmedOrderException;
import org.axonframework.test.aggregate.AggregateTestFixture;
import org.axonframework.test.aggregate.FixtureConfiguration;
import org.junit.*;
@ -41,12 +42,12 @@ public class OrderAggregateUnitTest {
}
@Test
public void givenOrderPlacedEvent_whenShipOrderCommand_thenShouldThrowIllegalStateException() {
public void givenOrderPlacedEvent_whenShipOrderCommand_thenShouldThrowUnconfirmedOrderException() {
String orderId = UUID.randomUUID().toString();
String product = "Deluxe Chair";
fixture.given(new OrderPlacedEvent(orderId, product))
.when(new ShipOrderCommand(orderId))
.expectException(IllegalStateException.class);
.expectException(UnconfirmedOrderException.class);
}
@Test

View File

@ -1,3 +1,4 @@
## Relevant articles:
## Relevant Articles:
- [String API Updates in Java 12](https://www.baeldung.com/java12-string-api)

View File

@ -0,0 +1,25 @@
*.class
0.*
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
.resourceCache
# Packaged files #
*.jar
*.war
*.ear
# Files generated by integration tests
backup-pom.xml
/bin/
/temp
#IntelliJ specific
.idea/
*.iml

View File

@ -0,0 +1,50 @@
<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</groupId>
<artifactId>core-java-arrays-2</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-arrays-2</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-java</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-java</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<!-- test scoped -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>core-java-arrays-2</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<properties>
<!-- util -->
<commons-lang3.version>3.9</commons-lang3.version>
<!-- testing -->
<assertj-core.version>3.10.0</assertj-core.version>
</properties>
</project>

View File

@ -0,0 +1,45 @@
package com.baeldung.array.looping;
public class LoopDiagonally {
public String loopDiagonally(String[][] twoDArray) {
int length = twoDArray.length;
int diagonalLines = (length + length) - 1;
int itemsInDiagonal = 0;
int midPoint = (diagonalLines / 2) + 1;
StringBuilder output = new StringBuilder();
for (int i = 1; i <= diagonalLines; i++) {
StringBuilder items = new StringBuilder();
int rowIndex;
int columnIndex;
if (i <= midPoint) {
itemsInDiagonal++;
for (int j = 0; j < itemsInDiagonal; j++) {
rowIndex = (i - j) - 1;
columnIndex = j;
items.append(twoDArray[rowIndex][columnIndex]);
}
} else {
itemsInDiagonal--;
for (int j = 0; j < itemsInDiagonal; j++) {
rowIndex = (length - 1) - j;
columnIndex = (i - length) + j;
items.append(twoDArray[rowIndex][columnIndex]);
}
}
if (i != diagonalLines) {
output.append(items).append(" ");
} else {
output.append(items);
}
}
return output.toString();
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.array.looping;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class LoopDiagonallyUnitTest {
@Test
public void twoArrayIsLoopedDiagonallyAsExpected() {
LoopDiagonally loopDiagonally = new LoopDiagonally();
String[][] twoDArray = {{"a", "b", "c"},
{"d", "e", "f"},
{"g", "h", "i"}};
String output = loopDiagonally.loopDiagonally(twoDArray);
assertEquals("a db gec hf i", output);
}
}

View File

@ -2,7 +2,10 @@ package com.baeldung.array;
import com.baeldung.arraycopy.model.Employee;
import java.util.Comparator;
public class SortedArrayChecker {
boolean isSorted(int[] array, int length) {
if (array == null || length < 2)
return true;
@ -22,7 +25,7 @@ public class SortedArrayChecker {
return true;
}
boolean isSorted(String[] array, int length) {
boolean isSorted(Comparable[] array, int length) {
if (array == null || length < 2)
return true;
@ -32,40 +35,31 @@ public class SortedArrayChecker {
return isSorted(array, length - 1);
}
boolean isSorted(String[] array) {
boolean isSorted(Comparable[] array) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i].compareTo(array[i + 1]) > 0)
return false;
}
return true;
}
}
boolean isSortedByName(Employee[] array) {
boolean isSorted(Object[] array, Comparator comparator) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i].getName().compareTo(array[i + 1].getName()) > 0)
if (comparator.compare(array[i], (array[i + 1])) > 0)
return false;
}
return true;
}
boolean isSortedByAge(Employee[] array) {
for (int i = 0; i < array.length - 1; ++i) {
if (array[i].getAge() > (array[i + 1].getAge()))
return false;
}
return true;
}
boolean isSortedByAge(Employee[] array, int length) {
boolean isSorted(Object[] array, Comparator comparator, int length) {
if (array == null || length < 2)
return true;
if (array[length - 2].getAge() > array[length - 1].getAge())
if (comparator.compare(array[length - 2], array[length - 1]) > 0)
return false;
return isSortedByAge(array, length - 1);
return isSorted(array, comparator, length - 1);
}
}

View File

@ -4,32 +4,33 @@ import com.baeldung.arraycopy.model.Employee;
import org.junit.Before;
import org.junit.Test;
import java.util.Comparator;
import static org.assertj.core.api.Assertions.assertThat;
class SortedArrayCheckerUnitTest {
public class SortedArrayCheckerUnitTest {
private static final int[] INTEGER_SORTED = {1, 3, 5, 7, 9};
private static final int[] INTEGER_NOT_SORTED = {1, 3, 11, 7};
private static final String[] STRING_SORTED = {"abc", "cde", "fgh"};
private static final String[] STRING_NOT_SORTED = {"abc", "fgh", "cde", "ijk"};
private final Employee[] EMPLOYEES_SORTED_BY_NAME = {
private static final Employee[] EMPLOYEES_SORTED_BY_NAME = {
new Employee(1, "Carlos", 26),
new Employee(2, "Daniel", 31),
new Employee(3, "Marta", 27)};
private final Employee[] EMPLOYEES_NOT_SORTED_BY_NAME = {
private static final Employee[] EMPLOYEES_NOT_SORTED_BY_NAME = {
new Employee(1, "Daniel", 31),
new Employee(2, "Carlos", 26),
new Employee(3, "Marta", 27)};
private final Employee[] EMPLOYEES_SORTED_BY_AGE = {
private static final Employee[] EMPLOYEES_SORTED_BY_AGE = {
new Employee(1, "Carlos", 26),
new Employee(2, "Marta", 27),
new Employee(3, "Daniel", 31)};
private final Employee[] EMPLOYEES_NOT_SORTED_BY_AGE = {
private static final Employee[] EMPLOYEES_NOT_SORTED_BY_AGE = {
new Employee(1, "Marta", 27),
new Employee(2, "Carlos", 26),
new Employee(3, "Daniel", 31)};
@ -61,13 +62,18 @@ class SortedArrayCheckerUnitTest {
@Test
public void givenEmployeeArray_thenReturnIfItIsSortedOrNot() {
assertThat(sortedArrayChecker.isSortedByName(EMPLOYEES_SORTED_BY_NAME)).isEqualTo(true);
assertThat(sortedArrayChecker.isSortedByName(EMPLOYEES_NOT_SORTED_BY_NAME)).isEqualTo(false);
assertThat(sortedArrayChecker.isSorted(EMPLOYEES_SORTED_BY_NAME, Comparator.comparing(Employee::getName))).isEqualTo(true);
assertThat(sortedArrayChecker.isSorted(EMPLOYEES_NOT_SORTED_BY_NAME, Comparator.comparing(Employee::getName))).isEqualTo(false);
assertThat(sortedArrayChecker.isSortedByAge(EMPLOYEES_SORTED_BY_AGE)).isEqualTo(true);
assertThat(sortedArrayChecker.isSortedByAge(EMPLOYEES_NOT_SORTED_BY_AGE)).isEqualTo(false);
assertThat(sortedArrayChecker.isSorted(EMPLOYEES_SORTED_BY_AGE, Comparator.comparingInt(Employee::getAge))).isEqualTo(true);
assertThat(sortedArrayChecker.isSorted(EMPLOYEES_NOT_SORTED_BY_AGE, Comparator.comparingInt(Employee::getAge))).isEqualTo(false);
assertThat(sortedArrayChecker.isSortedByAge(EMPLOYEES_SORTED_BY_AGE, EMPLOYEES_SORTED_BY_AGE.length)).isEqualTo(true);
assertThat(sortedArrayChecker.isSortedByAge(EMPLOYEES_NOT_SORTED_BY_AGE, EMPLOYEES_NOT_SORTED_BY_AGE.length)).isEqualTo(false);
assertThat(sortedArrayChecker
.isSorted(EMPLOYEES_SORTED_BY_AGE, Comparator.comparingInt(Employee::getAge), EMPLOYEES_SORTED_BY_AGE.length))
.isEqualTo(true);
assertThat(sortedArrayChecker
.isSorted(EMPLOYEES_NOT_SORTED_BY_AGE, Comparator.comparingInt(Employee::getAge), EMPLOYEES_NOT_SORTED_BY_AGE.length))
.isEqualTo(false);
}
}

View File

@ -1,3 +1,3 @@
## Relevant articles:
## Relevant Articles:
- [Will an Error Be Caught by Catch Block in Java?](https://www.baeldung.com/java-error-catch)

View File

@ -0,0 +1,24 @@
package com.baeldung.files;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingApacheCommonsIO;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingBufferedReader;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingGoogleGuava;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingLineNumberReader;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFileChannel;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFiles;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingScanner;
public class Main {
private static final String INPUT_FILE_NAME = "src/main/resources/input.txt";
public static void main(String... args) throws Exception {
System.out.printf("Total Number of Lines Using BufferedReader: %s%n", getTotalNumberOfLinesUsingBufferedReader(INPUT_FILE_NAME));
System.out.printf("Total Number of Lines Using LineNumberReader: %s%n", getTotalNumberOfLinesUsingLineNumberReader(INPUT_FILE_NAME));
System.out.printf("Total Number of Lines Using Scanner: %s%n", getTotalNumberOfLinesUsingScanner(INPUT_FILE_NAME));
System.out.printf("Total Number of Lines Using NIO Files: %s%n", getTotalNumberOfLinesUsingNIOFiles(INPUT_FILE_NAME));
System.out.printf("Total Number of Lines Using NIO FileChannel: %s%n", getTotalNumberOfLinesUsingNIOFileChannel(INPUT_FILE_NAME));
System.out.printf("Total Number of Lines Using Apache Commons IO: %s%n", getTotalNumberOfLinesUsingApacheCommonsIO(INPUT_FILE_NAME));
System.out.printf("Total Number of Lines Using NIO Google Guava: %s%n", getTotalNumberOfLinesUsingGoogleGuava(INPUT_FILE_NAME));
}
}

View File

@ -0,0 +1,112 @@
package com.baeldung.files;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Stream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
public class NumberOfLineFinder {
public static int getTotalNumberOfLinesUsingBufferedReader(String fileName) {
int lines = 0;
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
while (reader.readLine() != null) {
lines++;
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return lines;
}
public static int getTotalNumberOfLinesUsingLineNumberReader(String fileName) {
int lines = 0;
try (LineNumberReader reader = new LineNumberReader(new FileReader(fileName))) {
reader.skip(Integer.MAX_VALUE);
lines = reader.getLineNumber() + 1;
} catch (IOException ioe) {
ioe.printStackTrace();
}
return lines;
}
public static int getTotalNumberOfLinesUsingScanner(String fileName) {
int lines = 0;
try (Scanner scanner = new Scanner(new FileReader(fileName))) {
while (scanner.hasNextLine()) {
scanner.nextLine();
lines++;
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return lines;
}
public static int getTotalNumberOfLinesUsingNIOFiles(String fileName) {
int lines = 0;
try (Stream<String> fileStream = Files.lines(Paths.get(fileName))) {
lines = (int) fileStream.count();
} catch (IOException ioe) {
ioe.printStackTrace();
}
return lines;
}
public static int getTotalNumberOfLinesUsingNIOFileChannel(String fileName) {
int lines = 1;
try (FileChannel channel = FileChannel.open(Paths.get(fileName), StandardOpenOption.READ)) {
ByteBuffer byteBuffer = channel.map(MapMode.READ_ONLY, 0, channel.size());
while (byteBuffer.hasRemaining()) {
byte currentChar = byteBuffer.get();
if (currentChar == '\n') {
lines++;
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return lines;
}
public static int getTotalNumberOfLinesUsingApacheCommonsIO(String fileName) {
int lines = 0;
try {
LineIterator lineIterator = FileUtils.lineIterator(new File(fileName));
while (lineIterator.hasNext()) {
lineIterator.nextLine();
lines++;
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return lines;
}
public static int getTotalNumberOfLinesUsingGoogleGuava(String fileName) {
int lines = 0;
try {
List<String> lineItems = com.google.common.io.Files.readLines(Paths.get(fileName)
.toFile(), Charset.defaultCharset());
lines = lineItems.size();
} catch (IOException ioe) {
ioe.printStackTrace();
}
return lines;
}
}

View File

@ -0,0 +1,60 @@
package com.baeldung.file;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingApacheCommonsIO;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingBufferedReader;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingGoogleGuava;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingLineNumberReader;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFileChannel;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingNIOFiles;
import static com.baeldung.files.NumberOfLineFinder.getTotalNumberOfLinesUsingScanner;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class NumberOfLineFinderUnitTest {
private static final String INPUT_FILE_NAME = "src/main/resources/input.txt";
private static final int ACTUAL_LINE_COUNT = 45;
@Test
public void whenUsingBufferedReader_thenReturnTotalNumberOfLines() {
int lines = getTotalNumberOfLinesUsingBufferedReader(INPUT_FILE_NAME);
assertEquals(ACTUAL_LINE_COUNT, lines);
}
@Test
public void whenUsingLineNumberReader_thenReturnTotalNumberOfLines() {
int lines = getTotalNumberOfLinesUsingLineNumberReader(INPUT_FILE_NAME);
assertEquals(ACTUAL_LINE_COUNT, lines);
}
@Test
public void whenUsingScanner_thenReturnTotalNumberOfLines() {
int lines = getTotalNumberOfLinesUsingScanner(INPUT_FILE_NAME);
assertEquals(ACTUAL_LINE_COUNT, lines);
}
@Test
public void whenUsingNIOFiles_thenReturnTotalNumberOfLines() {
int lines = getTotalNumberOfLinesUsingNIOFiles(INPUT_FILE_NAME);
assertEquals(ACTUAL_LINE_COUNT, lines);
}
@Test
public void whenUsingNIOFileChannel_thenReturnTotalNumberOfLines() {
int lines = getTotalNumberOfLinesUsingNIOFileChannel(INPUT_FILE_NAME);
assertEquals(ACTUAL_LINE_COUNT, lines);
}
@Test
public void whenUsingApacheCommonsIO_thenReturnTotalNumberOfLines() {
int lines = getTotalNumberOfLinesUsingApacheCommonsIO(INPUT_FILE_NAME);
assertEquals(ACTUAL_LINE_COUNT, lines);
}
@Test
public void whenUsingGoogleGuava_thenReturnTotalNumberOfLines() {
int lines = getTotalNumberOfLinesUsingGoogleGuava(INPUT_FILE_NAME);
assertEquals(ACTUAL_LINE_COUNT, lines);
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.relationships.aggregation;
import java.util.List;
public class Car {
private List<Wheel> wheels;
}

View File

@ -0,0 +1,13 @@
package com.baeldung.relationships.aggregation;
import java.util.List;
public class CarWithStaticInnerWheel {
private List<Wheel> wheels;
public static class Wheel {
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.relationships.aggregation;
public class Wheel {
private Car car;
}

View File

@ -0,0 +1,7 @@
package com.baeldung.relationships.association;
public class Child {
private Mother mother;
}

View File

@ -0,0 +1,9 @@
package com.baeldung.relationships.association;
import java.util.List;
public class Mother {
private List<Child> children;
}

View File

@ -0,0 +1,18 @@
package com.baeldung.relationships.composition;
import java.util.List;
public class Building {
private String address;
private List<Room> rooms;
public class Room {
public String getBuildingAddress() {
return Building.this.address;
}
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.relationships.composition;
public class BuildingWithDefinitionRoomInMethod {
public Room createAnonymousRoom() {
return new Room() {
@Override
public void doInRoom() {}
};
}
public Room createInlineRoom() {
class InlineRoom implements Room {
@Override
public void doInRoom() {}
}
return new InlineRoom();
}
public Room createLambdaRoom() {
return () -> {};
}
public interface Room {
void doInRoom();
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.relationships.university;
import java.util.List;
public class Department {
private List<Professor> professors;
}

View File

@ -0,0 +1,10 @@
package com.baeldung.relationships.university;
import java.util.List;
public class Professor {
private List<Department> department;
private List<Professor> friends;
}

View File

@ -0,0 +1,9 @@
package com.baeldung.relationships.university;
import java.util.List;
public class University {
private List<Department> department;
}

View File

@ -0,0 +1,25 @@
*.class
0.*
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
.resourceCache
# Packaged files #
*.jar
*.war
*.ear
# Files generated by integration tests
backup-pom.xml
/bin/
/temp
#IntelliJ specific
.idea/
*.iml

View File

@ -0,0 +1,20 @@
<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-java-networking-2</artifactId>
<name>core-java-networking-2</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
</dependencies>
<build>
<finalName>core-java-networking-2</finalName>
</build>
</project>

View File

@ -0,0 +1,25 @@
package com.baeldung.url;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
public class UrlChecker {
public int getResponseCodeForURL(String address) throws IOException {
return getResponseCodeForURLUsing(address, "GET");
}
public int getResponseCodeForURLUsingHead(String address) throws IOException {
return getResponseCodeForURLUsing(address, "HEAD");
}
private int getResponseCodeForURLUsing(String address, String method) throws IOException {
HttpURLConnection.setFollowRedirects(false); // Set follow redirects to false
final URL url = new URL(address);
HttpURLConnection huc = (HttpURLConnection) url.openConnection();
huc.setRequestMethod(method);
return huc.getResponseCode();
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.url;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
import org.junit.Test;
public class UrlCheckerUnitTest {
@Test
public void givenValidUrl_WhenUsingHEAD_ThenReturn200() throws IOException {
UrlChecker tester = new UrlChecker();
int responseCode = tester.getResponseCodeForURLUsingHead("http://www.example.com");
assertEquals(200, responseCode);
}
@Test
public void givenInvalidIUrl_WhenUsingHEAD_ThenReturn404() throws IOException {
UrlChecker tester = new UrlChecker();
int responseCode = tester.getResponseCodeForURLUsingHead("http://www.example.com/unkownurl");
assertEquals(404, responseCode);
}
@Test
public void givenValidUrl_WhenUsingGET_ThenReturn200() throws IOException {
UrlChecker tester = new UrlChecker();
int responseCode = tester.getResponseCodeForURL("http://www.example.com");
assertEquals(200, responseCode);
}
@Test
public void givenInvalidIUrl_WhenUsingGET_ThenReturn404() throws IOException {
UrlChecker tester = new UrlChecker();
int responseCode = tester.getResponseCodeForURL("http://www.example.com/unkownurl");
assertEquals(404, responseCode);
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.sasl;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.RealmCallback;
public class ClientCallbackHandler implements CallbackHandler {
@Override
public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackException {
for (Callback cb : cbs) {
if (cb instanceof NameCallback) {
NameCallback nc = (NameCallback) cb;
nc.setName("username");
} else if (cb instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback) cb;
pc.setPassword("password".toCharArray());
} else if (cb instanceof RealmCallback) {
RealmCallback rc = (RealmCallback) cb;
rc.setText("myServer");
}
}
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung.sasl;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.RealmCallback;
public class ServerCallbackHandler implements CallbackHandler {
@Override
public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackException {
for (Callback cb : cbs) {
if (cb instanceof AuthorizeCallback) {
AuthorizeCallback ac = (AuthorizeCallback) cb;
ac.setAuthorized(true);
} else if (cb instanceof NameCallback) {
NameCallback nc = (NameCallback) cb;
nc.setName("username");
} else if (cb instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback) cb;
pc.setPassword("password".toCharArray());
} else if (cb instanceof RealmCallback) {
RealmCallback rc = (RealmCallback) cb;
rc.setText("myServer");
}
}
}
}

View File

@ -0,0 +1,76 @@
package com.baeldung.sasl;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class SaslUnitTest {
private static final String MECHANISM = "DIGEST-MD5";
private static final String SERVER_NAME = "myServer";
private static final String PROTOCOL = "myProtocol";
private static final String AUTHORIZATION_ID = null;
private static final String QOP_LEVEL = "auth-conf";
private SaslServer saslServer;
private SaslClient saslClient;
@Before
public void setUp() throws SaslException {
ServerCallbackHandler serverHandler = new ServerCallbackHandler();
ClientCallbackHandler clientHandler = new ClientCallbackHandler();
Map<String, String> props = new HashMap<>();
props.put(Sasl.QOP, QOP_LEVEL);
saslServer = Sasl.createSaslServer(MECHANISM, PROTOCOL, SERVER_NAME, props, serverHandler);
saslClient = Sasl.createSaslClient(new String[] { MECHANISM }, AUTHORIZATION_ID, PROTOCOL, SERVER_NAME, props, clientHandler);
}
@Test
public void givenHandlers_whenStarted_thenAutenticationWorks() throws SaslException {
byte[] challenge;
byte[] response;
challenge = saslServer.evaluateResponse(new byte[0]);
response = saslClient.evaluateChallenge(challenge);
challenge = saslServer.evaluateResponse(response);
response = saslClient.evaluateChallenge(challenge);
assertTrue(saslServer.isComplete());
assertTrue(saslClient.isComplete());
String qop = (String) saslClient.getNegotiatedProperty(Sasl.QOP);
assertEquals("auth-conf", qop);
byte[] outgoing = "Baeldung".getBytes();
byte[] secureOutgoing = saslClient.wrap(outgoing, 0, outgoing.length);
byte[] secureIncoming = secureOutgoing;
byte[] incoming = saslServer.unwrap(secureIncoming, 0, secureIncoming.length);
assertEquals("Baeldung", new String(incoming, StandardCharsets.UTF_8));
}
@After
public void tearDown() throws SaslException {
saslClient.dispose();
saslServer.dispose();
}
}

View File

@ -0,0 +1,3 @@
## Relevant Articles
- [Multi-Module Maven Application with Java Modules](https://www.baeldung.com/maven-multi-module-project-java-jpms)

View File

@ -17,6 +17,7 @@
<module>pre-jpms</module>
<module>core-java-exceptions</module>
<module>core-java-optional</module>
<module>core-java-networking-2</module>
</modules>
</project>

View File

@ -0,0 +1,148 @@
package com.baeldung.binarynumbers;
public class BinaryNumbers {
/**
* This method takes a decimal number and convert it into a binary number.
* example:- input:10, output:1010
*
* @param decimalNumber
* @return binary number
*/
public Integer convertDecimalToBinary(Integer decimalNumber) {
if (decimalNumber == 0) {
return decimalNumber;
}
StringBuilder binaryNumber = new StringBuilder();
while (decimalNumber > 0) {
int remainder = decimalNumber % 2;
int result = decimalNumber / 2;
binaryNumber.append(remainder);
decimalNumber = result;
}
binaryNumber = binaryNumber.reverse();
return Integer.valueOf(binaryNumber.toString());
}
/**
* This method takes a binary number and convert it into a decimal number.
* example:- input:101, output:5
*
* @param binary number
* @return decimal Number
*/
public Integer convertBinaryToDecimal(Integer binaryNumber) {
Integer result = 0;
Integer base = 1;
while (binaryNumber > 0) {
int lastDigit = binaryNumber % 10;
binaryNumber = binaryNumber / 10;
result += lastDigit * base;
base = base * 2;
}
return result;
}
/**
* This method accepts two binary numbers and returns sum of input numbers.
* Example:- firstNum: 101, secondNum: 100, output: 1001
*
* @param firstNum
* @param secondNum
* @return addition of input numbers
*/
public Integer addBinaryNumber(Integer firstNum, Integer secondNum) {
StringBuilder output = new StringBuilder();
int carry = 0;
int temp;
while (firstNum != 0 || secondNum != 0) {
temp = (firstNum % 10 + secondNum % 10 + carry) % 2;
output.append(temp);
carry = (firstNum % 10 + secondNum % 10 + carry) / 2;
firstNum = firstNum / 10;
secondNum = secondNum / 10;
}
if (carry != 0) {
output.append(carry);
}
return Integer.valueOf(output.reverse()
.toString());
}
/**
* This method takes two binary number as input and subtract second number from the first number.
* example:- firstNum: 1000, secondNum: 11, output: 101
* @param firstNum
* @param secondNum
* @return Result of subtraction of secondNum from first
*/
public Integer substractBinaryNumber(Integer firstNum, Integer secondNum) {
int onesComplement = Integer.valueOf(getOnesComplement(secondNum));
StringBuilder output = new StringBuilder();
int carry = 0;
int temp;
while (firstNum != 0 || onesComplement != 0) {
temp = (firstNum % 10 + onesComplement % 10 + carry) % 2;
output.append(temp);
carry = (firstNum % 10 + onesComplement % 10 + carry) / 2;
firstNum = firstNum / 10;
onesComplement = onesComplement / 10;
}
String additionOfFirstNumAndOnesComplement = output.reverse()
.toString();
if (carry == 1) {
return addBinaryNumber(Integer.valueOf(additionOfFirstNumAndOnesComplement), carry);
} else {
return getOnesComplement(Integer.valueOf(additionOfFirstNumAndOnesComplement));
}
}
public Integer getOnesComplement(Integer num) {
StringBuilder onesComplement = new StringBuilder();
while (num > 0) {
int lastDigit = num % 10;
if (lastDigit == 0) {
onesComplement.append(1);
} else {
onesComplement.append(0);
}
num = num / 10;
}
return Integer.valueOf(onesComplement.reverse()
.toString());
}
}

View File

@ -0,0 +1,73 @@
package com.baeldung.binarynumbers;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class BinaryNumbersUnitTest {
private BinaryNumbers binaryNumbers = new BinaryNumbers();
@Test
public void given_decimalNumber_then_returnBinaryNumber() {
assertEquals(Integer.valueOf(1000), binaryNumbers.convertDecimalToBinary(8));
assertEquals(Integer.valueOf(10100), binaryNumbers.convertDecimalToBinary(20));
}
@Test
public void given_decimalNumber_then_convertToBinaryNumber() {
assertEquals("1000", Integer.toBinaryString(8));
assertEquals("10100", Integer.toBinaryString(20));
}
@Test
public void given_binaryNumber_then_ConvertToDecimalNumber() {
assertEquals(8, Integer.parseInt("1000", 2));
assertEquals(20, Integer.parseInt("10100", 2));
}
@Test
public void given_binaryNumber_then_returnDecimalNumber() {
assertEquals(Integer.valueOf(8), binaryNumbers.convertBinaryToDecimal(1000));
assertEquals(Integer.valueOf(20), binaryNumbers.convertBinaryToDecimal(10100));
}
@Test
public void given_twoBinaryNumber_then_returnAddition() {
// adding 4 and 10
assertEquals(Integer.valueOf(1110), binaryNumbers.addBinaryNumber(100, 1010));
// adding 26 and 14
assertEquals(Integer.valueOf(101000), binaryNumbers.addBinaryNumber(11010, 1110));
}
@Test
public void given_twoBinaryNumber_then_returnSubtraction() {
// subtracting 16 from 25
assertEquals(Integer.valueOf(1001), binaryNumbers.substractBinaryNumber(11001, 10000));
// subtracting 29 from 16, the output here is negative
assertEquals(Integer.valueOf(1101), binaryNumbers.substractBinaryNumber(10000, 11101));
}
@Test
public void given_binaryLiteral_thenReturnDecimalValue() {
byte five = 0b101;
assertEquals((byte) 5, five);
short three = 0b11;
assertEquals((short) 3, three);
int nine = 0B1001;
assertEquals(9, nine);
long twentyNine = 0B11101;
assertEquals(29, twentyNine);
int minusThirtySeven = -0B100101;
assertEquals(-37, minusThirtySeven);
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.string.changecase;
import static org.junit.Assert.assertEquals;
import java.util.Locale;
import org.junit.Test;
public class ToLowerCaseUnitTest {
private static final Locale TURKISH = new Locale("tr");
private String name = "John Doe";
private String foreignUppercase = "\u0049";
@Test
public void givenMixedCaseString_WhenToLowerCase_ThenResultIsLowerCase() {
assertEquals("john doe", name.toLowerCase());
}
@Test
public void givenForeignString_WhenToLowerCaseWithoutLocale_ThenResultIsLowerCase() {
assertEquals("\u0069", foreignUppercase.toLowerCase());
}
@Test
public void givenForeignString_WhenToLowerCaseWithLocale_ThenResultIsLowerCase() {
assertEquals("\u0131", foreignUppercase.toLowerCase(TURKISH));
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.string.changecase;
import static org.junit.Assert.assertEquals;
import java.util.Locale;
import org.junit.Test;
public class ToUpperCaseUnitTest {
private static final Locale TURKISH = new Locale("tr");
private String name = "John Doe";
private String foreignLowercase = "\u0069";
@Test
public void givenMixedCaseString_WhenToUpperCase_ThenResultIsUpperCase() {
assertEquals("JOHN DOE", name.toUpperCase());
}
@Test
public void givenForeignString_WhenToUpperCaseWithoutLocale_ThenResultIsUpperCase() {
assertEquals("\u0049", foreignLowercase.toUpperCase());
}
@Test
public void givenForeignString_WhenToUpperCaseWithLocale_ThenResultIsUpperCase() {
assertEquals("\u0130", foreignLowercase.toUpperCase(TURKISH));
}
}

View File

@ -0,0 +1,56 @@
package com.baeldung.string.todouble;
import static org.junit.Assert.assertEquals;
import java.text.DecimalFormat;
import java.text.ParseException;
import org.junit.Test;
public class StringToDoubleConversionUnitTest {
@Test
public void givenValidString_WhenParseDouble_ThenResultIsPrimitiveDouble() {
assertEquals(1.23, Double.parseDouble("1.23"), 0.000001);
}
@Test(expected = NullPointerException.class)
public void givenNullString_WhenParseDouble_ThenNullPointerExceptionIsThrown() {
Double.parseDouble(null);
}
@Test(expected = NumberFormatException.class)
public void givenInalidString_WhenParseDouble_ThenNumberFormatExceptionIsThrown() {
Double.parseDouble("&");
}
@Test
public void givenValidString_WhenValueOf_ThenResultIsPrimitiveDouble() {
assertEquals(1.23, Double.valueOf("1.23"), 0.000001);
}
@Test(expected = NullPointerException.class)
public void givenNullString_WhenValueOf_ThenNullPointerExceptionIsThrown() {
Double.valueOf(null);
}
@Test(expected = NumberFormatException.class)
public void givenInalidString_WhenValueOf_ThenNumberFormatExceptionIsThrown() {
Double.valueOf("&");
}
@Test
public void givenValidString_WhenDecimalFormat_ThenResultIsValidDouble() throws ParseException {
assertEquals(1.23, new DecimalFormat("#").parse("1.23").doubleValue(), 0.000001);
}
@Test(expected = NullPointerException.class)
public void givenNullString_WhenDecimalFormat_ThenNullPointerExceptionIsThrown() throws ParseException {
new DecimalFormat("#").parse(null);
}
@Test(expected = ParseException.class)
public void givenInvalidString_WhenDecimalFormat_ThenParseExceptionIsThrown() throws ParseException {
new DecimalFormat("#").parse("&");
}
}

View File

@ -0,0 +1,19 @@
package org.baeldung.javabeanconstraints.bigdecimal;
import java.math.BigDecimal;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Digits;
public class Invoice {
@DecimalMin(value = "0.0", inclusive = false)
@Digits(integer=3, fraction=2)
private BigDecimal price;
private String description;
public Invoice(BigDecimal price, String description) {
this.price = price;
this.description = description;
}
}

View File

@ -0,0 +1,62 @@
package org.baeldung.javabeanconstraints.bigdecimal;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigDecimal;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import org.junit.BeforeClass;
import org.junit.Test;
public class InvoiceUnitTest {
private static Validator validator;
@BeforeClass
public static void setupValidatorInstance() {
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
@Test
public void whenPriceIntegerDigitLessThanThreeWithDecimalValue_thenShouldGiveConstraintViolations() {
Invoice invoice = new Invoice(new BigDecimal(10.21), "Book purchased");
Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
assertThat(violations.size()).isEqualTo(1);
violations.forEach(action-> assertThat(action.getMessage()).isEqualTo("numeric value out of bounds (<3 digits>.<2 digits> expected)"));
}
@Test
public void whenPriceIntegerDigitLessThanThreeWithIntegerValue_thenShouldNotGiveConstraintViolations() {
Invoice invoice = new Invoice(new BigDecimal(10), "Book purchased");
Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
assertThat(violations.size()).isEqualTo(0);
}
@Test
public void whenPriceIntegerDigitGreaterThanThree_thenShouldGiveConstraintViolations() {
Invoice invoice = new Invoice(new BigDecimal(1021.21), "Book purchased");
Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
assertThat(violations.size()).isEqualTo(1);
violations.forEach(action-> assertThat(action.getMessage()).isEqualTo("numeric value out of bounds (<3 digits>.<2 digits> expected)"));
}
@Test
public void whenPriceIsZero_thenShouldGiveConstraintViolations() {
Invoice invoice = new Invoice(new BigDecimal(000.00), "Book purchased");
Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
assertThat(violations.size()).isEqualTo(1);
violations.forEach(action-> assertThat(action.getMessage()).isEqualTo("must be greater than 0.0"));
}
@Test
public void whenPriceIsGreaterThanZero_thenShouldNotGiveConstraintViolations() {
Invoice invoice = new Invoice(new BigDecimal(100.50), "Book purchased");
Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
assertThat(violations.size()).isEqualTo(0);
}
}

View File

@ -0,0 +1,3 @@
## Relevant Articles
- [JHipster with a Microservice Architecture](https://www.baeldung.com/jhipster-microservices)

View File

@ -1,4 +1,6 @@
### Relevant articles
## Relevant Articles
- [Intro to JHipster](https://www.baeldung.com/jhipster)
# baeldung

View File

@ -0,0 +1,3 @@
## Relevant Articles
- [Building a Basic UAA-Secured JHipster Microservice](https://www.baeldung.com/jhipster-uaa-secured-micro-service)

View File

@ -121,8 +121,8 @@ public class AuthorizationEndpoint {
String redirectUri = originalParams.getFirst("resolved_redirect_uri");
StringBuilder sb = new StringBuilder(redirectUri);
String approbationStatus = params.getFirst("approbation_status");
if ("NO".equals(approbationStatus)) {
String approvalStatus = params.getFirst("approval_status");
if ("NO".equals(approvalStatus)) {
URI location = UriBuilder.fromUri(sb.toString())
.queryParam("error", "User doesn't approved the request.")
.queryParam("error_description", "User doesn't approved the request.")

View File

@ -15,15 +15,14 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@Path("token")
public class TokenEndpoint {
List<String> supportedGrantTypes = Collections.singletonList("authorization_code");
List<String> supportedGrantTypes = Arrays.asList("authorization_code", "refresh_token");
@Inject
private AppDataRepository appDataRepository;
@ -39,36 +38,36 @@ public class TokenEndpoint {
//Check grant_type params
String grantType = params.getFirst("grant_type");
Objects.requireNonNull(grantType, "grant_type params is required");
if (!supportedGrantTypes.contains(grantType)) {
JsonObject error = Json.createObjectBuilder()
.add("error", "unsupported_grant_type")
.add("error_description", "grant type should be one of :" + supportedGrantTypes)
.build();
return Response.status(Response.Status.BAD_REQUEST)
.entity(error).build();
if (grantType == null || grantType.isEmpty())
return responseError("Invalid_request", "grant_type is required", Response.Status.BAD_REQUEST);
if (!supportedGrantTypes.contains(grantType)) {
return responseError("unsupported_grant_type", "grant_type should be one of :" + supportedGrantTypes, Response.Status.BAD_REQUEST);
}
//Client Authentication
String[] clientCredentials = extract(authHeader);
if (clientCredentials.length != 2) {
return responseError("Invalid_request", "Bad Credentials client_id/client_secret", Response.Status.BAD_REQUEST);
}
String clientId = clientCredentials[0];
String clientSecret = clientCredentials[1];
Client client = appDataRepository.getClient(clientId);
if (client == null || clientSecret == null || !clientSecret.equals(client.getClientSecret())) {
JsonObject error = Json.createObjectBuilder()
.add("error", "invalid_client")
.build();
return Response.status(Response.Status.UNAUTHORIZED)
.entity(error).build();
if (client == null) {
return responseError("Invalid_request", "Invalid client_id", Response.Status.BAD_REQUEST);
}
String clientSecret = clientCredentials[1];
if (!clientSecret.equals(client.getClientSecret())) {
return responseError("Invalid_request", "Invalid client_secret", Response.Status.UNAUTHORIZED);
}
AuthorizationGrantTypeHandler authorizationGrantTypeHandler = authorizationGrantTypeHandlers.select(NamedLiteral.of(grantType)).get();
JsonObject tokenResponse = null;
try {
tokenResponse = authorizationGrantTypeHandler.createAccessToken(clientId, params);
} catch (WebApplicationException e) {
return e.getResponse();
} catch (Exception e) {
e.printStackTrace();
return responseError("Invalid_request", "Can't get token", Response.Status.INTERNAL_SERVER_ERROR);
}
return Response.ok(tokenResponse)
@ -81,6 +80,15 @@ public class TokenEndpoint {
if (authHeader != null && authHeader.startsWith("Basic ")) {
return new String(Base64.getDecoder().decode(authHeader.substring(6))).split(":");
}
return null;
return new String[]{};
}
private Response responseError(String error, String errorDescription, Response.Status status) {
JsonObject errorResponse = Json.createObjectBuilder()
.add("error", error)
.add("error_description", errorDescription)
.build();
return Response.status(status)
.entity(errorResponse).build();
}
}

View File

@ -0,0 +1,87 @@
package com.baeldung.oauth2.authorization.server.handler;
import com.baeldung.oauth2.authorization.server.PEMKeyUtils;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import org.eclipse.microprofile.config.Config;
import javax.inject.Inject;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Date;
import java.util.UUID;
public abstract class AbstractGrantTypeHandler implements AuthorizationGrantTypeHandler {
//Always RSA 256, but could be parametrized
protected JWSHeader jwsHeader = new JWSHeader.Builder(JWSAlgorithm.RS256).type(JOSEObjectType.JWT).build();
@Inject
protected Config config;
//30 min
protected Long expiresInMin = 30L;
protected JWSVerifier getJWSVerifier() throws Exception {
String verificationkey = config.getValue("verificationkey", String.class);
String pemEncodedRSAPublicKey = PEMKeyUtils.readKeyAsString(verificationkey);
RSAKey rsaPublicKey = (RSAKey) JWK.parseFromPEMEncodedObjects(pemEncodedRSAPublicKey);
return new RSASSAVerifier(rsaPublicKey);
}
protected JWSSigner getJwsSigner() throws Exception {
String signingkey = config.getValue("signingkey", String.class);
String pemEncodedRSAPrivateKey = PEMKeyUtils.readKeyAsString(signingkey);
RSAKey rsaKey = (RSAKey) JWK.parseFromPEMEncodedObjects(pemEncodedRSAPrivateKey);
return new RSASSASigner(rsaKey.toRSAPrivateKey());
}
protected String getAccessToken(String clientId, String subject, String approvedScope) throws Exception {
//4. Signing
JWSSigner jwsSigner = getJwsSigner();
Instant now = Instant.now();
//Long expiresInMin = 30L;
Date expirationTime = Date.from(now.plus(expiresInMin, ChronoUnit.MINUTES));
//3. JWT Payload or claims
JWTClaimsSet jwtClaims = new JWTClaimsSet.Builder()
.issuer("http://localhost:9080")
.subject(subject)
.claim("upn", subject)
.claim("client_id", clientId)
.audience("http://localhost:9280")
.claim("scope", approvedScope)
.claim("groups", Arrays.asList(approvedScope.split(" ")))
.expirationTime(expirationTime) // expires in 30 minutes
.notBeforeTime(Date.from(now))
.issueTime(Date.from(now))
.jwtID(UUID.randomUUID().toString())
.build();
SignedJWT signedJWT = new SignedJWT(jwsHeader, jwtClaims);
signedJWT.sign(jwsSigner);
return signedJWT.serialize();
}
protected String getRefreshToken(String clientId, String subject, String approvedScope) throws Exception {
JWSSigner jwsSigner = getJwsSigner();
Instant now = Instant.now();
//6.Build refresh token
JWTClaimsSet refreshTokenClaims = new JWTClaimsSet.Builder()
.subject(subject)
.claim("client_id", clientId)
.claim("scope", approvedScope)
//refresh token for 1 day.
.expirationTime(Date.from(now.plus(1, ChronoUnit.DAYS)))
.build();
SignedJWT signedRefreshToken = new SignedJWT(jwsHeader, refreshTokenClaims);
signedRefreshToken.sign(jwsSigner);
return signedRefreshToken.serialize();
}
}

View File

@ -1,18 +1,7 @@
package com.baeldung.oauth2.authorization.server.handler;
import com.baeldung.oauth2.authorization.server.PEMKeyUtils;
import com.baeldung.oauth2.authorization.server.model.AuthorizationCode;
import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import org.eclipse.microprofile.config.Config;
import javax.inject.Inject;
import javax.inject.Named;
import javax.json.Json;
import javax.json.JsonObject;
@ -20,22 +9,14 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Date;
import java.util.UUID;
@Named("authorization_code")
public class AuthorizationCodeGrantTypeHandler implements AuthorizationGrantTypeHandler {
public class AuthorizationCodeGrantTypeHandler extends AbstractGrantTypeHandler {
@PersistenceContext
private EntityManager entityManager;
@Inject
private Config config;
@Override
public JsonObject createAccessToken(String clientId, MultivaluedMap<String, String> params) throws Exception {
//1. code is required
@ -58,42 +39,16 @@ public class AuthorizationCodeGrantTypeHandler implements AuthorizationGrantType
throw new WebApplicationException("invalid_grant");
}
//JWT Header
JWSHeader jwsHeader = new JWSHeader.Builder(JWSAlgorithm.RS256).type(JOSEObjectType.JWT).build();
Instant now = Instant.now();
Long expiresInMin = 30L;
Date expiresIn = Date.from(now.plus(expiresInMin, ChronoUnit.MINUTES));
//3. JWT Payload or claims
JWTClaimsSet jwtClaims = new JWTClaimsSet.Builder()
.issuer("http://localhost:9080")
.subject(authorizationCode.getUserId())
.claim("upn", authorizationCode.getUserId())
.audience("http://localhost:9280")
.claim("scope", authorizationCode.getApprovedScopes())
.claim("groups", Arrays.asList(authorizationCode.getApprovedScopes().split(" ")))
.expirationTime(expiresIn) // expires in 30 minutes
.notBeforeTime(Date.from(now))
.issueTime(Date.from(now))
.jwtID(UUID.randomUUID().toString())
.build();
SignedJWT signedJWT = new SignedJWT(jwsHeader, jwtClaims);
//4. Signing
String signingkey = config.getValue("signingkey", String.class);
String pemEncodedRSAPrivateKey = PEMKeyUtils.readKeyAsString(signingkey);
RSAKey rsaKey = (RSAKey) JWK.parseFromPEMEncodedObjects(pemEncodedRSAPrivateKey);
signedJWT.sign(new RSASSASigner(rsaKey.toRSAPrivateKey()));
//5. Finally the JWT access token
String accessToken = signedJWT.serialize();
String accessToken = getAccessToken(clientId, authorizationCode.getUserId(), authorizationCode.getApprovedScopes());
String refreshToken = getRefreshToken(clientId, authorizationCode.getUserId(), authorizationCode.getApprovedScopes());
return Json.createObjectBuilder()
.add("token_type", "Bearer")
.add("access_token", accessToken)
.add("expires_in", expiresInMin * 60)
.add("scope", authorizationCode.getApprovedScopes())
.add("refresh_token", refreshToken)
.build();
}
}

View File

@ -0,0 +1,72 @@
package com.baeldung.oauth2.authorization.server.handler;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jwt.SignedJWT;
import javax.inject.Named;
import javax.json.Json;
import javax.json.JsonObject;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@Named("refresh_token")
public class RefreshTokenGrantTypeHandler extends AbstractGrantTypeHandler {
@Override
public JsonObject createAccessToken(String clientId, MultivaluedMap<String, String> params) throws Exception {
String refreshToken = params.getFirst("refresh_token");
if (refreshToken == null || "".equals(refreshToken)) {
throw new WebApplicationException("invalid_grant");
}
//Decode refresh token
SignedJWT signedRefreshToken = SignedJWT.parse(refreshToken);
JWSVerifier verifier = getJWSVerifier();
if (!signedRefreshToken.verify(verifier)) {
throw new WebApplicationException("Invalid refresh token.");
}
if (!(new Date().before(signedRefreshToken.getJWTClaimsSet().getExpirationTime()))) {
throw new WebApplicationException("Refresh token expired.");
}
String refreshTokenClientId = signedRefreshToken.getJWTClaimsSet().getStringClaim("client_id");
if (!clientId.equals(refreshTokenClientId)) {
throw new WebApplicationException("Invalid client_id.");
}
//At this point, the refresh token is valid and not yet expired
//So create a new access token from it.
String subject = signedRefreshToken.getJWTClaimsSet().getSubject();
String approvedScopes = signedRefreshToken.getJWTClaimsSet().getStringClaim("scope");
String requestedScopes = params.getFirst("scope");
if (requestedScopes != null && !requestedScopes.isEmpty()) {
Set<String> rScopes = new HashSet(Arrays.asList(requestedScopes.split(" ")));
Set<String> aScopes = new HashSet(Arrays.asList(approvedScopes.split(" ")));
if (!aScopes.containsAll(rScopes)) {
JsonObject error = Json.createObjectBuilder()
.add("error", "Invalid_request")
.add("error_description", "Requested scopes should be a subset of the original scopes.")
.build();
Response response = Response.status(Response.Status.BAD_REQUEST).entity(error).build();
throw new WebApplicationException(response);
}
} else {
requestedScopes = approvedScopes;
}
String accessToken = getAccessToken(clientId, subject, requestedScopes);
return Json.createObjectBuilder()
.add("token_type", "Bearer")
.add("access_token", accessToken)
.add("expires_in", expiresInMin * 60)
.add("scope", requestedScopes)
.add("refresh_token", refreshToken)
.build();
}
}

View File

@ -41,8 +41,8 @@
<tr>
<td colspan="2">
<input type="submit" name="approbation_status" value="YES"/>
<input type="submit" name="approbation_status" value="NO"/>
<input type="submit" name="approval_status" value="YES"/>
<input type="submit" name="approval_status" value="NO"/>
</td>
</tr>
</table>

View File

@ -0,0 +1,23 @@
package com.baeldung.oauth2.client;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Base64;
public abstract class AbstractServlet extends HttpServlet {
protected void dispatch(String location, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher requestDispatcher = request.getRequestDispatcher(location);
requestDispatcher.forward(request, response);
}
protected String getAuthorizationHeaderValue(String clientId, String clientSecret) {
String token = clientId + ":" + clientSecret;
String encodedString = Base64.getEncoder().encodeToString(token.getBytes());
return "Basic " + encodedString;
}
}

View File

@ -4,10 +4,8 @@ import org.eclipse.microprofile.config.Config;
import javax.inject.Inject;
import javax.json.JsonObject;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.client.Client;
@ -18,10 +16,9 @@ import javax.ws.rs.core.Form;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.Base64;
@WebServlet(urlPatterns = "/callback")
public class CallbackServlet extends HttpServlet {
public class CallbackServlet extends AbstractServlet {
@Inject
private Config config;
@ -29,6 +26,9 @@ public class CallbackServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String clientId = config.getValue("client.clientId", String.class);
String clientSecret = config.getValue("client.clientSecret", String.class);
//Error:
String error = request.getParameter("error");
if (error != null) {
@ -53,24 +53,15 @@ public class CallbackServlet extends HttpServlet {
form.param("code", code);
form.param("redirect_uri", config.getValue("client.redirectUri", String.class));
try {
JsonObject tokenResponse = target.request(MediaType.APPLICATION_JSON_TYPE)
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeaderValue())
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeaderValue(clientId, clientSecret))
.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE), JsonObject.class);
request.getSession().setAttribute("tokenResponse", tokenResponse);
} catch (Exception ex) {
System.out.println(ex.getMessage());
request.setAttribute("error", ex.getMessage());
}
dispatch("/", request, response);
}
private void dispatch(String location, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher requestDispatcher = request.getRequestDispatcher(location);
requestDispatcher.forward(request, response);
}
private String getAuthorizationHeaderValue() {
String clientId = config.getValue("client.clientId", String.class);
String clientSecret = config.getValue("client.clientSecret", String.class);
String token = clientId + ":" + clientSecret;
String encodedString = Base64.getEncoder().encodeToString(token.getBytes());
return "Basic " + encodedString;
}
}

View File

@ -0,0 +1,57 @@
package com.baeldung.oauth2.client;
import org.eclipse.microprofile.config.Config;
import javax.inject.Inject;
import javax.json.JsonObject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
@WebServlet(urlPatterns = "/refreshtoken")
public class RefreshTokenServlet extends AbstractServlet {
@Inject
private Config config;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String clientId = config.getValue("client.clientId", String.class);
String clientSecret = config.getValue("client.clientSecret", String.class);
JsonObject actualTokenResponse = (JsonObject) request.getSession().getAttribute("tokenResponse");
Client client = ClientBuilder.newClient();
WebTarget target = client.target(config.getValue("provider.tokenUri", String.class));
Form form = new Form();
form.param("grant_type", "refresh_token");
form.param("refresh_token", actualTokenResponse.getString("refresh_token"));
String scope = request.getParameter("scope");
if (scope != null && !scope.isEmpty()) {
form.param("scope", scope);
}
Response jaxrsResponse = target.request(MediaType.APPLICATION_JSON_TYPE)
.header(HttpHeaders.AUTHORIZATION, getAuthorizationHeaderValue(clientId, clientSecret))
.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE), Response.class);
JsonObject tokenResponse = jaxrsResponse.readEntity(JsonObject.class);
if (jaxrsResponse.getStatus() == 200) {
request.getSession().setAttribute("tokenResponse", tokenResponse);
} else {
request.setAttribute("error", tokenResponse.getString("error_description", "error!"));
}
dispatch("/", request, response);
}
}

View File

@ -10,6 +10,7 @@
body {
margin: 0px;
}
input[type=text], input[type=password] {
width: 75%;
padding: 4px 0px;
@ -17,6 +18,7 @@
border: 1px solid #502bcc;
box-sizing: border-box;
}
.container-error {
padding: 16px;
border: 1px solid #cc102a;
@ -25,6 +27,7 @@
margin-left: 25px;
margin-bottom: 25px;
}
.container {
padding: 16px;
border: 1px solid #130ecc;
@ -81,8 +84,20 @@
<li>access_token: ${tokenResponse.getString("access_token")}</li>
<li>scope: ${tokenResponse.getString("scope")}</li>
<li>Expires in (s): ${tokenResponse.getInt("expires_in")}</li>
<li>refresh_token: ${tokenResponse.getString("refresh_token")}</li>
</ul>
</div>
<div class="container">
<span><h4>Refresh Token</h4></span>
<hr>
<ul>
<li><a href="refreshtoken">Refresh token (original scope)</a></li>
<li><a href="refreshtoken?scope=resource.read">Refresh token (scope: resource.read)</a></li>
<li><a href="refreshtoken?scope=resource.write">Refresh token (scope: resource.write)</a></li>
</ul>
</div>
<div class="container">
<span><h4>OAuth2 Resource Server Call</h4></span>
<hr>
@ -90,7 +105,6 @@
<li><a href="downstream?action=read">Read Protected Resource</a></li>
<li><a href="downstream?action=write">Write Protected Resource</a></li>
</ul>
</div>
</body>

View File

@ -1 +0,0 @@
This is a parent module for projects that want to take advantage of the latest Spring Boot improvements/features.

View File

@ -1,92 +0,0 @@
<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>parent-boot-performance</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>parent-boot-performance</name>
<packaging>pom</packaging>
<description>Parent for all modules that want to take advantage of the latest Spring Boot improvements/features. Current version: 2.2</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>${start-class}</mainClass>
<!-- this is necessary as we're not using the Boot parent -->
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<profiles>
<profile>
<id>thin-jar</id>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<!-- The following enables the "thin jar" deployment option. -->
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>${thin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<rest-assured.version>3.1.0</rest-assured.version>
<!-- plugins -->
<thin.version>1.0.21.RELEASE</thin.version>
<spring-boot.version>2.2.0.M3</spring-boot.version>
</properties>
</project>

View File

@ -1 +1 @@
## Relevant articles:
## Relevant Articles:

View File

@ -1 +1 @@
## Relevant articles:
## Relevant Articles:

View File

@ -1 +1 @@
## Relevant articles:
## Relevant Articles:

View File

@ -0,0 +1,2 @@
### Relevant Articles:
- [Better Retries with Exponential Backoff and Jitter](https://baeldung.com/retries-with-exponential-backoff-and-jitter)

View File

@ -0,0 +1,54 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>backoff-jitter</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito-core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-retry</artifactId>
<version>${resilience4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<mockito-core.version>2.27.0</mockito-core.version>
<slf4j.version>1.7.26</slf4j.version>
<resilience4j.version>0.16.0</resilience4j.version>
</properties>
</project>

View File

@ -0,0 +1,103 @@
package com.baeldung.backoff.jitter;
import io.github.resilience4j.retry.IntervalFunction;
import io.github.resilience4j.retry.Retry;
import io.github.resilience4j.retry.RetryConfig;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.function.Function;
import static com.baeldung.backoff.jitter.BackoffWithJitterTest.RetryProperties.*;
import static io.github.resilience4j.retry.IntervalFunction.ofExponentialBackoff;
import static io.github.resilience4j.retry.IntervalFunction.ofExponentialRandomBackoff;
import static java.util.Collections.nCopies;
import static java.util.concurrent.Executors.newFixedThreadPool;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
public class BackoffWithJitterTest {
static Logger log = LoggerFactory.getLogger(BackoffWithJitterTest.class);
interface PingPongService {
String call(String ping) throws PingPongServiceException;
}
class PingPongServiceException extends RuntimeException {
public PingPongServiceException(String reason) {
super(reason);
}
}
private PingPongService service;
private static final int NUM_CONCURRENT_CLIENTS = 8;
@Before
public void setUp() {
service = mock(PingPongService.class);
}
@Test
public void whenRetryExponentialBackoff_thenRetriedConfiguredNoOfTimes() {
IntervalFunction intervalFn = ofExponentialBackoff(INITIAL_INTERVAL, MULTIPLIER);
Function<String, String> pingPongFn = getRetryablePingPongFn(intervalFn);
when(service.call(anyString())).thenThrow(PingPongServiceException.class);
try {
pingPongFn.apply("Hello");
} catch (PingPongServiceException e) {
verify(service, times(MAX_RETRIES)).call(anyString());
}
}
@Test
public void whenRetryExponentialBackoffWithoutJitter_thenThunderingHerdProblemOccurs() throws InterruptedException {
IntervalFunction intervalFn = ofExponentialBackoff(INITIAL_INTERVAL, MULTIPLIER);
test(intervalFn);
}
@Test
public void whenRetryExponentialBackoffWithJitter_thenRetriesAreSpread() throws InterruptedException {
IntervalFunction intervalFn = ofExponentialRandomBackoff(INITIAL_INTERVAL, MULTIPLIER, RANDOMIZATION_FACTOR);
test(intervalFn);
}
private void test(IntervalFunction intervalFn) throws InterruptedException {
Function<String, String> pingPongFn = getRetryablePingPongFn(intervalFn);
ExecutorService executors = newFixedThreadPool(NUM_CONCURRENT_CLIENTS);
List<Callable<String>> tasks = nCopies(NUM_CONCURRENT_CLIENTS, () -> pingPongFn.apply("Hello"));
when(service.call(anyString())).thenThrow(PingPongServiceException.class);
executors.invokeAll(tasks);
}
private Function<String, String> getRetryablePingPongFn(IntervalFunction intervalFn) {
RetryConfig retryConfig = RetryConfig.custom()
.maxAttempts(MAX_RETRIES)
.intervalFunction(intervalFn)
.retryExceptions(PingPongServiceException.class)
.build();
Retry retry = Retry.of("pingpong", retryConfig);
return Retry.decorateFunction(retry, ping -> {
log.info("Invoked at {}", LocalDateTime.now());
return service.call(ping);
});
}
static class RetryProperties {
static final Long INITIAL_INTERVAL = 1000L;
static final Double MULTIPLIER = 2.0D;
static final Double RANDOMIZATION_FACTOR = 0.6D;
static final Integer MAX_RETRIES = 4;
}
}

View File

@ -20,6 +20,7 @@
<module>design-patterns-2</module>
<module>solid</module>
<module>dip</module>
<module>backoff-jitter</module>
</modules>
<dependencyManagement>

View File

@ -0,0 +1 @@
# Relevant Articles

View File

@ -0,0 +1,115 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<artifactId>java-jpa-2</artifactId>
<name>java-jpa-2</name>
<parent>
<artifactId>parent-modules</artifactId>
<groupId>com.baeldung</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<!--Compile time JPA API-->
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>${javax.persistence-api.version}</version>
</dependency>
<!--Runtime JPA implementation-->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>${eclipselink.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>3.3.3</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<outputDirectory>target/metamodel</outputDirectory>
<processors>
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
</processors>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>target/metamodel</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<hibernate.version>5.4.0.Final</hibernate.version>
<eclipselink.version>2.7.4-RC1</eclipselink.version>
<postgres.version>42.2.5</postgres.version>
<javax.persistence-api.version>2.2</javax.persistence-api.version>
</properties>
</project>

View File

@ -0,0 +1,12 @@
package com.baeldung.jpa.entity;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity(name = "MyArticle")
@Table(name = Article.TABLE_NAME)
public class Article {
public static final String TABLE_NAME = "ARTICLES";
}

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [A Guide to Sql2o](http://www.baeldung.com/sql2o)

View File

@ -0,0 +1,54 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<artifactId>java-sql2o</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
<name>java-sql2o</name>
<parent>
<artifactId>persistence-modules</artifactId>
<groupId>com.baeldung</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.sql2o</groupId>
<artifactId>sql2o</artifactId>
<version>${sql2o.version}</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<hsqldb.version>2.4.0</hsqldb.version>
<junit.version>4.12</junit.version>
<sql2o.version>1.6.0</sql2o.version>
</properties>
</project>

View File

@ -0,0 +1,340 @@
package com.baeldung.persistence.sql2o;
import org.junit.Test;
import org.sql2o.Connection;
import org.sql2o.Query;
import org.sql2o.ResultSetIterable;
import org.sql2o.Sql2o;
import org.sql2o.data.Row;
import org.sql2o.data.Table;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import static org.junit.Assert.*;
public class Sql2oIntegrationTest {
@Test
public void whenSql2oCreated_thenSuccess() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
java.sql.Connection jdbcConnection = connection.getJdbcConnection();
assertFalse(jdbcConnection.isClosed());
} catch (SQLException e) {
fail(e.getMessage());
}
}
@Test
public void whenTableCreated_thenInsertIsPossible() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_1 (id integer identity, name varchar(50), url varchar(100))").executeUpdate();
assertEquals(0, connection.getResult());
connection.createQuery("INSERT INTO PROJECT_1 VALUES (1, 'tutorials', 'github.com/eugenp/tutorials')").executeUpdate();
assertEquals(1, connection.getResult());
connection.createQuery("drop table PROJECT_1").executeUpdate();
}
}
@Test
public void whenIdentityColumn_thenInsertReturnsNewId() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_2 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
Query query = connection.createQuery(
"INSERT INTO PROJECT_2 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')",
true);
assertEquals(0, query.executeUpdate().getKey());
query = connection.createQuery("INSERT INTO PROJECT_2 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')",
true);
assertEquals(1, query.executeUpdate().getKeys()[0]);
connection.createQuery("drop table PROJECT_2").executeUpdate();
}
}
@Test
public void whenSelect_thenResultsAreObjects() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_3 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')").executeUpdate();
Query query = connection.createQuery("select * from PROJECT_3 order by id");
List<Project> list = query.executeAndFetch(Project.class);
assertEquals("tutorials", list.get(0).getName());
assertEquals("REST with Spring", list.get(1).getName());
connection.createQuery("drop table PROJECT_3").executeUpdate();
}
}
@Test
public void whenSelectAlias_thenResultsAreObjects() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_4 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100), creation_date date)").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_4 (NAME, URL, creation_date) VALUES ('tutorials', 'github.com/eugenp/tutorials', '2019-01-01')").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_4 (NAME, URL, creation_date) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring', '2019-02-01')").executeUpdate();
Query query = connection.createQuery("select NAME, URL, creation_date as creationDate from PROJECT_4 order by id");
List<Project> list = query.executeAndFetch(Project.class);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
assertEquals("2019-01-01", sdf.format(list.get(0).getCreationDate()));
assertEquals("2019-02-01", sdf.format(list.get(1).getCreationDate()));
connection.createQuery("drop table PROJECT_4").executeUpdate();
}
}
@Test
public void whenSelectMapping_thenResultsAreObjects() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100), creation_date date)").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_5 (NAME, URL, creation_date) VALUES ('tutorials', 'github.com/eugenp/tutorials', '2019-01-01')").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_5 (NAME, URL, creation_date) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring', '2019-02-01')").executeUpdate();
Query query = connection.createQuery("select * from PROJECT_5 order by id")
.addColumnMapping("CrEaTiOn_date", "creationDate");
List<Project> list = query.executeAndFetch(Project.class);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
assertEquals("2019-01-01", sdf.format(list.get(0).getCreationDate()));
assertEquals("2019-02-01", sdf.format(list.get(1).getCreationDate()));
connection.createQuery("drop table PROJECT_5").executeUpdate();
}
}
@Test
public void whenSelectCount_thenResultIsScalar() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_6 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100), creation_date date)").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_6 (NAME, URL, creation_date) VALUES ('tutorials', 'github.com/eugenp/tutorials', '2019-01-01')").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_6 (NAME, URL, creation_date) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring', '2019-02-01')").executeUpdate();
Query query = connection.createQuery("select count(*) from PROJECT_6");
assertEquals(2.0, query.executeScalar(Double.TYPE), 0.001);
connection.createQuery("drop table PROJECT_6").executeUpdate();
}
}
@Test
public void whenFetchTable_thenResultsAreMaps() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100), creation_date date)").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_5 (NAME, URL, creation_date) VALUES ('tutorials', 'github.com/eugenp/tutorials', '2019-01-01')").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_5 (NAME, URL, creation_date) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring', '2019-02-01')").executeUpdate();
Query query = connection.createQuery("select * from PROJECT_5 order by id");
Table table = query.executeAndFetchTable();
List<Map<String, Object>> list = table.asList();
assertEquals("tutorials", list.get(0).get("name"));
assertEquals("REST with Spring", list.get(1).get("name"));
connection.createQuery("drop table PROJECT_5").executeUpdate();
}
}
@Test
public void whenFetchTable_thenResultsAreRows() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100), creation_date date)").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_5 (NAME, URL, creation_date) VALUES ('tutorials', 'github.com/eugenp/tutorials', '2019-01-01')").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_5 (NAME, URL, creation_date) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring', '2019-02-01')").executeUpdate();
Query query = connection.createQuery("select * from PROJECT_5 order by id");
Table table = query.executeAndFetchTable();
List<Row> rows = table.rows();
assertEquals("tutorials", rows.get(0).getString("name"));
assertEquals("REST with Spring", rows.get(1).getString("name"));
connection.createQuery("drop table PROJECT_5").executeUpdate();
}
}
@Test
public void whenParameters_thenReplacement() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_10 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
Query query = connection.createQuery("INSERT INTO PROJECT_10 (NAME, URL) VALUES (:name, :url)")
.addParameter("name", "REST with Spring")
.addParameter("url", "github.com/eugenp/REST-With-Spring");
assertEquals(1, query.executeUpdate().getResult());
List<Project> list = connection.createQuery("SELECT * FROM PROJECT_10 WHERE NAME = 'REST with Spring'").executeAndFetch(Project.class);
assertEquals(1, list.size());
connection.createQuery("drop table PROJECT_10").executeUpdate();
}
}
@Test
public void whenPOJOParameters_thenReplacement() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_11 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
Project project = new Project();
project.setName("REST with Spring");
project.setUrl("github.com/eugenp/REST-With-Spring");
connection.createQuery("INSERT INTO PROJECT_11 (NAME, URL) VALUES (:name, :url)")
.bind(project).executeUpdate();
assertEquals(1, connection.getResult());
List<Project> list = connection.createQuery("SELECT * FROM PROJECT_11 WHERE NAME = 'REST with Spring'").executeAndFetch(Project.class);
assertEquals(1, list.size());
connection.createQuery("drop table PROJECT_11").executeUpdate();
}
}
@Test
public void whenTransactionRollback_thenNoDataInserted() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.beginTransaction()) {
connection.createQuery("create table PROJECT_12 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_12 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_12 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')").executeUpdate();
connection.rollback();
List<Map<String, Object>> list = connection.createQuery("SELECT * FROM PROJECT_12").executeAndFetchTable().asList();
assertEquals(0, list.size());
}
}
@Test
public void whenTransactionEnds_thenSubsequentStatementsNotRolledBack() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.beginTransaction()) {
connection.createQuery("create table PROJECT_13 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_13 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')").executeUpdate();
List<Map<String, Object>> list = connection.createQuery("SELECT * FROM PROJECT_13").executeAndFetchTable().asList();
assertEquals(1, list.size());
connection.rollback();
list = connection.createQuery("SELECT * FROM PROJECT_13").executeAndFetchTable().asList();
assertEquals(0, list.size());
connection.createQuery("INSERT INTO PROJECT_13 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')").executeUpdate();
list = connection.createQuery("SELECT * FROM PROJECT_13").executeAndFetchTable().asList();
assertEquals(1, list.size());
//No implicit rollback
}
try(Connection connection = sql2o.beginTransaction()) {
List<Map<String, Object>> list = connection.createQuery("SELECT * FROM PROJECT_13").executeAndFetchTable().asList();
assertEquals(1, list.size());
}
}
@Test
public void whenTransactionRollbackThenCommit_thenOnlyLastInserted() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.beginTransaction()) {
connection.createQuery("create table PROJECT_14 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_14 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')").executeUpdate();
List<Map<String, Object>> list = connection.createQuery("SELECT * FROM PROJECT_14").executeAndFetchTable().asList();
assertEquals(1, list.size());
connection.rollback(false);
list = connection.createQuery("SELECT * FROM PROJECT_14").executeAndFetchTable().asList();
assertEquals(0, list.size());
connection.createQuery("INSERT INTO PROJECT_14 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')").executeUpdate();
list = connection.createQuery("SELECT * FROM PROJECT_14").executeAndFetchTable().asList();
assertEquals(1, list.size());
//Implicit rollback
}
try(Connection connection = sql2o.beginTransaction()) {
List<Map<String, Object>> list = connection.createQuery("SELECT * FROM PROJECT_14").executeAndFetchTable().asList();
assertEquals(0, list.size());
connection.createQuery("INSERT INTO PROJECT_14 (NAME, URL) VALUES ('tutorials', 'https://github.com/eugenp/tutorials')").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_14 (NAME, URL) VALUES ('REST with Spring', 'https://github.com/eugenp/REST-With-Spring')").executeUpdate();
connection.commit();
list = connection.createQuery("SELECT * FROM PROJECT_14").executeAndFetchTable().asList();
assertEquals(2, list.size());
}
try(Connection connection = sql2o.beginTransaction()) {
List<Map<String, Object>> list = connection.createQuery("SELECT * FROM PROJECT_14").executeAndFetchTable().asList();
assertEquals(2, list.size());
}
}
@Test
public void whenBatch_thenMultipleInserts() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.beginTransaction()) {
connection.createQuery("create table PROJECT_15 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
Query query = connection.createQuery("INSERT INTO PROJECT_15 (NAME, URL) VALUES (:name, :url)");
for(int i = 0; i < 1000; i++) {
query.addParameter("name", "tutorials" + i);
query.addParameter("url", "https://github.com/eugenp/tutorials" + i);
query.addToBatch();
}
query.executeBatch();
connection.commit();
}
try(Connection connection = sql2o.beginTransaction()) {
assertEquals(1000L, connection.createQuery("SELECT count(*) FROM PROJECT_15").executeScalar());
}
}
@Test
public void whenLazyFetch_thenResultsAreObjects() {
Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
try(Connection connection = sql2o.open()) {
connection.createQuery("create table PROJECT_16 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_16 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')").executeUpdate();
connection.createQuery("INSERT INTO PROJECT_16 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')").executeUpdate();
Query query = connection.createQuery("select * from PROJECT_16 order by id");
try(ResultSetIterable<Project> projects = query.executeAndFetchLazy(Project.class)) {
for(Project p : projects) {
assertNotNull(p.getName());
assertNotNull(p.getUrl());
assertNull(p.getCreationDate());
}
}
connection.createQuery("drop table PROJECT_16").executeUpdate();
}
}
static class Project {
private long id;
private String name;
private String url;
private Date creationDate;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
}
}

View File

@ -2,10 +2,6 @@
<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">
<artifactId>jpa-hibernate-cascade-type</artifactId>
<modelVersion>4.0.0</modelVersion>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
@ -13,6 +9,10 @@
<relativePath>../../</relativePath>
</parent>
<artifactId>jpa-hibernate-cascade-type</artifactId>
<modelVersion>4.0.0</modelVersion>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>

View File

@ -29,7 +29,9 @@
<module>java-cockroachdb</module>
<module>java-jdbi</module>
<module>java-jpa</module>
<module>java-jpa-2</module>
<module>java-mongodb</module>
<module>java-sql2o</module>
<module>jnosql</module>
<module>liquibase</module>
<module>orientdb</module>
@ -58,5 +60,6 @@
<module>spring-jpa</module>
<module>spring-persistence-simple</module>
<module>jpa-hibernate-cascade-type</module>
<module>r2dbc</module>
</modules>
</project>

31
persistence-modules/r2dbc/.gitignore vendored Normal file
View File

@ -0,0 +1,31 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/

View File

@ -0,0 +1,114 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.Properties;
public class MavenWrapperDownloader {
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL =
"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: : " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

Binary file not shown.

View File

@ -0,0 +1 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [R2DBC Reactive Relational Database Connectivity](https://www.baeldung.com/r2dbc)

286
persistence-modules/r2dbc/mvnw vendored Normal file
View File

@ -0,0 +1,286 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
# TODO classpath?
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
wget "$jarUrl" -O "$wrapperJarPath"
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
curl -o "$wrapperJarPath" "$jarUrl"
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

161
persistence-modules/r2dbc/mvnw.cmd vendored Normal file
View File

@ -0,0 +1,161 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
echo Found %WRAPPER_JAR%
) else (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
echo Finished downloading %WRAPPER_JAR%
)
@REM End of extension
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

Some files were not shown because too many files have changed in this diff Show More