diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Board.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Board.java new file mode 100644 index 0000000000..ddb5901682 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Board.java @@ -0,0 +1,208 @@ +package com.baeldung.algorithms.play2048; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Board { + private static final Logger LOG = LoggerFactory.getLogger(Board.class); + + private final int[][] board; + + private final int score; + + public Board(int size) { + assert(size > 0); + + this.board = new int[size][]; + this.score = 0; + + for (int x = 0; x < size; ++x) { + this.board[x] = new int[size]; + for (int y = 0; y < size; ++y) { + board[x][y] = 0; + } + } + } + + private Board(int[][] board, int score) { + this.score = score; + this.board = new int[board.length][]; + + for (int x = 0; x < board.length; ++x) { + this.board[x] = Arrays.copyOf(board[x], board[x].length); + } + } + + public int getSize() { + return board.length; + } + + public int getScore() { + return score; + } + + public int getCell(Cell cell) { + int x = cell.getX(); + int y = cell.getY(); + assert(x >= 0 && x < board.length); + assert(y >= 0 && y < board.length); + + return board[x][y]; + } + + public boolean isEmpty(Cell cell) { + return getCell(cell) == 0; + } + + public List emptyCells() { + List result = new ArrayList<>(); + for (int x = 0; x < board.length; ++x) { + for (int y = 0; y < board[x].length; ++y) { + Cell cell = new Cell(x, y); + if (isEmpty(cell)) { + result.add(cell); + } + } + } + return result; + } + + public Board placeTile(Cell cell, int number) { + if (!isEmpty(cell)) { + throw new IllegalArgumentException("That cell is not empty"); + } + + Board result = new Board(this.board, this.score); + result.board[cell.getX()][cell.getY()] = number; + return result; + } + + public Board move(Move move) { + // Clone the board + int[][] tiles = new int[this.board.length][]; + for (int x = 0; x < this.board.length; ++x) { + tiles[x] = Arrays.copyOf(this.board[x], this.board[x].length); + } + + LOG.debug("Before move: {}", Arrays.deepToString(tiles)); + // If we're doing an Left/Right move then transpose the board to make it a Up/Down move + if (move == Move.LEFT || move == Move.RIGHT) { + tiles = transpose(tiles); + LOG.debug("After transpose: {}", Arrays.deepToString(tiles)); + } + // If we're doing a Right/Down move then reverse the board. + // With the above we're now always doing an Up move + if (move == Move.DOWN || move == Move.RIGHT) { + tiles = reverse(tiles); + LOG.debug("After reverse: {}", Arrays.deepToString(tiles)); + } + LOG.debug("Ready to move: {}", Arrays.deepToString(tiles)); + + // Shift everything up + int[][] result = new int[tiles.length][]; + int newScore = 0; + for (int x = 0; x < tiles.length; ++x) { + LinkedList thisRow = new LinkedList<>(); + for (int y = 0; y < tiles[0].length; ++y) { + if (tiles[x][y] > 0) { + thisRow.add(tiles[x][y]); + } + } + + LOG.debug("Unmerged row: {}", thisRow); + LinkedList newRow = new LinkedList<>(); + while (thisRow.size() >= 2) { + int first = thisRow.pop(); + int second = thisRow.peek(); + LOG.debug("Looking at numbers {} and {}", first, second); + if (second == first) { + LOG.debug("Numbers match, combining"); + int newNumber = first * 2; + newRow.add(newNumber); + newScore += newNumber; + thisRow.pop(); + } else { + LOG.debug("Numbers don't match"); + newRow.add(first); + } + } + newRow.addAll(thisRow); + LOG.debug("Merged row: {}", newRow); + + result[x] = new int[tiles[0].length]; + for (int y = 0; y < tiles[0].length; ++y) { + if (newRow.isEmpty()) { + result[x][y] = 0; + } else { + result[x][y] = newRow.pop(); + } + } + } + LOG.debug("After moves: {}", Arrays.deepToString(result)); + + // Un-reverse the board + if (move == Move.DOWN || move == Move.RIGHT) { + result = reverse(result); + LOG.debug("After reverse: {}", Arrays.deepToString(result)); + } + // Un-transpose the board + if (move == Move.LEFT || move == Move.RIGHT) { + result = transpose(result); + LOG.debug("After transpose: {}", Arrays.deepToString(result)); + } + return new Board(result, this.score + newScore); + } + + private static int[][] transpose(int[][] input) { + int[][] result = new int[input.length][]; + + for (int x = 0; x < input.length; ++x) { + result[x] = new int[input[0].length]; + for (int y = 0; y < input[0].length; ++y) { + result[x][y] = input[y][x]; + } + } + + return result; + } + + private static int[][] reverse(int[][] input) { + int[][] result = new int[input.length][]; + + for (int x = 0; x < input.length; ++x) { + result[x] = new int[input[0].length]; + for (int y = 0; y < input[0].length; ++y) { + result[x][y] = input[x][input.length - y - 1]; + } + } + + return result; + } + + @Override + public String toString() { + return Arrays.deepToString(board); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Board board1 = (Board) o; + return Arrays.deepEquals(board, board1.board); + } + + @Override + public int hashCode() { + return Arrays.deepHashCode(board); + } +} diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Cell.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Cell.java new file mode 100644 index 0000000000..98ee23ac90 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Cell.java @@ -0,0 +1,26 @@ +package com.baeldung.algorithms.play2048; + +import java.util.StringJoiner; + +public class Cell { + private int x; + private int y; + + public Cell(int x, int y) { + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + @Override + public String toString() { + return new StringJoiner(", ", Cell.class.getSimpleName() + "[", "]").add("x=" + x).add("y=" + y).toString(); + } +} diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Computer.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Computer.java new file mode 100644 index 0000000000..5ef1d04368 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Computer.java @@ -0,0 +1,27 @@ +package com.baeldung.algorithms.play2048; + +import java.security.SecureRandom; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Computer { + private static final Logger LOG = LoggerFactory.getLogger(Computer.class); + + private final SecureRandom rng = new SecureRandom(); + + public Board makeMove(Board input) { + List emptyCells = input.emptyCells(); + LOG.info("Number of empty cells: {}", emptyCells.size()); + + double numberToPlace = rng.nextDouble(); + LOG.info("New number probability: {}", numberToPlace); + + int indexToPlace = rng.nextInt(emptyCells.size()); + Cell cellToPlace = emptyCells.get(indexToPlace); + LOG.info("Placing number into empty cell: {}", cellToPlace); + + return input.placeTile(cellToPlace, numberToPlace >= 0.9 ? 4 : 2); + } +} diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Human.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Human.java new file mode 100644 index 0000000000..d1b32f0309 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Human.java @@ -0,0 +1,126 @@ +package com.baeldung.algorithms.play2048; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.math3.util.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Human { + private static final Logger LOG = LoggerFactory.getLogger(Human.class); + + public Board makeMove(Board input) { + // For each move in MOVE + // Generate board from move + // Generate Score for Board + // Return board with the best score + // + // Generate Score + // If Depth Limit + // Return Final Score + // Total Score = 0 + // For every empty square in new board + // Generate board with "2" in square + // Calculate Score + // Total Score += (Score * 0.9) + // Generate board with "4" in square + // Calculate Score + // Total Score += (Score * 0.1) + // + // Calculate Score + // For each move in MOVE + // Generate board from move + // Generate score for board + // Return the best generated score + + return Arrays.stream(Move.values()) + .parallel() + .map(input::move) + .filter(board -> !board.equals(input)) + .max(Comparator.comparingInt(board -> generateScore(board, 0))) + .orElse(input); + } + + private int generateScore(Board board, int depth) { + if (depth >= 3) { + int finalScore = calculateFinalScore(board); + LOG.debug("Final score for board {}: {}", board,finalScore); + return finalScore; + } + + return board.emptyCells().stream() + .parallel() + .flatMap(cell -> Stream.of(new Pair<>(cell, 2), new Pair<>(cell, 4))) + .mapToInt(move -> { + LOG.debug("Simulating move {} at depth {}", move, depth); + Board newBoard = board.placeTile(move.getFirst(), move.getSecond()); + int boardScore = calculateScore(newBoard, depth + 1); + int calculatedScore = (int) (boardScore * (move.getSecond() == 2 ? 0.9 : 0.1)); + LOG.debug("Calculated score for board {} and move {} at depth {}: {}", newBoard, move, depth, calculatedScore); + return calculatedScore; + }) + .sum(); + } + + private int calculateScore(Board board, int depth) { + return Arrays.stream(Move.values()) + .parallel() + .map(board::move) + .filter(moved -> !moved.equals(board)) + .mapToInt(newBoard -> generateScore(newBoard, depth)) + .max() + .orElse(0); + } + + private int calculateFinalScore(Board board) { + List> rowsToScore = new ArrayList<>(); + for (int i = 0; i < board.getSize(); ++i) { + List row = new ArrayList<>(); + List col = new ArrayList<>(); + + for (int j = 0; j < board.getSize(); ++j) { + row.add(board.getCell(new Cell(i, j))); + col.add(board.getCell(new Cell(j, i))); + } + + rowsToScore.add(row); + rowsToScore.add(col); + } + + return rowsToScore.stream() + .parallel() + .mapToInt(row -> { + List preMerged = row.stream() + .filter(value -> value != 0) + .collect(Collectors.toList()); + + int numMerges = 0; + int monotonicityLeft = 0; + int monotonicityRight = 0; + for (int i = 0; i < preMerged.size() - 1; ++i) { + Integer first = preMerged.get(i); + Integer second = preMerged.get(i + 1); + if (first.equals(second)) { + ++numMerges; + } else if (first > second) { + monotonicityLeft += first - second; + } else { + monotonicityRight += second - first; + } + } + + int score = 1000; + score += 250 * row.stream().filter(value -> value == 0).count(); + score += 750 * numMerges; + score -= 10 * row.stream().mapToInt(value -> value).sum(); + score -= 50 * Math.min(monotonicityLeft, monotonicityRight); + return score; + }) + .sum(); + } +} diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Move.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Move.java new file mode 100644 index 0000000000..8678cec833 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Move.java @@ -0,0 +1,8 @@ +package com.baeldung.algorithms.play2048; + +public enum Move { + UP, + DOWN, + LEFT, + RIGHT +} diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Play2048.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Play2048.java new file mode 100644 index 0000000000..ec5b3dca40 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/play2048/Play2048.java @@ -0,0 +1,73 @@ +package com.baeldung.algorithms.play2048; + +public class Play2048 { + private static final int SIZE = 3; + private static final int INITIAL_NUMBERS = 2; + + public static void main(String[] args) { + // The board and players + Board board = new Board(SIZE); + Computer computer = new Computer(); + Human human = new Human(); + + // The computer has two moves first + System.out.println("Setup"); + System.out.println("====="); + for (int i = 0; i < INITIAL_NUMBERS; ++i) { + board = computer.makeMove(board); + } + + printBoard(board); + do { + board = human.makeMove(board); + System.out.println("Human move"); + System.out.println("=========="); + printBoard(board); + + board = computer.makeMove(board); + System.out.println("Computer move"); + System.out.println("============="); + printBoard(board); + } while (!board.emptyCells().isEmpty()); + + System.out.println("Final Score: " + board.getScore()); + + } + + private static void printBoard(Board board) { + StringBuilder topLines = new StringBuilder(); + StringBuilder midLines = new StringBuilder(); + for (int x = 0; x < board.getSize(); ++x) { + topLines.append("+--------"); + midLines.append("| "); + } + topLines.append("+"); + midLines.append("|"); + + + for (int y = 0; y < board.getSize(); ++y) { + System.out.println(topLines); + System.out.println(midLines); + for (int x = 0; x < board.getSize(); ++x) { + Cell cell = new Cell(x, y); + System.out.print("|"); + if (board.isEmpty(cell)) { + System.out.print(" "); + } else { + StringBuilder output = new StringBuilder(Integer.toString(board.getCell(cell))); + while (output.length() < 8) { + output.append(" "); + if (output.length() < 8) { + output.insert(0, " "); + } + } + System.out.print(output); + } + } + System.out.println("|"); + System.out.println(midLines); + } + System.out.println(topLines); + System.out.println("Score: " + board.getScore()); + } +} diff --git a/algorithms-sorting-2/src/main/java/com/baeldung/algorithms/quicksort/DutchNationalFlagPartioning.java b/algorithms-sorting-2/src/main/java/com/baeldung/algorithms/quicksort/DutchNationalFlagPartioning.java index e868cf0e2e..0fc09c0b3d 100644 --- a/algorithms-sorting-2/src/main/java/com/baeldung/algorithms/quicksort/DutchNationalFlagPartioning.java +++ b/algorithms-sorting-2/src/main/java/com/baeldung/algorithms/quicksort/DutchNationalFlagPartioning.java @@ -5,21 +5,21 @@ import static com.baeldung.algorithms.quicksort.SortingUtils.swap; public class DutchNationalFlagPartioning { - public static Partition partition(int[] a, int begin, int end) { + public static Partition partition(int[] input, int begin, int end) { int lt = begin, current = begin, gt = end; - int partitioningValue = a[begin]; + int partitioningValue = input[begin]; while (current <= gt) { - int compareCurrent = compare(a[current], partitioningValue); + int compareCurrent = compare(input[current], partitioningValue); switch (compareCurrent) { case -1: - swap(a, current++, lt++); + swap(input, current++, lt++); break; case 0: current++; break; case 1: - swap(a, current, gt--); + swap(input, current, gt--); break; } } diff --git a/core-groovy-2/src/main/groovy/com/baeldung/determinedatatype/Person.groovy b/core-groovy-2/src/main/groovy/com/baeldung/determinedatatype/Person.groovy new file mode 100644 index 0000000000..3ac88b7952 --- /dev/null +++ b/core-groovy-2/src/main/groovy/com/baeldung/determinedatatype/Person.groovy @@ -0,0 +1,14 @@ +package com.baeldung.determinedatatype + +class Person { + + private int ageAsInt + private Double ageAsDouble + private String ageAsString + + Person() {} + Person(int ageAsInt) { this.ageAsInt = ageAsInt} + Person(Double ageAsDouble) { this.ageAsDouble = ageAsDouble} + Person(String ageAsString) { this.ageAsString = ageAsString} +} +class Student extends Person {} diff --git a/core-groovy-2/src/test/groovy/com/baeldung/determinedatatype/PersonTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/determinedatatype/PersonTest.groovy new file mode 100644 index 0000000000..4c6589f207 --- /dev/null +++ b/core-groovy-2/src/test/groovy/com/baeldung/determinedatatype/PersonTest.groovy @@ -0,0 +1,56 @@ +package com.baeldung.determinedatatype + +import org.junit.Assert +import org.junit.Test +import com.baeldung.determinedatatype.Person + +public class PersonTest { + + @Test + public void givenWhenParameterTypeIsInteger_thenReturnTrue() { + Person personObj = new Person(10) + Assert.assertTrue(personObj.ageAsInt instanceof Integer) + } + + @Test + public void givenWhenParameterTypeIsDouble_thenReturnTrue() { + Person personObj = new Person(10.0) + Assert.assertTrue((personObj.ageAsDouble).getClass() == Double) + } + + @Test + public void givenWhenParameterTypeIsString_thenReturnTrue() { + Person personObj = new Person("10 years") + Assert.assertTrue(personObj.ageAsString.class == String) + } + + @Test + public void givenClassName_WhenParameterIsInteger_thenReturnTrue() { + Assert.assertTrue(Person.class.getDeclaredField('ageAsInt').type == int.class) + } + + @Test + public void givenWhenObjectIsInstanceOfType_thenReturnTrue() { + Person personObj = new Person() + Assert.assertTrue(personObj instanceof Person) + } + + @Test + public void givenWhenInstanceIsOfSubtype_thenReturnTrue() { + Student studentObj = new Student() + Assert.assertTrue(studentObj in Person) + } + + @Test + public void givenGroovyList_WhenFindClassName_thenReturnTrue() { + def ageList = ['ageAsString','ageAsDouble', 10] + Assert.assertTrue(ageList.class == ArrayList) + Assert.assertTrue(ageList.getClass() == ArrayList) + } + + @Test + public void givenGrooyMap_WhenFindClassName_thenReturnTrue() { + def ageMap = [ageAsString: '10 years', ageAsDouble: 10.0] + Assert.assertFalse(ageMap.class == LinkedHashMap) + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-14/README.md b/core-java-modules/core-java-14/README.md index dc80800054..d382c4814a 100644 --- a/core-java-modules/core-java-14/README.md +++ b/core-java-modules/core-java-14/README.md @@ -9,3 +9,4 @@ This module contains articles about Java 14. - [Pattern Matching for instanceof in Java 14](https://www.baeldung.com/java-pattern-matching-instanceof) - [Helpful NullPointerExceptions in Java 14](https://www.baeldung.com/java-14-nullpointerexception) - [Foreign Memory Access API in Java 14](https://www.baeldung.com/java-foreign-memory-access) +- [Java 14 Record Keyword](https://www.baeldung.com/java-record-keyword) diff --git a/core-java-modules/core-java-9-improvements/README.md b/core-java-modules/core-java-9-improvements/README.md index 3b0bdcd651..db989d10ab 100644 --- a/core-java-modules/core-java-9-improvements/README.md +++ b/core-java-modules/core-java-9-improvements/README.md @@ -5,7 +5,7 @@ This module contains articles about the improvements to core Java features intro ### Relevant Articles: - [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors) -- [Java 9 Convenience Factory Methods for Collections](https://www.baeldung.com/java-9-collections-factory-methods) +- [Java Convenience Factory Methods for Collections](https://www.baeldung.com/java-9-collections-factory-methods) - [Java 9 Stream API Improvements](https://www.baeldung.com/java-9-stream-api) - [Java 9 java.util.Objects Additions](https://www.baeldung.com/java-9-objects-new) - [Java 9 CompletableFuture API Improvements](https://www.baeldung.com/java-9-completablefuture) diff --git a/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/arrays/JavaArraysToStringUnitTest.java b/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/arrays/JavaArraysToStringUnitTest.java new file mode 100644 index 0000000000..064803465d --- /dev/null +++ b/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/arrays/JavaArraysToStringUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.arrays; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class JavaArraysToStringUnitTest { + + @Test + public void givenInstanceOfArray_whenTryingToConvertToString_thenNameOfClassIsShown() { + Object[] arrayOfObjects = { "John", 2, true }; + assertTrue(arrayOfObjects.toString().startsWith("[Ljava.lang.Object;")); + } + + @Test + public void givenInstanceOfArray_whenUsingArraysToStringToConvert_thenValueOfObjectsAreShown() { + Object[] arrayOfObjects = { "John", 2, true }; + assertEquals(Arrays.toString(arrayOfObjects), "[John, 2, true]"); + } + + @Test + public void givenInstanceOfDeepArray_whenUsingArraysDeepToStringToConvert_thenValueOfInnerObjectsAreShown() { + Object[] innerArray = { "We", "Are", "Inside" }; + Object[] arrayOfObjects = { "John", 2, innerArray }; + assertEquals(Arrays.deepToString(arrayOfObjects), "[John, 2, [We, Are, Inside]]"); + } + + @Test + public void givenInstanceOfDeepArray_whenUsingStreamsToConvert_thenValueOfObjectsAreShown() { + Object[] arrayOfObjects = { "John", 2, true }; + List listOfString = Stream.of(arrayOfObjects) + .map(Object::toString) + .collect(Collectors.toList()); + assertEquals(listOfString.toString(), "[John, 2, true]"); + } +} diff --git a/core-java-modules/core-java-concurrency-advanced-3/README.md b/core-java-modules/core-java-concurrency-advanced-3/README.md index e33b6ab692..ca29e5ca85 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/README.md +++ b/core-java-modules/core-java-concurrency-advanced-3/README.md @@ -13,4 +13,5 @@ This module contains articles about advanced topics about multithreading with co - [Java Thread Deadlock and Livelock](https://www.baeldung.com/java-deadlock-livelock) - [Guide to AtomicStampedReference in Java](https://www.baeldung.com/java-atomicstampedreference) - [The ABA Problem in Concurrency](https://www.baeldung.com/cs/aba-concurrency) +- [Introduction to Lock-Free Data Structures](https://www.baeldung.com/lock-free-programming) - [[<-- previous]](/core-java-modules/core-java-concurrency-advanced-2) diff --git a/core-java-modules/core-java-concurrency-collections/README.md b/core-java-modules/core-java-concurrency-collections/README.md index 80a21ee533..af6e7a8b59 100644 --- a/core-java-modules/core-java-concurrency-collections/README.md +++ b/core-java-modules/core-java-concurrency-collections/README.md @@ -13,3 +13,4 @@ This module contains articles about concurrent Java collections - [Guide to the Java TransferQueue](http://www.baeldung.com/java-transfer-queue) - [Guide to the ConcurrentSkipListMap](http://www.baeldung.com/java-concurrent-skip-list-map) - [Guide to CopyOnWriteArrayList](http://www.baeldung.com/java-copy-on-write-arraylist) +- [LinkedBlockingQueue vs ConcurrentLinkedQueue](https://www.baeldung.com/java-queue-linkedblocking-concurrentlinked) diff --git a/core-java-modules/core-java-exceptions-2/src/test/java/com/baeldung/exceptions/TooManyOpenFilesExceptionLiveTest.java b/core-java-modules/core-java-exceptions-2/src/test/java/com/baeldung/exceptions/TooManyOpenFilesExceptionLiveTest.java new file mode 100644 index 0000000000..9373563df7 --- /dev/null +++ b/core-java-modules/core-java-exceptions-2/src/test/java/com/baeldung/exceptions/TooManyOpenFilesExceptionLiveTest.java @@ -0,0 +1,82 @@ +package com.baeldung.exceptions; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; + + +public class TooManyOpenFilesExceptionLiveTest { + + private File tempFile; + + @BeforeEach + public void setUp() throws IOException { + tempFile = File.createTempFile("testForException", "tmp"); + } + + @AfterEach + public void tearDown() { + System.gc(); + tempFile.delete(); + } + + @Test + public void whenNotClosingResoures_thenIOExceptionShouldBeThrown() { + try { + for (int x = 0; x < 1000000; x++) { + FileInputStream leakyHandle = new FileInputStream(tempFile); + } + Assertions.fail("Method Should Have Failed"); + } catch (IOException e) { + assertTrue(e.getMessage().toLowerCase().contains("too many open files")); + } catch (Exception e) { + Assertions.fail("Unexpected exception"); + } + } + + @Test + public void whenClosingResoures_thenIOExceptionShouldNotBeThrown() { + try { + for (int x = 0; x < 1000000; x++) { + FileInputStream nonLeakyHandle = null; + try { + nonLeakyHandle = new FileInputStream(tempFile); + } finally { + if (nonLeakyHandle != null) { + nonLeakyHandle.close(); + } + } + } + } catch (IOException e) { + assertFalse(e.getMessage().toLowerCase().contains("too many open files")); + Assertions.fail("Method Should Not Have Failed"); + } catch (Exception e) { + Assertions.fail("Unexpected exception"); + } + } + + @Test + public void whenUsingTryWithResoures_thenIOExceptionShouldNotBeThrown() { + try { + for (int x = 0; x < 1000000; x++) { + try (FileInputStream nonLeakyHandle = new FileInputStream(tempFile)) { + //Do something with the file + } + } + } catch (IOException e) { + assertFalse(e.getMessage().toLowerCase().contains("too many open files")); + Assertions.fail("Method Should Not Have Failed"); + } catch (Exception e) { + Assertions.fail("Unexpected exception"); + } + } +} diff --git a/core-java-modules/core-java-jvm/pom.xml b/core-java-modules/core-java-jvm/pom.xml index f3e5470a61..08e536998c 100644 --- a/core-java-modules/core-java-jvm/pom.xml +++ b/core-java-modules/core-java-jvm/pom.xml @@ -51,14 +51,37 @@ system ${java.home}/../lib/tools.jar + + org.ow2.asm + asm + ${asm.version} + + + org.ow2.asm + asm-util + ${asm.version} + + + org.apache.bcel + bcel + ${bcel.version} + + + org.openjdk.jol + jol-core + ${jol-core.version} + 3.6.1 - 3.21.0-GA + 3.27.0-GA 2.1.0.1 1.8.0 + 0.10 + 8.0.1 + 6.5.0 diff --git a/core-java-modules/core-java-jvm/src/test/java/com/baeldung/boolsize/BooleanSizeUnitTest.java b/core-java-modules/core-java-jvm/src/test/java/com/baeldung/boolsize/BooleanSizeUnitTest.java new file mode 100644 index 0000000000..19c7055438 --- /dev/null +++ b/core-java-modules/core-java-jvm/src/test/java/com/baeldung/boolsize/BooleanSizeUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.boolsize; + +import org.junit.Test; +import org.openjdk.jol.info.ClassLayout; +import org.openjdk.jol.vm.VM; + +public class BooleanSizeUnitTest { + + @Test + public void printingTheVMDetails() { + System.out.println(VM.current().details()); + } + + @Test + public void printingTheBoolWrapper() { + System.out.println(ClassLayout.parseClass(BooleanWrapper.class).toPrintable()); + } + + @Test + public void printingTheBoolArray() { + boolean[] value = new boolean[3]; + + System.out.println(ClassLayout.parseInstance(value).toPrintable()); + } +} diff --git a/core-java-modules/core-java-jvm/src/test/java/com/baeldung/boolsize/BooleanWrapper.java b/core-java-modules/core-java-jvm/src/test/java/com/baeldung/boolsize/BooleanWrapper.java new file mode 100644 index 0000000000..1ad164adbc --- /dev/null +++ b/core-java-modules/core-java-jvm/src/test/java/com/baeldung/boolsize/BooleanWrapper.java @@ -0,0 +1,5 @@ +package com.baeldung.boolsize; + +class BooleanWrapper { + private boolean value; +} diff --git a/core-java-modules/core-java-jvm/src/test/java/com/baeldung/bytecode/ViewBytecodeUnitTest.java b/core-java-modules/core-java-jvm/src/test/java/com/baeldung/bytecode/ViewBytecodeUnitTest.java new file mode 100644 index 0000000000..5b0fdf26d4 --- /dev/null +++ b/core-java-modules/core-java-jvm/src/test/java/com/baeldung/bytecode/ViewBytecodeUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.bytecode; + +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.bcel.Repository; +import org.apache.bcel.classfile.JavaClass; +import org.junit.Test; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.util.TraceClassVisitor; +import javassist.ClassPool; +import javassist.NotFoundException; +import javassist.bytecode.ClassFile; + +public class ViewBytecodeUnitTest { + + @Test + public void whenUsingASM_thenReadBytecode() throws IOException { + ClassReader reader = new ClassReader("java.lang.Object"); + StringWriter sw = new StringWriter(); + TraceClassVisitor tcv = new TraceClassVisitor(new PrintWriter(sw)); + reader.accept(tcv, 0); + + assertTrue(sw.toString().contains("public class java/lang/Object")); + } + + @Test + public void whenUsingBCEL_thenReadBytecode() throws ClassNotFoundException { + JavaClass objectClazz = Repository.lookupClass("java.lang.Object"); + + assertEquals(objectClazz.getClassName(), "java.lang.Object"); + assertEquals(objectClazz.getMethods().length, 14); + assertTrue(objectClazz.toString().contains("public class java.lang.Object")); + } + + @Test + public void whenUsingJavassist_thenReadBytecode() throws NotFoundException { + ClassPool cp = ClassPool.getDefault(); + ClassFile cf = cp.get("java.lang.Object").getClassFile(); + + assertEquals(cf.getName(), "java.lang.Object"); + assertEquals(cf.getMethods().size(), 14); + } + +} + + diff --git a/core-java-modules/core-java-lang-math/README.md b/core-java-modules/core-java-lang-math/README.md index 9295349f82..af63780dbb 100644 --- a/core-java-modules/core-java-lang-math/README.md +++ b/core-java-modules/core-java-lang-math/README.md @@ -6,7 +6,6 @@ - [Java 8 Math New Methods](https://www.baeldung.com/java-8-math) - [Java 8 Unsigned Arithmetic Support](https://www.baeldung.com/java-unsigned-arithmetic) - [How to Separate Double into Integer and Decimal Parts](https://www.baeldung.com/java-separate-double-into-integer-decimal-parts) -- [The strictfp Keyword in Java](https://www.baeldung.com/java-strictfp) - [Basic Calculator in Java](https://www.baeldung.com/java-basic-calculator) - [Overflow and Underflow in Java](https://www.baeldung.com/java-overflow-underflow) - [Obtaining a Power Set of a Set in Java](https://www.baeldung.com/java-power-set-of-a-set) diff --git a/core-java-modules/core-java-lang-oop-types/README.md b/core-java-modules/core-java-lang-oop-types/README.md index 80344c70fa..449a0f59cc 100644 --- a/core-java-modules/core-java-lang-oop-types/README.md +++ b/core-java-modules/core-java-lang-oop-types/README.md @@ -7,3 +7,6 @@ This module contains articles about types in Java - [Guide to the this Java Keyword](https://www.baeldung.com/java-this) - [Nested Classes in Java](https://www.baeldung.com/java-nested-classes) - [Marker Interfaces in Java](https://www.baeldung.com/java-marker-interfaces) +- [Iterating Over Enum Values in Java](https://www.baeldung.com/java-enum-iteration) +- [Attaching Values to Java Enum](https://www.baeldung.com/java-enum-values) +- [A Guide to Java Enums](https://www.baeldung.com/a-guide-to-java-enums) diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/Pizza.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/Pizza.java similarity index 100% rename from core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/Pizza.java rename to core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/Pizza.java diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java similarity index 100% rename from core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java rename to core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/PizzaDeliveryStrategy.java diff --git a/core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java similarity index 100% rename from core-java-modules/core-java-lang-syntax/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java rename to core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/PizzaDeliverySystemConfiguration.java diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/values/Element1.java similarity index 100% rename from core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java rename to core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/values/Element1.java diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/values/Element2.java similarity index 100% rename from core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java rename to core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/values/Element2.java diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/values/Element3.java similarity index 100% rename from core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java rename to core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/values/Element3.java diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/values/Element4.java similarity index 100% rename from core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java rename to core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/values/Element4.java diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/values/Labeled.java similarity index 100% rename from core-java-modules/core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java rename to core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/values/Labeled.java diff --git a/core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/enums/PizzaUnitTest.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/PizzaUnitTest.java similarity index 100% rename from core-java-modules/core-java-lang-syntax/src/test/java/com/baeldung/enums/PizzaUnitTest.java rename to core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/PizzaUnitTest.java diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/iteration/DaysOfWeekEnum.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/iteration/DaysOfWeekEnum.java similarity index 100% rename from core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/iteration/DaysOfWeekEnum.java rename to core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/iteration/DaysOfWeekEnum.java diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/iteration/EnumIterationExamples.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/iteration/EnumIterationExamples.java similarity index 100% rename from core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/iteration/EnumIterationExamples.java rename to core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/iteration/EnumIterationExamples.java diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/values/Element1UnitTest.java similarity index 100% rename from core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java rename to core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/values/Element1UnitTest.java diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/values/Element2UnitTest.java similarity index 100% rename from core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java rename to core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/values/Element2UnitTest.java diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/values/Element3UnitTest.java similarity index 100% rename from core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java rename to core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/values/Element3UnitTest.java diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/values/Element4UnitTest.java similarity index 100% rename from core-java-modules/core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java rename to core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/values/Element4UnitTest.java diff --git a/core-java-modules/core-java-lang-operators/README.md b/core-java-modules/core-java-lang-operators/README.md index facbf40fc6..3e2afd1489 100644 --- a/core-java-modules/core-java-lang-operators/README.md +++ b/core-java-modules/core-java-lang-operators/README.md @@ -12,3 +12,4 @@ This module contains articles about Java operators - [The XOR Operator in Java](https://www.baeldung.com/java-xor-operator) - [Java Bitwise Operators](https://www.baeldung.com/java-bitwise-operators) - [Bitwise & vs Logical && Operators](https://www.baeldung.com/java-bitwise-vs-logical-and) +- [Finding an Object’s Class in Java](https://www.baeldung.com/java-finding-class) diff --git a/core-java-modules/core-java-lang/README.md b/core-java-modules/core-java-lang/README.md index 9e98bb849b..9166b93b7f 100644 --- a/core-java-modules/core-java-lang/README.md +++ b/core-java-modules/core-java-lang/README.md @@ -4,7 +4,6 @@ This module contains articles about core features in the Java language ### Relevant Articles: - [Generate equals() and hashCode() with Eclipse](https://www.baeldung.com/java-eclipse-equals-and-hashcode) -- [Iterating Over Enum Values in Java](https://www.baeldung.com/java-enum-iteration) - [Comparator and Comparable in Java](https://www.baeldung.com/java-comparator-comparable) - [Recursion In Java](https://www.baeldung.com/java-recursion) - [A Guide to the finalize Method in Java](https://www.baeldung.com/java-finalize) @@ -12,8 +11,6 @@ This module contains articles about core features in the Java language - [Using Java Assertions](https://www.baeldung.com/java-assert) - [Synthetic Constructs in Java](https://www.baeldung.com/java-synthetic) - [Retrieving a Class Name in Java](https://www.baeldung.com/java-class-name) -- [Attaching Values to Java Enum](https://www.baeldung.com/java-enum-values) - [The Java continue and break Keywords](https://www.baeldung.com/java-continue-and-break) -- [A Guide to Java Enums](https://www.baeldung.com/a-guide-to-java-enums) - [Infinite Loops in Java](https://www.baeldung.com/infinite-loops-java) - [[More --> ]](/core-java-modules/core-java-lang-2) diff --git a/core-java-modules/core-java-string-conversions/src/test/java/com/baeldung/stringtoint/StringToIntOrIntegerUnitTest.java b/core-java-modules/core-java-string-conversions/src/test/java/com/baeldung/stringtoint/StringToIntOrIntegerUnitTest.java index 336b2ac324..278d69d4ac 100644 --- a/core-java-modules/core-java-string-conversions/src/test/java/com/baeldung/stringtoint/StringToIntOrIntegerUnitTest.java +++ b/core-java-modules/core-java-string-conversions/src/test/java/com/baeldung/stringtoint/StringToIntOrIntegerUnitTest.java @@ -17,6 +17,15 @@ public class StringToIntOrIntegerUnitTest { assertThat(result).isEqualTo(42); } + @Test + public void givenBinaryString_whenParsingInt_shouldConvertToInt() { + String givenString = "101010"; + + int result = Integer.parseInt(givenString, 2); + + assertThat(result).isEqualTo(42); + } + @Test public void givenString_whenCallingIntegerValueOf_shouldConvertToInt() { String givenString = "42"; @@ -27,6 +36,15 @@ public class StringToIntOrIntegerUnitTest { } @Test + public void givenBinaryString_whenCallingIntegerValueOf_shouldConvertToInt() { + String givenString = "101010"; + + Integer result = Integer.valueOf(givenString, 2); + + assertThat(result).isEqualTo(new Integer(42)); + } + + @Test public void givenString_whenCallingValueOf_shouldCacheSomeValues() { for (int i = -128; i <= 127; i++) { String value = i + ""; diff --git a/core-kotlin-modules/core-kotlin-lang-2/README.md b/core-kotlin-modules/core-kotlin-lang-2/README.md index 7576ddb210..e6dad87ee4 100644 --- a/core-kotlin-modules/core-kotlin-lang-2/README.md +++ b/core-kotlin-modules/core-kotlin-lang-2/README.md @@ -12,4 +12,5 @@ This module contains articles about core features in the Kotlin language. - [Comprehensive Guide to Null Safety in Kotlin](https://www.baeldung.com/kotlin-null-safety) - [Kotlin Scope Functions](https://www.baeldung.com/kotlin-scope-functions) - [If-Else Expression in Kotlin](https://www.baeldung.com/kotlin/if-else-expression) +- [Checking Whether a lateinit var Is Initialized in Kotlin](https://www.baeldung.com/kotlin/checking-lateinit) - [[<-- Prev]](/core-kotlin-modules/core-kotlin-lang) \ No newline at end of file diff --git a/drools/README.MD b/drools/README.MD index bcec0cc2f0..414ad2dea3 100644 --- a/drools/README.MD +++ b/drools/README.MD @@ -5,5 +5,4 @@ This module contains articles about Drools ### Relevant Articles: - [Introduction to Drools](https://www.baeldung.com/drools) -- [Drools Using Rules from Excel Files](https://www.baeldung.com/drools-excel) - [An Example of Backward Chaining in Drools](https://www.baeldung.com/drools-backward-chaining) diff --git a/guava-collections-map/pom.xml b/guava-collections-map/pom.xml index ee8ceb10f3..06537d26bd 100644 --- a/guava-collections-map/pom.xml +++ b/guava-collections-map/pom.xml @@ -16,12 +16,39 @@ guava-collections-map + src/main/resources true + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + test + + + + + 5.6.2 + \ No newline at end of file diff --git a/guava-collections-set/pom.xml b/guava-collections-set/pom.xml index 8bb0b924f9..49d96965a7 100644 --- a/guava-collections-set/pom.xml +++ b/guava-collections-set/pom.xml @@ -13,8 +13,32 @@ ../parent-java + + guava-collections-set + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + test + org.assertj assertj-core @@ -23,13 +47,10 @@ - - guava-collections-set - - 3.6.1 + 5.6.2 diff --git a/guava-collections/pom.xml b/guava-collections/pom.xml index c6019362c5..744eba1a38 100644 --- a/guava-collections/pom.xml +++ b/guava-collections/pom.xml @@ -15,6 +15,25 @@ ../parent-java + + guava-collections + + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + @@ -27,7 +46,20 @@ commons-lang3 ${commons-lang3.version} + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + test + org.assertj assertj-core @@ -44,16 +76,6 @@ - - guava-collections - - - src/main/resources - true - - - - 4.1 @@ -61,6 +83,7 @@ 3.6.1 2.0.0.0 + 5.6.2 \ No newline at end of file diff --git a/guava-io/pom.xml b/guava-io/pom.xml index 7517d442b0..fd637f2474 100644 --- a/guava-io/pom.xml +++ b/guava-io/pom.xml @@ -4,6 +4,9 @@ 4.0.0 guava-io 0.1.0-SNAPSHOT + + 5.6.2 + guava-io @@ -15,12 +18,35 @@ guava-io + src/main/resources true + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + test + + \ No newline at end of file diff --git a/guava-io/src/main/test/java/com/baeldung/guava/GuavaCountingOutputStreamUnitTest.java b/guava-io/src/test/java/com/baeldung/guava/GuavaCountingOutputStreamUnitTest.java similarity index 100% rename from guava-io/src/main/test/java/com/baeldung/guava/GuavaCountingOutputStreamUnitTest.java rename to guava-io/src/test/java/com/baeldung/guava/GuavaCountingOutputStreamUnitTest.java diff --git a/guava-io/src/main/test/java/com/baeldung/guava/GuavaIOUnitTest.java b/guava-io/src/test/java/com/baeldung/guava/GuavaIOUnitTest.java similarity index 93% rename from guava-io/src/main/test/java/com/baeldung/guava/GuavaIOUnitTest.java rename to guava-io/src/test/java/com/baeldung/guava/GuavaIOUnitTest.java index 7d7b0ea04d..4d7c688f58 100644 --- a/guava-io/src/main/test/java/com/baeldung/guava/GuavaIOUnitTest.java +++ b/guava-io/src/test/java/com/baeldung/guava/GuavaIOUnitTest.java @@ -11,8 +11,11 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; +import org.junit.After; import org.junit.Test; import com.google.common.base.Charsets; @@ -31,6 +34,21 @@ import com.google.common.io.Resources; public class GuavaIOUnitTest { + @After + public void afterEach() throws Exception { + deleteProducedFiles(); + } + + private void deleteProducedFiles() throws IOException { + deleteIfExists("test.out"); + deleteIfExists("test_copy.in"); + deleteIfExists("test_le.txt"); + } + + private void deleteIfExists(String fileName) throws IOException { + java.nio.file.Files.deleteIfExists(Paths.get("src", "test", "resources", fileName)); + } + @Test public void whenWriteUsingFiles_thenWritten() throws IOException { final String expectedValue = "Hello world"; @@ -206,5 +224,4 @@ public class GuavaIOUnitTest { assertEquals(value, result); } - } diff --git a/guava-io/src/test/resources/test1.in b/guava-io/src/test/resources/test1.in new file mode 100644 index 0000000000..70c379b63f --- /dev/null +++ b/guava-io/src/test/resources/test1.in @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/guava-io/src/test/resources/test1_1.in b/guava-io/src/test/resources/test1_1.in new file mode 100644 index 0000000000..8318c86b35 --- /dev/null +++ b/guava-io/src/test/resources/test1_1.in @@ -0,0 +1 @@ +Test \ No newline at end of file diff --git a/guava-io/src/test/resources/test2.in b/guava-io/src/test/resources/test2.in new file mode 100644 index 0000000000..622efea9e6 --- /dev/null +++ b/guava-io/src/test/resources/test2.in @@ -0,0 +1,4 @@ +John +Jane +Adam +Tom \ No newline at end of file diff --git a/guava-modules/guava-18/pom.xml b/guava-modules/guava-18/pom.xml index 30d9f953ac..d65fab1e57 100644 --- a/guava-modules/guava-18/pom.xml +++ b/guava-modules/guava-18/pom.xml @@ -8,9 +8,9 @@ com.baeldung - parent-java + guava-modules 0.0.1-SNAPSHOT - ../../parent-java + ../ diff --git a/guava-modules/guava-19/pom.xml b/guava-modules/guava-19/pom.xml index 0060afd426..20a405cff4 100644 --- a/guava-modules/guava-19/pom.xml +++ b/guava-modules/guava-19/pom.xml @@ -8,9 +8,9 @@ com.baeldung - parent-java + guava-modules 0.0.1-SNAPSHOT - ../../parent-java + ../ diff --git a/guava-modules/guava-21/pom.xml b/guava-modules/guava-21/pom.xml index 7932cfa6d8..b126df99cb 100644 --- a/guava-modules/guava-21/pom.xml +++ b/guava-modules/guava-21/pom.xml @@ -8,9 +8,9 @@ com.baeldung - parent-java + guava-modules 0.0.1-SNAPSHOT - ../../parent-java + ../ diff --git a/guava-modules/pom.xml b/guava-modules/pom.xml index 2b899df162..4e7282364d 100644 --- a/guava-modules/pom.xml +++ b/guava-modules/pom.xml @@ -4,13 +4,16 @@ 4.0.0 guava-modules guava-modules + + 5.6.2 + pom com.baeldung - parent-modules - 1.0.0-SNAPSHOT - .. + parent-java + 0.0.1-SNAPSHOT + ../parent-java @@ -19,4 +22,28 @@ guava-21 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + test + + diff --git a/guava/pom.xml b/guava/pom.xml index df6d57bd09..881390ae73 100644 --- a/guava/pom.xml +++ b/guava/pom.xml @@ -15,13 +15,45 @@ ../parent-java + + guava + + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + org.apache.commons commons-lang3 ${commons-lang3.version} + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + test + org.assertj assertj-core @@ -30,18 +62,9 @@ - - guava - - - src/main/resources - true - - - - + 5.6.2 3.6.1 diff --git a/jackson-modules/pom.xml b/jackson-modules/pom.xml index 4281710ac9..00722510af 100644 --- a/jackson-modules/pom.xml +++ b/jackson-modules/pom.xml @@ -23,6 +23,16 @@ jackson-exceptions + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + com.fasterxml.jackson.core @@ -35,6 +45,22 @@ jackson-dataformat-xml ${jackson.version} + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + test + + + 5.6.2 + \ No newline at end of file diff --git a/jackson-simple/pom.xml b/jackson-simple/pom.xml index f41df7085c..1f838bbed0 100644 --- a/jackson-simple/pom.xml +++ b/jackson-simple/pom.xml @@ -13,6 +13,25 @@ ../parent-java + + jackson-simple + + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + + @@ -20,7 +39,20 @@ jackson-dataformat-xml ${jackson.version} + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + test + org.assertj assertj-core @@ -29,18 +61,9 @@ - - jackson-simple - - - src/main/resources - true - - - - + 5.6.2 3.11.0 diff --git a/jhipster-5/bookstore-monolith/pom.xml b/jhipster-5/bookstore-monolith/pom.xml index 233765e0f3..4e4c82f327 100644 --- a/jhipster-5/bookstore-monolith/pom.xml +++ b/jhipster-5/bookstore-monolith/pom.xml @@ -225,6 +225,12 @@ io.dropwizard.metrics metrics-core + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + diff --git a/libraries-3/README.md b/libraries-3/README.md index 6279dcf5ad..4041ac2d86 100644 --- a/libraries-3/README.md +++ b/libraries-3/README.md @@ -16,5 +16,4 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m - [Introduction to Takes](https://www.baeldung.com/java-takes) - [Using NullAway to Avoid NullPointerExceptions](https://www.baeldung.com/java-nullaway) - [Introduction to Alibaba Arthas](https://www.baeldung.com/java-alibaba-arthas-intro) -- [Quick Guide to Spring Cloud Circuit Breaker](https://www.baeldung.com/spring-cloud-circuit-breaker) - More articles [[<-- prev]](/libraries-2) [[next -->]](/libraries-4) diff --git a/libraries-concurrency/coroutines-with-quasar/README.md b/libraries-concurrency/README.md similarity index 100% rename from libraries-concurrency/coroutines-with-quasar/README.md rename to libraries-concurrency/README.md diff --git a/libraries-concurrency/coroutines-with-quasar/pom.xml b/libraries-concurrency/coroutines-with-quasar/pom.xml deleted file mode 100644 index 59241272e7..0000000000 --- a/libraries-concurrency/coroutines-with-quasar/pom.xml +++ /dev/null @@ -1,84 +0,0 @@ - - 4.0.0 - coroutines-with-quasar - coroutines-with-quasar - - - com.baeldung - libraries-concurrency - 1.0.0-SNAPSHOT - - - - - co.paralleluniverse - quasar-core - 0.8.0 - - - co.paralleluniverse - quasar-actors - 0.8.0 - - - co.paralleluniverse - quasar-reactive-streams - 0.8.0 - - - - - - - maven-dependency-plugin - 3.1.2 - - - getClasspathFilenames - - properties - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - com.baeldung.quasar.App - target/classes - java - - - -Dco.paralleluniverse.fibers.verifyInstrumentation=true - - - -javaagent:${co.paralleluniverse:quasar-core:jar} - - - -classpath - - - - com.baeldung.quasar.App - - - - - maven-compiler-plugin - 3.8.0 - - - org.apache.maven.plugins - maven-compiler-plugin - - 12 - 12 - - - - - diff --git a/libraries-concurrency/pom.xml b/libraries-concurrency/pom.xml index cb59b17674..e1307408b0 100644 --- a/libraries-concurrency/pom.xml +++ b/libraries-concurrency/pom.xml @@ -5,7 +5,6 @@ 4.0.0 libraries-concurrency libraries-concurrency - pom parent-modules @@ -13,8 +12,70 @@ 1.0.0-SNAPSHOT - - - + + + co.paralleluniverse + quasar-core + 0.8.0 + + + co.paralleluniverse + quasar-actors + 0.8.0 + + + co.paralleluniverse + quasar-reactive-streams + 0.8.0 + + + + + + maven-dependency-plugin + 3.1.2 + + + getClasspathFilenames + + properties + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + com.baeldung.quasar.App + target/classes + java + + + -Dco.paralleluniverse.fibers.verifyInstrumentation=true + + + -javaagent:${co.paralleluniverse:quasar-core:jar} + + + -classpath + + + + com.baeldung.quasar.App + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + + + \ No newline at end of file diff --git a/libraries-concurrency/coroutines-with-quasar/src/main/java/com/baeldung/quasar/App.java b/libraries-concurrency/src/main/java/com/baeldung/quasar/App.java similarity index 100% rename from libraries-concurrency/coroutines-with-quasar/src/main/java/com/baeldung/quasar/App.java rename to libraries-concurrency/src/main/java/com/baeldung/quasar/App.java diff --git a/libraries-data-2/README.md b/libraries-data-2/README.md index ce7a1680d1..01f891ba2f 100644 --- a/libraries-data-2/README.md +++ b/libraries-data-2/README.md @@ -12,6 +12,7 @@ This module contains articles about libraries for data processing in Java. - [An Introduction to SuanShu](https://www.baeldung.com/suanshu) - [Intro to Derive4J](https://www.baeldung.com/derive4j) - [Java-R Integration](https://www.baeldung.com/java-r-integration) +- [Univocity Parsers](https://www.baeldung.com/java-univocity-parsers) - More articles: [[<-- prev]](/../libraries-data) ##### Building the project diff --git a/libraries-data-2/pom.xml b/libraries-data-2/pom.xml index 2d27ec2107..ac23747caa 100644 --- a/libraries-data-2/pom.xml +++ b/libraries-data-2/pom.xml @@ -153,7 +153,13 @@ renjin-script-engine ${renjin.version} - + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + + org.apache.kafka kafka-clients ${kafka.version} diff --git a/libraries-testing/pom.xml b/libraries-testing/pom.xml index 89cb0bd494..5a5cb99238 100644 --- a/libraries-testing/pom.xml +++ b/libraries-testing/pom.xml @@ -151,6 +151,13 @@ test + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + + diff --git a/logging-modules/log4j2/README.md b/logging-modules/log4j2/README.md index 6a65ae9c02..06f218f469 100644 --- a/logging-modules/log4j2/README.md +++ b/logging-modules/log4j2/README.md @@ -6,3 +6,4 @@ - [Creating a Custom Log4j2 Appender](https://www.baeldung.com/log4j2-custom-appender) - [Get Log Output in JSON](http://www.baeldung.com/java-log-json-output) - [System.out.println vs Loggers](https://www.baeldung.com/java-system-out-println-vs-loggers) +- [Log4j 2 Plugins](https://www.baeldung.com/log4j2-plugins) diff --git a/netflix-modules/genie/README.md b/netflix-modules/genie/README.md deleted file mode 100644 index f6e15ba403..0000000000 --- a/netflix-modules/genie/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [Introduction to Netflix Genie](https://www.baeldung.com/netflix-genie-intro) diff --git a/netty/src/main/java/com/baeldung/http/server/CustomHttpServerHandler.java b/netty/src/main/java/com/baeldung/http/server/CustomHttpServerHandler.java index 038f559329..abefbed0d9 100644 --- a/netty/src/main/java/com/baeldung/http/server/CustomHttpServerHandler.java +++ b/netty/src/main/java/com/baeldung/http/server/CustomHttpServerHandler.java @@ -5,8 +5,6 @@ import static io.netty.handler.codec.http.HttpResponseStatus.CONTINUE; import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; -import java.util.Set; - import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; @@ -20,9 +18,6 @@ import io.netty.handler.codec.http.HttpObject; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpUtil; import io.netty.handler.codec.http.LastHttpContent; -import io.netty.handler.codec.http.cookie.Cookie; -import io.netty.handler.codec.http.cookie.ServerCookieDecoder; -import io.netty.handler.codec.http.cookie.ServerCookieEncoder; import io.netty.util.CharsetUtil; public class CustomHttpServerHandler extends SimpleChannelInboundHandler { @@ -45,22 +40,20 @@ public class CustomHttpServerHandler extends SimpleChannelInboundHandler } responseData.setLength(0); - responseData.append(ResponseBuilder.addRequestAttributes(request)); - responseData.append(ResponseBuilder.addHeaders(request)); - responseData.append(ResponseBuilder.addParams(request)); + responseData.append(RequestUtils.formatParams(request)); } - responseData.append(ResponseBuilder.addDecoderResult(request)); + responseData.append(RequestUtils.evaluateDecoderResult(request)); if (msg instanceof HttpContent) { HttpContent httpContent = (HttpContent) msg; - responseData.append(ResponseBuilder.addBody(httpContent)); - responseData.append(ResponseBuilder.addDecoderResult(request)); + responseData.append(RequestUtils.formatBody(httpContent)); + responseData.append(RequestUtils.evaluateDecoderResult(request)); if (msg instanceof LastHttpContent) { LastHttpContent trailer = (LastHttpContent) msg; - responseData.append(ResponseBuilder.addLastResponse(request, trailer)); + responseData.append(RequestUtils.prepareLastResponse(request, trailer)); writeResponse(ctx, trailer, responseData); } } @@ -88,18 +81,6 @@ public class CustomHttpServerHandler extends SimpleChannelInboundHandler .set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); } - String cookieString = request.headers() - .get(HttpHeaderNames.COOKIE); - if (cookieString != null) { - Set cookies = ServerCookieDecoder.STRICT.decode(cookieString); - if (!cookies.isEmpty()) { - for (Cookie cookie : cookies) { - httpResponse.headers() - .add(HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode(cookie)); - } - } - } - ctx.write(httpResponse); if (!keepAlive) { diff --git a/netty/src/main/java/com/baeldung/http/server/ResponseBuilder.java b/netty/src/main/java/com/baeldung/http/server/RequestUtils.java similarity index 61% rename from netty/src/main/java/com/baeldung/http/server/ResponseBuilder.java rename to netty/src/main/java/com/baeldung/http/server/RequestUtils.java index 6d4e7845da..92ec2242f3 100644 --- a/netty/src/main/java/com/baeldung/http/server/ResponseBuilder.java +++ b/netty/src/main/java/com/baeldung/http/server/RequestUtils.java @@ -7,32 +7,15 @@ import java.util.Map.Entry; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.DecoderResult; import io.netty.handler.codec.http.HttpContent; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpObject; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.LastHttpContent; import io.netty.handler.codec.http.QueryStringDecoder; import io.netty.util.CharsetUtil; -class ResponseBuilder { +class RequestUtils { - static StringBuilder addRequestAttributes(HttpRequest request) { - StringBuilder responseData = new StringBuilder(); - responseData.append("Version: ") - .append(request.protocolVersion()) - .append("\r\n"); - responseData.append("Host: ") - .append(request.headers() - .get(HttpHeaderNames.HOST, "unknown")) - .append("\r\n"); - responseData.append("URI: ") - .append(request.uri()) - .append("\r\n\r\n"); - return responseData; - } - - static StringBuilder addParams(HttpRequest request) { + static StringBuilder formatParams(HttpRequest request) { StringBuilder responseData = new StringBuilder(); QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.uri()); Map> params = queryStringDecoder.parameters(); @@ -42,9 +25,9 @@ class ResponseBuilder { List vals = p.getValue(); for (String val : vals) { responseData.append("Parameter: ") - .append(key) + .append(key.toUpperCase()) .append(" = ") - .append(val) + .append(val.toUpperCase()) .append("\r\n"); } } @@ -53,24 +36,7 @@ class ResponseBuilder { return responseData; } - static StringBuilder addHeaders(HttpRequest request) { - StringBuilder responseData = new StringBuilder(); - HttpHeaders headers = request.headers(); - if (!headers.isEmpty()) { - for (Map.Entry header : headers) { - CharSequence key = header.getKey(); - CharSequence value = header.getValue(); - responseData.append(key) - .append(" = ") - .append(value) - .append("\r\n"); - } - responseData.append("\r\n"); - } - return responseData; - } - - static StringBuilder addBody(HttpContent httpContent) { + static StringBuilder formatBody(HttpContent httpContent) { StringBuilder responseData = new StringBuilder(); ByteBuf content = httpContent.content(); if (content.isReadable()) { @@ -81,7 +47,7 @@ class ResponseBuilder { return responseData; } - static StringBuilder addDecoderResult(HttpObject o) { + static StringBuilder evaluateDecoderResult(HttpObject o) { StringBuilder responseData = new StringBuilder(); DecoderResult result = o.decoderResult(); @@ -94,7 +60,7 @@ class ResponseBuilder { return responseData; } - static StringBuilder addLastResponse(HttpRequest request, LastHttpContent trailer) { + static StringBuilder prepareLastResponse(HttpRequest request, LastHttpContent trailer) { StringBuilder responseData = new StringBuilder(); responseData.append("Good Bye!\r\n"); diff --git a/netty/src/test/java/com/baeldung/http/server/HttpServerLiveTest.java b/netty/src/test/java/com/baeldung/http/server/HttpServerLiveTest.java index 7a0f884724..77f1288838 100644 --- a/netty/src/test/java/com/baeldung/http/server/HttpServerLiveTest.java +++ b/netty/src/test/java/com/baeldung/http/server/HttpServerLiveTest.java @@ -89,7 +89,7 @@ public class HttpServerLiveTest { } @Test - public void whenGetSent_thenCookieReceivedInResponse() throws Exception { + public void whenGetSent_thenResponseOK() throws Exception { DefaultFullHttpRequest request = createRequest(null); channel.writeAndFlush(request); @@ -98,9 +98,6 @@ public class HttpServerLiveTest { assertEquals(200, response.getStatus()); assertEquals("HTTP/1.1", response.getVersion()); - Map headers = response.getHeaders(); - String cookies = headers.get("set-cookie"); - assertTrue(cookies.contains("my-cookie")); } @After diff --git a/parent-boot-2/pom.xml b/parent-boot-2/pom.xml index 631d8a0581..c7bb11b1d5 100644 --- a/parent-boot-2/pom.xml +++ b/parent-boot-2/pom.xml @@ -32,11 +32,6 @@ io.rest-assured rest-assured - - net.bytebuddy - byte-buddy - ${byte-buddy.version} - org.springframework.boot spring-boot-starter-test diff --git a/patterns/solid/README.md b/patterns/solid/README.md index cae346e3c9..f5146732a0 100644 --- a/patterns/solid/README.md +++ b/patterns/solid/README.md @@ -2,4 +2,4 @@ - [A Solid Guide to Solid Principles](https://www.baeldung.com/solid-principles) - [Single Responsibility Principle in Java](https://www.baeldung.com/java-single-responsibility-principle) - +- [Open/Closed Principle in Java](https://www.baeldung.com/java-open-closed-principle) diff --git a/pdf/README.md b/pdf/README.md index 8c7bd1fa26..b904b101fb 100644 --- a/pdf/README.md +++ b/pdf/README.md @@ -5,3 +5,4 @@ This module contains articles about PDF files. ### Relevant Articles: - [PDF Conversions in Java](https://www.baeldung.com/pdf-conversions-java) - [Creating PDF Files in Java](https://www.baeldung.com/java-pdf-creation) +- [Generating PDF Files Using Thymeleaf](https://www.baeldung.com/thymeleaf-generate-pdf) diff --git a/persistence-modules/core-java-persistence/pom.xml b/persistence-modules/core-java-persistence/pom.xml index 1224523ac7..3dd8da1b7a 100644 --- a/persistence-modules/core-java-persistence/pom.xml +++ b/persistence-modules/core-java-persistence/pom.xml @@ -60,6 +60,7 @@ + 1.4.200 42.2.5.jre7 3.10.0 2.4.0 diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/genkeys/JdbcInsertIdIntegrationTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/genkeys/JdbcInsertIdIntegrationTest.java new file mode 100644 index 0000000000..f1ea5bfbb4 --- /dev/null +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/genkeys/JdbcInsertIdIntegrationTest.java @@ -0,0 +1,93 @@ +package com.baeldung.genkeys; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JdbcInsertIdIntegrationTest { + + private static final String QUERY = "insert into persons (name) values (?)"; + + private static Connection connection; + + @BeforeClass + public static void setUp() throws Exception { + connection = DriverManager.getConnection("jdbc:h2:mem:generated-keys", "sa", ""); + connection + .createStatement() + .execute("create table persons(id bigint auto_increment, name varchar(255))"); + } + + @AfterClass + public static void tearDown() throws SQLException { + connection + .createStatement() + .execute("drop table persons"); + connection.close(); + } + + @Test + public void givenInsert_whenUsingAutoGenFlag_thenBeAbleToFetchTheIdAfterward() throws SQLException { + try (PreparedStatement statement = connection.prepareStatement(QUERY, Statement.RETURN_GENERATED_KEYS)) { + statement.setString(1, "Foo"); + int affectedRows = statement.executeUpdate(); + assertThat(affectedRows).isPositive(); + + try (ResultSet keys = statement.getGeneratedKeys()) { + assertThat(keys.next()).isTrue(); + assertThat(keys.getLong(1)).isGreaterThanOrEqualTo(1); + } + } + } + + @Test + public void givenInsert_whenUsingAutoGenFlagViaExecute_thenBeAbleToFetchTheIdAfterward() throws SQLException { + try (Statement statement = connection.createStatement()) { + String query = "insert into persons (name) values ('Foo')"; + int affectedRows = statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS); + assertThat(affectedRows).isPositive(); + + try (ResultSet keys = statement.getGeneratedKeys()) { + assertThat(keys.next()).isTrue(); + assertThat(keys.getLong(1)).isGreaterThanOrEqualTo(1); + } + } + } + + @Test + public void givenInsert_whenUsingReturningCols_thenBeAbleToFetchTheIdAfterward() throws SQLException { + try (PreparedStatement statement = connection.prepareStatement(QUERY, new String[] { "id" })) { + statement.setString(1, "Foo"); + int affectedRows = statement.executeUpdate(); + assertThat(affectedRows).isPositive(); + + try (ResultSet keys = statement.getGeneratedKeys()) { + assertThat(keys.next()).isTrue(); + assertThat(keys.getLong(1)).isGreaterThanOrEqualTo(1); + } + } + } + + @Test + public void givenInsert_whenUsingReturningColsViaExecute_thenBeAbleToFetchTheIdAfterward() throws SQLException { + try (Statement statement = connection.createStatement()) { + String query = "insert into persons (name) values ('Foo')"; + int affectedRows = statement.executeUpdate(query, new String[] { "id" }); + assertThat(affectedRows).isPositive(); + + try (ResultSet keys = statement.getGeneratedKeys()) { + assertThat(keys.next()).isTrue(); + assertThat(keys.getLong(1)).isGreaterThanOrEqualTo(1); + } + } + } +} diff --git a/persistence-modules/hibernate-enterprise/pom.xml b/persistence-modules/hibernate-enterprise/pom.xml index 060cb4c904..ae58e409c4 100644 --- a/persistence-modules/hibernate-enterprise/pom.xml +++ b/persistence-modules/hibernate-enterprise/pom.xml @@ -55,6 +55,12 @@ hibernate-testing ${hibernate.version} + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + diff --git a/persistence-modules/java-jpa-2/README.md b/persistence-modules/java-jpa-2/README.md index 4b822c4782..d711eef1b0 100644 --- a/persistence-modules/java-jpa-2/README.md +++ b/persistence-modules/java-jpa-2/README.md @@ -13,4 +13,5 @@ This module contains articles about the Java Persistence API (JPA) in Java. - [JPA Annotation for the PostgreSQL TEXT Type](https://www.baeldung.com/jpa-annotation-postgresql-text-type) - [Mapping a Single Entity to Multiple Tables in JPA](https://www.baeldung.com/jpa-mapping-single-entity-to-multiple-tables) - [Constructing a JPA Query Between Unrelated Entities](https://www.baeldung.com/jpa-query-unrelated-entities) +- [When Does JPA Set the Primary Key](https://www.baeldung.com/jpa-strategies-when-set-primary-key) - More articles: [[<-- prev]](/java-jpa) diff --git a/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/Admin.java b/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/Admin.java new file mode 100644 index 0000000000..1c59b33ab8 --- /dev/null +++ b/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/Admin.java @@ -0,0 +1,36 @@ +package com.baeldung.jpa.generateidvalue; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "app_admin") +public class Admin { + + @Id + @GeneratedValue + private Long id; + + @Column(name = "admin_name") + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/Article.java b/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/Article.java new file mode 100644 index 0000000000..06465de179 --- /dev/null +++ b/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/Article.java @@ -0,0 +1,39 @@ +package com.baeldung.jpa.generateidvalue; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +@Entity +@Table(name = "article") +public class Article { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "article_gen") + @SequenceGenerator(name = "article_gen", sequenceName = "article_seq") + private Long id; + + @Column(name = "article_name") + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/IdGenerator.java b/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/IdGenerator.java new file mode 100644 index 0000000000..0fac86747f --- /dev/null +++ b/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/IdGenerator.java @@ -0,0 +1,48 @@ +package com.baeldung.jpa.generateidvalue; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Table(name = "id_gen") +@Entity +public class IdGenerator { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "gen_name") + private String gen_name; + + @Column(name = "gen_value") + private Long gen_value; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getGen_name() { + return gen_name; + } + + public void setGen_name(String gen_name) { + this.gen_name = gen_name; + } + + public Long getGen_value() { + return gen_value; + } + + public void setGen_value(Long gen_value) { + this.gen_value = gen_value; + } + +} \ No newline at end of file diff --git a/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/Task.java b/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/Task.java new file mode 100644 index 0000000000..a51ec53418 --- /dev/null +++ b/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/Task.java @@ -0,0 +1,39 @@ +package com.baeldung.jpa.generateidvalue; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.TableGenerator; + +@Entity +@Table(name = "task") +public class Task { + + @Id + @TableGenerator(name = "id_generator", table = "id_gen", pkColumnName = "gen_name", valueColumnName = "gen_value", pkColumnValue = "task_gen", initialValue = 10000, allocationSize = 10) + @GeneratedValue(strategy = GenerationType.TABLE, generator = "id_generator") + private Long id; + + @Column(name = "name") + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/User.java b/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/User.java new file mode 100644 index 0000000000..88fefe7ba6 --- /dev/null +++ b/persistence-modules/java-jpa-2/src/main/java/com/baeldung/jpa/generateidvalue/User.java @@ -0,0 +1,37 @@ +package com.baeldung.jpa.generateidvalue; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "app_user") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "user_name") + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/persistence-modules/java-jpa-2/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa-2/src/main/resources/META-INF/persistence.xml index eec7f7cf6e..3bc81910d9 100644 --- a/persistence-modules/java-jpa-2/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/java-jpa-2/src/main/resources/META-INF/persistence.xml @@ -184,4 +184,29 @@ value="false" /> + + + org.eclipse.persistence.jpa.PersistenceProvider + com.baeldung.jpa.generateidvalue.Admin + com.baeldung.jpa.generateidvalue.Article + com.baeldung.jpa.generateidvalue.IdGenerator + com.baeldung.jpa.generateidvalue.Task + com.baeldung.jpa.generateidvalue.User + true + + + + + + + + + + + + + diff --git a/persistence-modules/java-jpa-2/src/main/resources/primary_key_generator.sql b/persistence-modules/java-jpa-2/src/main/resources/primary_key_generator.sql new file mode 100644 index 0000000000..9acd1bc11b --- /dev/null +++ b/persistence-modules/java-jpa-2/src/main/resources/primary_key_generator.sql @@ -0,0 +1,4 @@ +CREATE SEQUENCE article_seq MINVALUE 1 START WITH 50 INCREMENT BY 50; + +INSERT INTO id_gen (gen_name, gen_val) VALUES ('id_generator', 0); +INSERT INTO id_gen (gen_name, gen_val) VALUES ('task_gen', 10000); \ No newline at end of file diff --git a/persistence-modules/java-jpa-2/src/test/java/com/baeldung/jpa/generateidvalue/PrimaryKeyUnitTest.java b/persistence-modules/java-jpa-2/src/test/java/com/baeldung/jpa/generateidvalue/PrimaryKeyUnitTest.java new file mode 100644 index 0000000000..eead56dbff --- /dev/null +++ b/persistence-modules/java-jpa-2/src/test/java/com/baeldung/jpa/generateidvalue/PrimaryKeyUnitTest.java @@ -0,0 +1,81 @@ +package com.baeldung.jpa.generateidvalue; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * PrimaryKeyGeneratorTest class + * + * @author shiwangzhihe@gmail.com + */ +public class PrimaryKeyUnitTest { + private static EntityManager entityManager; + + @BeforeClass + public static void setup() { + EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-h2-primarykey"); + entityManager = factory.createEntityManager(); + } + + @Test + public void givenIdentityStrategy_whenCommitTransction_thenReturnPrimaryKey() { + User user = new User(); + user.setName("TestName"); + + entityManager.getTransaction() + .begin(); + entityManager.persist(user); + Assert.assertNull(user.getId()); + entityManager.getTransaction() + .commit(); + + Long expectPrimaryKey = 1L; + Assert.assertEquals(expectPrimaryKey, user.getId()); + } + + @Test + public void givenTableStrategy_whenPersist_thenReturnPrimaryKey() { + Task task = new Task(); + task.setName("Test Task"); + + entityManager.getTransaction() + .begin(); + entityManager.persist(task); + Long expectPrimaryKey = 10000L; + Assert.assertEquals(expectPrimaryKey, task.getId()); + + entityManager.getTransaction() + .commit(); + } + + @Test + public void givenSequenceStrategy_whenPersist_thenReturnPrimaryKey() { + Article article = new Article(); + article.setName("Test Name"); + + entityManager.getTransaction() + .begin(); + entityManager.persist(article); + Long expectPrimaryKey = 51L; + Assert.assertEquals(expectPrimaryKey, article.getId()); + + entityManager.getTransaction() + .commit(); + } + + @Test + public void givenAutoStrategy_whenPersist_thenReturnPrimaryKey() { + Admin admin = new Admin(); + admin.setName("Test Name"); + + entityManager.persist(admin); + + Long expectPrimaryKey = 1L; + Assert.assertEquals(expectPrimaryKey, admin.getId()); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-elasticsearch/README.md b/persistence-modules/spring-data-elasticsearch/README.md index 22126c2f00..63f1185732 100644 --- a/persistence-modules/spring-data-elasticsearch/README.md +++ b/persistence-modules/spring-data-elasticsearch/README.md @@ -6,6 +6,7 @@ - [Guide to Elasticsearch in Java](https://www.baeldung.com/elasticsearch-java) - [Geospatial Support in ElasticSearch](https://www.baeldung.com/elasticsearch-geo-spatial) - [A Simple Tagging Implementation with Elasticsearch](https://www.baeldung.com/elasticsearch-tagging) +- [Introduction to Spring Data Elasticsearch – test 2](https://www.baeldung.com/spring-data-elasticsearch-test-2) ### Build the Project with Tests Running ``` diff --git a/persistence-modules/spring-jpa/README.md b/persistence-modules/spring-jpa/README.md index 5db88cd5ee..94a1e1f575 100644 --- a/persistence-modules/spring-jpa/README.md +++ b/persistence-modules/spring-jpa/README.md @@ -10,9 +10,9 @@ - [Self-Contained Testing Using an In-Memory Database](https://www.baeldung.com/spring-jpa-test-in-memory-database) - [A Guide to Spring AbstractRoutingDatasource](https://www.baeldung.com/spring-abstract-routing-data-source) - [Obtaining Auto-generated Keys in Spring JDBC](https://www.baeldung.com/spring-jdbc-autogenerated-keys) -- [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring) - [Use Criteria Queries in a Spring Data Application](https://www.baeldung.com/spring-data-criteria-queries) - [Many-To-Many Relationship in JPA](https://www.baeldung.com/jpa-many-to-many) +- [Spring Persistence (Hibernate and JPA) with a JNDI datasource](https://www.baeldung.com/spring-persistence-hibernate-and-jpa-with-a-jndi-datasource-2) ### Eclipse Config diff --git a/persistence-modules/spring-persistence-simple-2/README.md b/persistence-modules/spring-persistence-simple-2/README.md index 70eab26d45..477c938f89 100644 --- a/persistence-modules/spring-persistence-simple-2/README.md +++ b/persistence-modules/spring-persistence-simple-2/README.md @@ -2,3 +2,4 @@ - [Spring JdbcTemplate Unit Testing](https://www.baeldung.com/spring-jdbctemplate-testing) - [Using a List of Values in a JdbcTemplate IN Clause](https://www.baeldung.com/spring-jdbctemplate-in-list) +- [Transactional Annotations: Spring vs. JTA](https://www.baeldung.com/spring-vs-jta-transactional) diff --git a/pom.xml b/pom.xml index f797f1bbce..e441386a53 100644 --- a/pom.xml +++ b/pom.xml @@ -69,12 +69,6 @@ ${hamcrest-all.version} test - - net.bytebuddy - byte-buddy - ${byte-buddy.version} - test - org.mockito mockito-core @@ -1280,7 +1274,7 @@ wildfly xml xstream - libraries-concurrency + diff --git a/spring-boot-modules/spring-boot-ci-cd/README.md b/spring-boot-modules/spring-boot-ci-cd/README.md index ee8f106b53..0a38c23ab7 100644 --- a/spring-boot-modules/spring-boot-ci-cd/README.md +++ b/spring-boot-modules/spring-boot-ci-cd/README.md @@ -4,4 +4,4 @@ This module contains articles about CI/CD with Spring Boot ## Relevant Articles -- [CI/CD for a Spring Boot Project](https://www.baeldung.com/spring-boot-ci-cd) +- [Applying CI/CD With Spring Boot](https://www.baeldung.com/spring-boot-ci-cd) diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/crud/controllers/UserController.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/crud/controllers/UserController.java index 726be6a384..8a7ef96f1e 100644 --- a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/crud/controllers/UserController.java +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/crud/controllers/UserController.java @@ -36,7 +36,7 @@ public class UserController { userRepository.save(user); model.addAttribute("users", userRepository.findAll()); - return "index"; + return "redirect:/index"; } @GetMapping("/edit/{id}") @@ -55,7 +55,7 @@ public class UserController { userRepository.save(user); model.addAttribute("users", userRepository.findAll()); - return "index"; + return "redirect:/index"; } @GetMapping("/delete/{id}") diff --git a/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/crud/UserControllerUnitTest.java b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/crud/UserControllerUnitTest.java index 033108c195..f1455f7a73 100644 --- a/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/crud/UserControllerUnitTest.java +++ b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/crud/UserControllerUnitTest.java @@ -41,7 +41,7 @@ public class UserControllerUnitTest { when(mockedBindingResult.hasErrors()).thenReturn(false); - assertThat(userController.addUser(user, mockedBindingResult, mockedModel)).isEqualTo("index"); + assertThat(userController.addUser(user, mockedBindingResult, mockedModel)).isEqualTo("redirect:/index"); } @Test @@ -64,7 +64,7 @@ public class UserControllerUnitTest { when(mockedBindingResult.hasErrors()).thenReturn(false); - assertThat(userController.updateUser(1l, user, mockedBindingResult, mockedModel)).isEqualTo("index"); + assertThat(userController.updateUser(1l, user, mockedBindingResult, mockedModel)).isEqualTo("redirect:/index"); } @Test diff --git a/spring-boot-modules/spring-boot-mvc-3/README.md b/spring-boot-modules/spring-boot-mvc-3/README.md new file mode 100644 index 0000000000..c220c6c405 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-3/README.md @@ -0,0 +1,7 @@ +## Spring Boot MVC + +This module contains articles about Spring Web MVC in Spring Boot projects. + +### Relevant Articles: + +- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2) \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-3/pom.xml b/spring-boot-modules/spring-boot-mvc-3/pom.xml new file mode 100644 index 0000000000..64e8a99c6c --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-3/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + spring-boot-mvc-3 + spring-boot-mvc-3 + jar + Module For Spring Boot MVC Web + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/circularviewpath/CircularViewPathApplication.java b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/circularviewpath/CircularViewPathApplication.java new file mode 100644 index 0000000000..deb50e2ed7 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/circularviewpath/CircularViewPathApplication.java @@ -0,0 +1,21 @@ +package com.baeldung.circularviewpath; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Spring Boot launcher for an application + * + */ +@SpringBootApplication(scanBasePackages = "com.baeldung.controller.circularviewpath") +public class CircularViewPathApplication { + + /** + * Launches a Spring Boot application + * + * @param args null + */ + public static void main(String[] args) { + SpringApplication.run(CircularViewPathApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/controller/circularviewpath/CircularViewPathController.java b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/controller/circularviewpath/CircularViewPathController.java new file mode 100644 index 0000000000..a4d6a97f7d --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-3/src/main/java/com/baeldung/controller/circularviewpath/CircularViewPathController.java @@ -0,0 +1,16 @@ +package com.baeldung.controller.circularviewpath; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class CircularViewPathController { + + /** + * A request mapping which may cause circular view path exception + */ + @GetMapping("/path") + public String path() { + return "path"; + } +} diff --git a/spring-boot-modules/spring-boot-mvc-3/src/main/resources/logback.xml b/spring-boot-modules/spring-boot-mvc-3/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-3/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-3/src/main/resources/templates/path.html b/spring-boot-modules/spring-boot-mvc-3/src/main/resources/templates/path.html new file mode 100644 index 0000000000..b329797275 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-3/src/main/resources/templates/path.html @@ -0,0 +1,13 @@ + + + + + + + path.html + + + +

path.html

+ + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties-2/README.md b/spring-boot-modules/spring-boot-properties-2/README.md index cd0fd5e5ee..1874fa74a5 100644 --- a/spring-boot-modules/spring-boot-properties-2/README.md +++ b/spring-boot-modules/spring-boot-properties-2/README.md @@ -7,4 +7,5 @@ This module contains articles about Properties in Spring Boot. - [A Quick Guide to Spring @Value](https://www.baeldung.com/spring-value-annotation) - [Using Spring @Value with Defaults](https://www.baeldung.com/spring-value-defaults) - [How to Inject a Property Value Into a Class Not Managed by Spring?](https://www.baeldung.com/inject-properties-value-non-spring-class) -- More articles: [[<-- prev]](../spring-boot-properties) \ No newline at end of file +- [@PropertySource with YAML Files in Spring Boot](https://www.baeldung.com/spring-yaml-propertysource) +- More articles: [[<-- prev]](../spring-boot-properties) diff --git a/spring-boot-modules/spring-boot-properties/.dockerignore b/spring-boot-modules/spring-boot-properties/.dockerignore deleted file mode 100644 index df36044e46..0000000000 --- a/spring-boot-modules/spring-boot-properties/.dockerignore +++ /dev/null @@ -1,13 +0,0 @@ -# Logs -logs -*.log - -# Git -.git -.cache - -# Classes -**/*.class - -# Ignore md files -*.md diff --git a/spring-boot-modules/spring-boot-properties/Dockerfile b/spring-boot-modules/spring-boot-properties/Dockerfile deleted file mode 100644 index d6bd2a95ae..0000000000 --- a/spring-boot-modules/spring-boot-properties/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM maven:3.6.0-jdk-11 -WORKDIR /code/spring-boot-modules/spring-boot-properties/ -COPY ./spring-boot-modules/spring-boot-properties/pom.xml . -COPY ./spring-boot-modules/spring-boot-properties/src ./src -COPY ./parent-boot-2/pom.xml /code/parent-boot-2/pom.xml -COPY ./pom.xml /code/pom.xml -COPY ./custom-pmd-0.0.1.jar /code/custom-pmd-0.0.1.jar -COPY ./baeldung-pmd-rules.xml /code/baeldung-pmd-rules.xml -RUN mvn dependency:resolve -CMD ["mvn", "spring-boot:run"] \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/MyApplication.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/MyApplication.java index d42b731213..f3cfff57b7 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/MyApplication.java +++ b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/MyApplication.java @@ -11,6 +11,9 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import com.baeldung.yaml.YAMLConfig.Idm; +import com.baeldung.yaml.YAMLConfig.Service; + @SpringBootApplication public class MyApplication implements CommandLineRunner { @@ -26,6 +29,23 @@ public class MyApplication implements CommandLineRunner { System.out.println("using environment:" + myConfig.getEnvironment()); System.out.println("name:" + myConfig.getName()); System.out.println("servers:" + myConfig.getServers()); + + if ("testing".equalsIgnoreCase(myConfig.getEnvironment())) { + System.out.println("external:" + myConfig.getExternal()); + System.out.println("map:" + myConfig.getMap()); + + Idm idm = myConfig.getComponent().getIdm(); + Service service = myConfig.getComponent().getService(); + System.out.println("Idm:"); + System.out.println(" Url: " + idm.getUrl()); + System.out.println(" User: " + idm.getUser()); + System.out.println(" Password: " + idm.getPassword()); + System.out.println(" Description: " + idm.getDescription()); + System.out.println("Service:"); + System.out.println(" Url: " + service.getUrl()); + System.out.println(" Token: " + service.getToken()); + System.out.println(" Description: " + service.getDescription()); + } } } diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/YAMLConfig.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/YAMLConfig.java index ad633c4b56..83c083734c 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/YAMLConfig.java +++ b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/YAMLConfig.java @@ -1,7 +1,10 @@ package com.baeldung.yaml; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; + import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; @@ -13,6 +16,9 @@ public class YAMLConfig { private String name; private String environment; private List servers = new ArrayList(); + private List external = new ArrayList(); + private Map map = new HashMap(); + private Component component = new Component(); public List getServers() { return servers; @@ -37,5 +43,111 @@ public class YAMLConfig { public void setEnvironment(String environment) { this.environment = environment; } + + public Component getComponent() { + return component; + } + + public void setComponent(Component component) { + this.component = component; + } + + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } + + public List getExternal() { + return external; + } + + public void setExternal(List external) { + this.external = external; + } + + public class Component { + private Idm idm = new Idm(); + private Service service = new Service(); + + public Idm getIdm() { + return idm; + } + public void setIdm(Idm idm) { + this.idm = idm; + } + + public Service getService() { + return service; + } + public void setService(Service service) { + this.service = service; + } + + } + + public class Idm { + private String url; + private String user; + private String password; + private String description; + + public String getUrl() { + return url; + } + public void setUrl(String url) { + this.url = url; + } + + public String getUser() { + return user; + } + public void setUser(String user) { + this.user = user; + } + + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + } + + public class Service { + private String url; + private String token; + private String description; + + public String getUrl() { + return url; + } + public void setUrl(String url) { + this.url = url; + } + + public String getToken() { + return token; + } + public void setToken(String token) { + this.token = token; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + } } diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/application.yml b/spring-boot-modules/spring-boot-properties/src/main/resources/application.yml index 4914ff15f7..30e64f9d35 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/resources/application.yml +++ b/spring-boot-modules/spring-boot-properties/src/main/resources/application.yml @@ -6,22 +6,42 @@ spring: --- spring: - profiles: test + profiles: test name: test-YAML environment: testing servers: - - www.abc.test.com - - www.xyz.test.com - + - www.abc.test.com + - www.xyz.test.com + +external: [www.abc.test.com, www.xyz.test.com] + +map: + firstkey: key1 + secondkey: key2 + +component: + idm: + url: myurl + user: user + password: password + description: > + this should be a long + description + service: + url: myurlservice + token: token + description: > + this should be another long + description --- spring: - profiles: prod + profiles: prod name: prod-YAML environment: production servers: - - www.abc.com - - www.xyz.com + - www.abc.com + - www.xyz.com --- diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLIntegrationTest.java index 090d5c592e..19412c91f5 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLIntegrationTest.java +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLIntegrationTest.java @@ -11,6 +11,7 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(classes = MyApplication.class) +@TestPropertySource(properties = {"spring.profiles.active = test"}) class YAMLIntegrationTest { @Autowired @@ -20,5 +21,6 @@ class YAMLIntegrationTest { void whenProfileTest_thenNameTesting() { assertTrue("testing".equalsIgnoreCase(config.getEnvironment())); assertTrue("test-YAML".equalsIgnoreCase(config.getName())); + assertTrue("myurl".equalsIgnoreCase(config.getComponent().getIdm().getUrl())); } } diff --git a/spring-boot-modules/spring-boot-springdoc/README.md b/spring-boot-modules/spring-boot-springdoc/README.md index e54f4e926f..2447f30f6b 100644 --- a/spring-boot-modules/spring-boot-springdoc/README.md +++ b/spring-boot-modules/spring-boot-springdoc/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: -- [Documenting a Spring REST API Using OpenAPI 3.0](https://www.baeldung.com/spring-rest-openapi-documentation) +- [Documenting a Spring REST API Using OpenAPI 3.0](https://www.baeldung.com/spring-rest-openapi-documentation) +- [Spring REST Docs vs OpenAPI](https://www.baeldung.com/spring-rest-docs-vs-openapi) diff --git a/spring-cloud-data-flow/apache-spark-job/pom.xml b/spring-cloud-data-flow/apache-spark-job/pom.xml index 65a57671ea..a4816a30ba 100644 --- a/spring-cloud-data-flow/apache-spark-job/pom.xml +++ b/spring-cloud-data-flow/apache-spark-job/pom.xml @@ -22,16 +22,6 @@ org.apache.spark spark-core_${scala.version} ${spark.version} - - - log4j - log4j - - - org.slf4j - slf4j-log4j12 - -
diff --git a/spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java b/spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java index dfead21728..3f7c3be678 100644 --- a/spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java +++ b/spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java @@ -13,7 +13,7 @@ import java.util.stream.IntStream; public class PiApproximation { public static void main(String[] args) { - SparkConf conf = new SparkConf().setAppName("BaeldungPIApproximation"); + SparkConf conf = new SparkConf().setAppName("BaeldungPIApproximation").setMaster("local[2]"); JavaSparkContext context = new JavaSparkContext(conf); int slices = args.length >= 1 ? Integer.valueOf(args[0]) : 2; int n = (100000L * slices) > Integer.MAX_VALUE ? Integer.MAX_VALUE : 100000 * slices; diff --git a/spring-cloud-data-flow/batch-job/pom.xml b/spring-cloud-data-flow/batch-job/pom.xml index e11df0df8e..6b02b000e1 100644 --- a/spring-cloud-data-flow/batch-job/pom.xml +++ b/spring-cloud-data-flow/batch-job/pom.xml @@ -11,9 +11,8 @@ com.baeldung - parent-boot-1 + spring-cloud-data-flow 0.0.1-SNAPSHOT - ../../parent-boot-1 @@ -21,7 +20,7 @@ org.springframework.cloud spring-cloud-dependencies - Brixton.SR5 + Hoxton.SR4 pom import @@ -31,8 +30,7 @@ org.springframework.cloud - spring-cloud-task-starter - ${spring-cloud-task-starter.version} + spring-cloud-starter-task @@ -48,7 +46,7 @@ - 1.0.3.RELEASE + 2.2.3.RELEASE diff --git a/spring-cloud-data-flow/pom.xml b/spring-cloud-data-flow/pom.xml index e2a0664f30..5b516146ae 100644 --- a/spring-cloud-data-flow/pom.xml +++ b/spring-cloud-data-flow/pom.xml @@ -9,8 +9,9 @@ com.baeldung - parent-modules - 1.0.0-SNAPSHOT + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-etl/customer-mongodb-sink/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-etl/customer-mongodb-sink/pom.xml index 9fd378b171..43772505a4 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-etl/customer-mongodb-sink/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-etl/customer-mongodb-sink/pom.xml @@ -9,9 +9,8 @@ com.baeldung - parent-boot-2 + spring-cloud-data-flow-etl 0.0.1-SNAPSHOT - ../../../parent-boot-2 @@ -63,7 +62,7 @@ UTF-8 UTF-8 - Greenwich.RELEASE + Hoxton.SR4 diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-etl/customer-transform/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-etl/customer-transform/pom.xml index fdec22f3b3..f0d18a1c4f 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-etl/customer-transform/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-etl/customer-transform/pom.xml @@ -9,9 +9,8 @@ com.baeldung - parent-boot-2 + spring-cloud-data-flow-etl 0.0.1-SNAPSHOT - ../../../parent-boot-2 @@ -55,7 +54,7 @@ UTF-8 UTF-8 - Greenwich.RELEASE + Hoxton.SR4 diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/pom.xml index ba108dc5c7..34da489cd1 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/pom.xml @@ -50,6 +50,12 @@ hibernate-entitymanager ${hibernate.compatible.version} + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + test + diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/log-sink/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/log-sink/pom.xml index 02d572aeb7..186e5b1886 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/log-sink/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/log-sink/pom.xml @@ -10,9 +10,8 @@ com.baeldung - parent-boot-1 + spring-cloud-data-flow-stream-processing 0.0.1-SNAPSHOT - ../../../parent-boot-1 @@ -35,7 +34,7 @@ - Brixton.SR7 + Hoxton.SR4 diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/pom.xml index 5342049d73..e794287e10 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/pom.xml @@ -2,6 +2,7 @@ 4.0.0 + com.baeldung spring-cloud-data-flow-stream-processing 0.0.1-SNAPSHOT spring-cloud-data-flow-stream-processing @@ -9,9 +10,8 @@ com.baeldung - parent-modules - 1.0.0-SNAPSHOT - ../../ + spring-cloud-data-flow + 0.0.1-SNAPSHOT @@ -21,5 +21,13 @@ time-processor log-sink + + + + org.springframework.boot + spring-boot-starter-test + test + + diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-processor/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-processor/pom.xml index f8db434423..b4ad84cfe9 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-processor/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-processor/pom.xml @@ -10,9 +10,8 @@ com.baeldung - parent-boot-1 + spring-cloud-data-flow-stream-processing 0.0.1-SNAPSHOT - ../../../parent-boot-1 @@ -35,7 +34,7 @@ - Brixton.SR7 + Hoxton.SR4 diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-source/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-source/pom.xml index 8194755814..05908d3c52 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-source/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-source/pom.xml @@ -2,6 +2,7 @@ 4.0.0 + com.baeldung.spring.cloud time-source 0.0.1-SNAPSHOT time-source @@ -10,9 +11,8 @@ com.baeldung - parent-boot-1 + spring-cloud-data-flow-stream-processing 0.0.1-SNAPSHOT - ../../../parent-boot-1 @@ -35,7 +35,7 @@ - Brixton.SR7 + Hoxton.SR4 diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index 3de527c33b..6fddb1693f 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -40,6 +40,7 @@ spring-cloud-task spring-cloud-zuul spring-cloud-zuul-fallback + spring-cloud-ribbon-retry diff --git a/spring-cloud/spring-cloud-ribbon-retry/pom.xml b/spring-cloud/spring-cloud-ribbon-retry/pom.xml new file mode 100644 index 0000000000..5318ea6913 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + com.baeldung.spring.cloud + spring-cloud-ribbon-retry + 0.0.1-SNAPSHOT + spring-cloud-ribbon-retry + pom + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + ribbon-client-service + ribbon-weather-service + + + + + + org.springframework.cloud + spring-cloud-starter-parent + ${spring-cloud.version} + pom + import + + + + + + Hoxton.SR3 + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/pom.xml b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/pom.xml new file mode 100644 index 0000000000..ad47eb6c84 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + ribbon-client-service + + + com.baeldung.spring.cloud + spring-cloud-ribbon-retry + 0.0.1-SNAPSHOT + + + + + org.springframework.cloud + spring-cloud-starter-netflix-ribbon + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.retry + spring-retry + + + com.baeldung.spring.cloud + ribbon-weather-service + 0.0.1-SNAPSHOT + test + + + + + Hoxton.SR3 + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/RibbonClientApp.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/RibbonClientApp.java new file mode 100644 index 0000000000..e06d4a93a1 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/RibbonClientApp.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.cloud.ribbon.retry; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RibbonClientApp { + + public static void main(String[] args) { + SpringApplication.run(RibbonClientApp.class, args); + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/backoff/ExponentialBackoffRetryFactory.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/backoff/ExponentialBackoffRetryFactory.java new file mode 100644 index 0000000000..c70ee71b7d --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/backoff/ExponentialBackoffRetryFactory.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.cloud.ribbon.retry.backoff; + +import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryFactory; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.context.annotation.Profile; +import org.springframework.retry.backoff.BackOffPolicy; +import org.springframework.retry.backoff.ExponentialBackOffPolicy; +import org.springframework.stereotype.Component; + +@Component +@Profile("exponential-backoff") +class ExponentialBackoffRetryFactory extends RibbonLoadBalancedRetryFactory { + + public ExponentialBackoffRetryFactory(SpringClientFactory clientFactory) { + super(clientFactory); + } + + @Override + public BackOffPolicy createBackOffPolicy(String service) { + ExponentialBackOffPolicy exponentialBackOffPolicy = new ExponentialBackOffPolicy(); + exponentialBackOffPolicy.setInitialInterval(1000); + exponentialBackOffPolicy.setMultiplier(2); + exponentialBackOffPolicy.setMaxInterval(10000); + return exponentialBackOffPolicy; + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/backoff/ExponentialRandomBackoffRetryFactory.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/backoff/ExponentialRandomBackoffRetryFactory.java new file mode 100644 index 0000000000..c1fad4d1a0 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/backoff/ExponentialRandomBackoffRetryFactory.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.cloud.ribbon.retry.backoff; + +import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryFactory; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.context.annotation.Profile; +import org.springframework.retry.backoff.BackOffPolicy; +import org.springframework.retry.backoff.ExponentialRandomBackOffPolicy; +import org.springframework.stereotype.Component; + +@Component +@Profile("exponential-random-backoff") +class ExponentialRandomBackoffRetryFactory extends RibbonLoadBalancedRetryFactory { + + public ExponentialRandomBackoffRetryFactory(SpringClientFactory clientFactory) { + super(clientFactory); + } + + @Override + public BackOffPolicy createBackOffPolicy(String service) { + ExponentialRandomBackOffPolicy exponentialRandomBackOffPolicy = new ExponentialRandomBackOffPolicy(); + exponentialRandomBackOffPolicy.setInitialInterval(1000); + exponentialRandomBackOffPolicy.setMultiplier(2); + exponentialRandomBackOffPolicy.setMaxInterval(10000); + return exponentialRandomBackOffPolicy; + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/backoff/FixedBackoffRetryFactory.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/backoff/FixedBackoffRetryFactory.java new file mode 100644 index 0000000000..6dab5d15b4 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/backoff/FixedBackoffRetryFactory.java @@ -0,0 +1,24 @@ +package com.baeldung.spring.cloud.ribbon.retry.backoff; + +import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancedRetryFactory; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; +import org.springframework.context.annotation.Profile; +import org.springframework.retry.backoff.BackOffPolicy; +import org.springframework.retry.backoff.FixedBackOffPolicy; +import org.springframework.stereotype.Component; + +@Component +@Profile("fixed-backoff") +class FixedBackoffRetryFactory extends RibbonLoadBalancedRetryFactory { + + public FixedBackoffRetryFactory(SpringClientFactory clientFactory) { + super(clientFactory); + } + + @Override + public BackOffPolicy createBackOffPolicy(String service) { + FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy(); + fixedBackOffPolicy.setBackOffPeriod(2000); + return fixedBackOffPolicy; + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/config/RibbonConfiguration.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/config/RibbonConfiguration.java new file mode 100644 index 0000000000..c493b4dbe2 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/config/RibbonConfiguration.java @@ -0,0 +1,20 @@ +package com.baeldung.spring.cloud.ribbon.retry.config; + +import com.netflix.loadbalancer.IPing; +import com.netflix.loadbalancer.IRule; +import com.netflix.loadbalancer.PingUrl; +import com.netflix.loadbalancer.WeightedResponseTimeRule; +import org.springframework.context.annotation.Bean; + +public class RibbonConfiguration { + + @Bean + public IPing ribbonPing() { + return new PingUrl(); + } + + @Bean + public IRule ribbonRule() { + return new WeightedResponseTimeRule(); + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/config/WeatherClientRibbonConfiguration.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/config/WeatherClientRibbonConfiguration.java new file mode 100644 index 0000000000..88955db025 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/config/WeatherClientRibbonConfiguration.java @@ -0,0 +1,19 @@ +package com.baeldung.spring.cloud.ribbon.retry.config; + +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.cloud.netflix.ribbon.RibbonClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +@RibbonClient(name = "weather-service", configuration = RibbonConfiguration.class) +public class WeatherClientRibbonConfiguration { + + @LoadBalanced + @Bean + RestTemplate getRestTemplate() { + return new RestTemplate(); + } + +} diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/controller/RibbonClientController.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/controller/RibbonClientController.java new file mode 100644 index 0000000000..ebe5b58386 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/controller/RibbonClientController.java @@ -0,0 +1,21 @@ +package com.baeldung.spring.cloud.ribbon.retry.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +@RestController +public class RibbonClientController { + + private static final String WEATHER_SERVICE = "weather-service"; + + @Autowired + private RestTemplate restTemplate; + + @GetMapping("/client/weather") + public String weather() { + String result = restTemplate.getForObject("http://" + WEATHER_SERVICE + "/weather", String.class); + return "Weather Service Response: " + result; + } +} diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/resources/application.yml b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/resources/application.yml new file mode 100644 index 0000000000..3199f38dce --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/main/resources/application.yml @@ -0,0 +1,17 @@ +spring: + profiles: + # fixed-backoff, exponential-backoff, exponential-random-backoff + active: fixed-backoff + application: + name: ribbon-client + +weather-service: + ribbon: + eureka: + enabled: false + listOfServers: http://localhost:8081, http://localhost:8082 + ServerListRefreshInterval: 5000 + MaxAutoRetries: 3 + MaxAutoRetriesNextServer: 1 + OkToRetryOnAllOperations: true + retryableStatusCodes: 503, 408 diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/test/java/com/baeldung/spring/cloud/ribbon/retry/RibbonRetryFailureIntegrationTest.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/test/java/com/baeldung/spring/cloud/ribbon/retry/RibbonRetryFailureIntegrationTest.java new file mode 100644 index 0000000000..0e72bdbb86 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/test/java/com/baeldung/spring/cloud/ribbon/retry/RibbonRetryFailureIntegrationTest.java @@ -0,0 +1,50 @@ +package com.baeldung.spring.cloud.ribbon.retry; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.http.ResponseEntity; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = RibbonClientApp.class) +public class RibbonRetryFailureIntegrationTest { + + private static ConfigurableApplicationContext weatherServiceInstance1; + private static ConfigurableApplicationContext weatherServiceInstance2; + + @LocalServerPort + private int port; + private TestRestTemplate restTemplate = new TestRestTemplate(); + + @BeforeAll + public static void setup() { + weatherServiceInstance1 = startApp(8081); + weatherServiceInstance2 = startApp(8082); + } + + @AfterAll + public static void cleanup() { + weatherServiceInstance1.close(); + weatherServiceInstance2.close(); + } + + private static ConfigurableApplicationContext startApp(int port) { + return SpringApplication.run(RibbonWeatherServiceApp.class, "--server.port=" + port, "--successful.call.divisor=6"); + } + + @Test + public void whenRibbonClientIsCalledAndServiceUnavailable_thenFailure() { + String url = "http://localhost:" + port + "/client/weather"; + + ResponseEntity response = restTemplate.getForEntity(url, String.class); + + assertTrue(response.getStatusCode().is5xxServerError()); + } + +} diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/test/java/com/baeldung/spring/cloud/ribbon/retry/RibbonRetrySuccessIntegrationTest.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/test/java/com/baeldung/spring/cloud/ribbon/retry/RibbonRetrySuccessIntegrationTest.java new file mode 100644 index 0000000000..2055159117 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-client-service/src/test/java/com/baeldung/spring/cloud/ribbon/retry/RibbonRetrySuccessIntegrationTest.java @@ -0,0 +1,52 @@ +package com.baeldung.spring.cloud.ribbon.retry; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.http.ResponseEntity; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = RibbonClientApp.class) +public class RibbonRetrySuccessIntegrationTest { + + private static ConfigurableApplicationContext weatherServiceInstance1; + private static ConfigurableApplicationContext weatherServiceInstance2; + + @LocalServerPort + private int port; + private TestRestTemplate restTemplate = new TestRestTemplate(); + + @BeforeAll + public static void setup() { + weatherServiceInstance1 = startApp(8081); + weatherServiceInstance2 = startApp(8082); + } + + private static ConfigurableApplicationContext startApp(int port) { + return SpringApplication.run(RibbonWeatherServiceApp.class, "--server.port=" + port, "--successful.call.divisor=3"); + } + + @AfterAll + public static void cleanup() { + weatherServiceInstance1.close(); + weatherServiceInstance2.close(); + } + + @Test + public void whenRibbonClientIsCalledAndServiceAvailable_thenSuccess() { + String url = "http://localhost:" + port + "/client/weather"; + + ResponseEntity response = restTemplate.getForEntity(url, String.class); + + assertTrue(response.getStatusCode().is2xxSuccessful()); + assertEquals(response.getBody(), "Weather Service Response: Today's a sunny day"); + } + +} diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/pom.xml b/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/pom.xml new file mode 100644 index 0000000000..f091341025 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + ribbon-weather-service + + + com.baeldung.spring.cloud + spring-cloud-ribbon-retry + 0.0.1-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/RibbonWeatherServiceApp.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/RibbonWeatherServiceApp.java new file mode 100644 index 0000000000..ceeacbd426 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/RibbonWeatherServiceApp.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.cloud.ribbon.retry; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RibbonWeatherServiceApp { + + public static void main(String[] args) { + SpringApplication.run(RibbonWeatherServiceApp.class, args); + } +} diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/WeatherController.java b/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/WeatherController.java new file mode 100644 index 0000000000..ec0b94e505 --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/src/main/java/com/baeldung/spring/cloud/ribbon/retry/WeatherController.java @@ -0,0 +1,39 @@ +package com.baeldung.spring.cloud.ribbon.retry; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class WeatherController { + + private static final Logger LOGGER = LoggerFactory.getLogger(WeatherController.class); + + private int nrOfCalls = 0; + + @Value("${successful.call.divisor}") + private int divisor; + + @GetMapping("/") + public String health() { + return "I am Ok"; + } + + @GetMapping("/weather") + public ResponseEntity weather() { + LOGGER.info("Providing today's weather information"); + if (isServiceUnavailable()) { + return new ResponseEntity<>(HttpStatus.SERVICE_UNAVAILABLE); + } + LOGGER.info("Today's a sunny day"); + return new ResponseEntity<>("Today's a sunny day", HttpStatus.OK); + } + + private boolean isServiceUnavailable() { + return ++nrOfCalls % divisor != 0; + } +} diff --git a/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/src/main/resources/application.properties b/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/src/main/resources/application.properties new file mode 100644 index 0000000000..ea25e8f2da --- /dev/null +++ b/spring-cloud/spring-cloud-ribbon-retry/ribbon-weather-service/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.application.name=weather-service +successful.call.divisor=3 diff --git a/spring-cloud/spring-cloud-stream-starters/twitterhdfs/pom.xml b/spring-cloud/spring-cloud-stream-starters/twitterhdfs/pom.xml index 1cfbf7e7c8..c9a73b9aa1 100644 --- a/spring-cloud/spring-cloud-stream-starters/twitterhdfs/pom.xml +++ b/spring-cloud/spring-cloud-stream-starters/twitterhdfs/pom.xml @@ -9,10 +9,10 @@ jar - com.baeldung - parent-boot-1 - 0.0.1-SNAPSHOT - ../../../parent-boot-1 + org.springframework.boot + spring-boot-starter-parent + 2.1.13.RELEASE + @@ -32,6 +32,11 @@ javax.servlet jstl + + org.springframework.boot + spring-boot-starter-test + test + @@ -45,7 +50,7 @@ - 1.3.1.RELEASE + 2.1.2.RELEASE \ No newline at end of file diff --git a/spring-core-4/src/main/java/com/baeldung/beanpostprocessor/GlobalEventBus.java b/spring-core-4/src/main/java/com/baeldung/beanpostprocessor/GlobalEventBus.java index 8b3c528c4d..fff9eb8a0f 100644 --- a/spring-core-4/src/main/java/com/baeldung/beanpostprocessor/GlobalEventBus.java +++ b/spring-core-4/src/main/java/com/baeldung/beanpostprocessor/GlobalEventBus.java @@ -8,7 +8,7 @@ import java.util.concurrent.Executors; @SuppressWarnings("ALL") public final class GlobalEventBus { - public static final String GLOBAL_EVENT_BUS_EXPRESSION = "T(com.baeldung.postprocessor.GlobalEventBus).getEventBus()"; + public static final String GLOBAL_EVENT_BUS_EXPRESSION = "T(com.baeldung.beanpostprocessor.GlobalEventBus).getEventBus()"; private static final String IDENTIFIER = "global-event-bus"; diff --git a/spring-jooq/pom.xml b/spring-jooq/pom.xml index 63c6b5c8ee..c07d6278cb 100644 --- a/spring-jooq/pom.xml +++ b/spring-jooq/pom.xml @@ -73,6 +73,17 @@ + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + 0 + + + org.codehaus.mojo properties-maven-plugin diff --git a/spring-resttemplate-2/README.md b/spring-resttemplate-2/README.md new file mode 100644 index 0000000000..e0a394c642 --- /dev/null +++ b/spring-resttemplate-2/README.md @@ -0,0 +1,7 @@ +## Spring RestTemplate + +This module contains articles about Spring RestTemplate + +### Relevant Articles: + + diff --git a/spring-resttemplate-2/pom.xml b/spring-resttemplate-2/pom.xml new file mode 100644 index 0000000000..1a594fd21e --- /dev/null +++ b/spring-resttemplate-2/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + spring-resttemplate + 0.1-SNAPSHOT + spring-resttemplate-2 + war + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + + + + + + org.springframework + spring-web + + + commons-logging + commons-logging + + + + + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/RestTemplateConfigurationApplication.java b/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/RestTemplateConfigurationApplication.java new file mode 100644 index 0000000000..4fa14edda1 --- /dev/null +++ b/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/RestTemplateConfigurationApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.resttemplate.logging; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@EnableAutoConfiguration +public class RestTemplateConfigurationApplication { + + public static void main(String[] args) { + SpringApplication.run(RestTemplateConfigurationApplication.class, args); + } +} diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/web/controller/PersonController.java b/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/web/controller/PersonController.java new file mode 100644 index 0000000000..8436c52a4a --- /dev/null +++ b/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/web/controller/PersonController.java @@ -0,0 +1,17 @@ +package com.baeldung.resttemplate.logging.web.controller; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class PersonController { + + @PostMapping("/persons") + public List getPersons() { + return Arrays.asList(new String[] { "Lucie", "Jackie", "Danesh", "Tao" }); + } + +} \ No newline at end of file diff --git a/spring-resttemplate-2/src/main/resources/application.properties b/spring-resttemplate-2/src/main/resources/application.properties new file mode 100644 index 0000000000..ea4f7c866d --- /dev/null +++ b/spring-resttemplate-2/src/main/resources/application.properties @@ -0,0 +1,2 @@ +server.port=8080 +server.servlet.context-path=/spring-rest \ No newline at end of file diff --git a/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/LoggingInterceptor.java b/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/LoggingInterceptor.java new file mode 100644 index 0000000000..17ce390d8a --- /dev/null +++ b/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/LoggingInterceptor.java @@ -0,0 +1,29 @@ +package com.baeldung.resttemplate.logging; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; + +public class LoggingInterceptor implements ClientHttpRequestInterceptor { + + final static Logger log = LoggerFactory.getLogger(LoggingInterceptor.class); + + @Override + public ClientHttpResponse intercept(HttpRequest req, byte[] reqBody, ClientHttpRequestExecution ex) throws IOException { + log.debug("Request body: {}", new String(reqBody, StandardCharsets.UTF_8)); + ClientHttpResponse response = ex.execute(req, reqBody); + InputStreamReader isr = new InputStreamReader(response.getBody(), StandardCharsets.UTF_8); + String body = new BufferedReader(isr).lines() + .collect(Collectors.joining("\n")); + log.debug("Response body: {}", body); + return response; + } +} diff --git a/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/RestTemplateLoggingLiveTest.java b/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/RestTemplateLoggingLiveTest.java new file mode 100644 index 0000000000..99d0201eff --- /dev/null +++ b/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/RestTemplateLoggingLiveTest.java @@ -0,0 +1,50 @@ +package com.baeldung.resttemplate.logging; + +import static org.hamcrest.CoreMatchers.equalTo; + +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.CollectionUtils; +import org.springframework.web.client.RestTemplate; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class RestTemplateLoggingLiveTest { + + private static final String baseUrl = "http://localhost:8080/spring-rest"; + + @Test + public void givenHttpClientConfiguration_whenSendGetForRequestEntity_thenRequestResponseFullLog() { + + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); + + final ResponseEntity response = restTemplate.postForEntity(baseUrl + "/persons", "my request body", String.class); + assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + } + + @Test + public void givenLoggingInterceptorConfiguration_whenSendGetForRequestEntity_thenRequestResponseCustomLog() { + + RestTemplate restTemplate = new RestTemplate(); + List interceptors = restTemplate.getInterceptors(); + if (CollectionUtils.isEmpty(interceptors)) { + interceptors = new ArrayList<>(); + } + interceptors.add(new LoggingInterceptor()); + restTemplate.setInterceptors(interceptors); + + final ResponseEntity response = restTemplate.postForEntity(baseUrl + "/persons", "my request body", String.class); + assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + } +} diff --git a/spring-resttemplate-2/src/test/resources/application.properties b/spring-resttemplate-2/src/test/resources/application.properties new file mode 100644 index 0000000000..7bc9e56041 --- /dev/null +++ b/spring-resttemplate-2/src/test/resources/application.properties @@ -0,0 +1,5 @@ +logging.level.org.springframework.web.client.RestTemplate=DEBUG +logging.level.com.baeldung.resttemplate.logging.LoggingInterceptor=DEBUG +logging.level.org.apache.http=DEBUG +logging.level.httpclient.wire=DEBUG +logging.pattern.console=%20logger{20} - %msg%n diff --git a/spring-thymeleaf-3/README.md b/spring-thymeleaf-3/README.md index a8e234b067..de18771c1e 100644 --- a/spring-thymeleaf-3/README.md +++ b/spring-thymeleaf-3/README.md @@ -4,3 +4,4 @@ This module contains articles about Spring with Thymeleaf ## Relevant Articles: - [Add CSS and JS to Thymeleaf](https://www.baeldung.com/spring-thymeleaf-css-js) +- [Formatting Currencies in Spring Using Thymeleaf](https://www.baeldung.com/spring-thymeleaf-currencies) diff --git a/testing-modules/selenium-junit-testng/README.md b/testing-modules/selenium-junit-testng/README.md index 198247d7bf..8baddd3449 100644 --- a/testing-modules/selenium-junit-testng/README.md +++ b/testing-modules/selenium-junit-testng/README.md @@ -1,4 +1,6 @@ ### Relevant Articles: + - [Guide to Selenium with JUnit / TestNG](http://www.baeldung.com/java-selenium-with-junit-and-testng) - [Testing with Selenium/WebDriver and the Page Object Pattern](http://www.baeldung.com/selenium-webdriver-page-object) - [Using Cookies With Selenium WebDriver in Java](https://www.baeldung.com/java-selenium-webdriver-cookies) +- [Clicking Elements in Selenium using JavaScript](https://www.baeldung.com/java-selenium-javascript) diff --git a/testing-modules/testing-assertions/README.md b/testing-modules/testing-assertions/README.md new file mode 100644 index 0000000000..08e2e66062 --- /dev/null +++ b/testing-modules/testing-assertions/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Asserting Log Messages With JUnit](https://www.baeldung.com/junit-asserting-logs)