commit
d2b88c18ff
|
@ -85,3 +85,9 @@ transaction.log
|
||||||
*-shell.log
|
*-shell.log
|
||||||
|
|
||||||
apache-cxf/cxf-aegis/baeldung.xml
|
apache-cxf/cxf-aegis/baeldung.xml
|
||||||
|
testing-modules/report-*.json
|
||||||
|
|
||||||
|
libraries-2/*.db
|
||||||
|
|
||||||
|
# SDKMan
|
||||||
|
.sdkmanrc
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
package com.baeldung.jgrapht;
|
package com.baeldung.jgrapht;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
import org.jgrapht.ext.JGraphXAdapter;
|
import org.jgrapht.ext.JGraphXAdapter;
|
||||||
import org.jgrapht.graph.DefaultDirectedGraph;
|
import org.jgrapht.graph.DefaultDirectedGraph;
|
||||||
import org.jgrapht.graph.DefaultEdge;
|
import org.jgrapht.graph.DefaultEdge;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.mxgraph.layout.mxCircleLayout;
|
import com.mxgraph.layout.mxCircleLayout;
|
||||||
import com.mxgraph.layout.mxIGraphLayout;
|
import com.mxgraph.layout.mxIGraphLayout;
|
||||||
import com.mxgraph.util.mxCellRenderer;
|
import com.mxgraph.util.mxCellRenderer;
|
||||||
|
@ -20,7 +25,7 @@ public class GraphImageGenerationUnitTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void createGraph() throws IOException {
|
public void createGraph() throws IOException {
|
||||||
File imgFile = new File("src/test/resources/graph.png");
|
File imgFile = new File("src/test/resources/graph1.png");
|
||||||
imgFile.createNewFile();
|
imgFile.createNewFile();
|
||||||
g = new DefaultDirectedGraph<String, DefaultEdge>(DefaultEdge.class);
|
g = new DefaultDirectedGraph<String, DefaultEdge>(DefaultEdge.class);
|
||||||
String x1 = "x1";
|
String x1 = "x1";
|
||||||
|
@ -34,12 +39,18 @@ public class GraphImageGenerationUnitTest {
|
||||||
g.addEdge(x3, x1);
|
g.addEdge(x3, x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void cleanup() {
|
||||||
|
File imgFile = new File("src/test/resources/graph1.png");
|
||||||
|
imgFile.deleteOnExit();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenAdaptedGraph_whenWriteBufferedImage_ThenFileShouldExist() throws IOException {
|
public void givenAdaptedGraph_whenWriteBufferedImage_ThenFileShouldExist() throws IOException {
|
||||||
JGraphXAdapter<String, DefaultEdge> graphAdapter = new JGraphXAdapter<String, DefaultEdge>(g);
|
JGraphXAdapter<String, DefaultEdge> graphAdapter = new JGraphXAdapter<String, DefaultEdge>(g);
|
||||||
mxIGraphLayout layout = new mxCircleLayout(graphAdapter);
|
mxIGraphLayout layout = new mxCircleLayout(graphAdapter);
|
||||||
layout.execute(graphAdapter.getDefaultParent());
|
layout.execute(graphAdapter.getDefaultParent());
|
||||||
File imgFile = new File("src/test/resources/graph.png");
|
File imgFile = new File("src/test/resources/graph1.png");
|
||||||
BufferedImage image = mxCellRenderer.createBufferedImage(graphAdapter, null, 2, Color.WHITE, true, null);
|
BufferedImage image = mxCellRenderer.createBufferedImage(graphAdapter, null, 2, Color.WHITE, true, null);
|
||||||
ImageIO.write(image, "PNG", imgFile);
|
ImageIO.write(image, "PNG", imgFile);
|
||||||
assertTrue(imgFile.exists());
|
assertTrue(imgFile.exists());
|
||||||
|
|
|
@ -7,4 +7,6 @@
|
||||||
- [Efficiently Merge Sorted Java Sequences](https://www.baeldung.com/java-merge-sorted-sequences)
|
- [Efficiently Merge Sorted Java Sequences](https://www.baeldung.com/java-merge-sorted-sequences)
|
||||||
- [Introduction to Greedy Algorithms with Java](https://www.baeldung.com/java-greedy-algorithms)
|
- [Introduction to Greedy Algorithms with Java](https://www.baeldung.com/java-greedy-algorithms)
|
||||||
- [The Caesar Cipher in Java](https://www.baeldung.com/java-caesar-cipher)
|
- [The Caesar Cipher in Java](https://www.baeldung.com/java-caesar-cipher)
|
||||||
|
- [Implementing a 2048 Solver in Java](https://www.baeldung.com/2048-java-solver)
|
||||||
|
- [Finding Top K Elements in an Array](https://www.baeldung.com/java-array-top-elements)
|
||||||
- More articles: [[<-- prev]](/../algorithms-miscellaneous-5)
|
- More articles: [[<-- prev]](/../algorithms-miscellaneous-5)
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.baeldung.algorithms.linkedlist;
|
||||||
|
|
||||||
|
public class LinkedListReversal {
|
||||||
|
|
||||||
|
ListNode reverseList(ListNode head) {
|
||||||
|
ListNode previous = null;
|
||||||
|
ListNode current = head;
|
||||||
|
while (current != null) {
|
||||||
|
ListNode nextElement = current.getNext();
|
||||||
|
current.setNext(previous);
|
||||||
|
previous = current;
|
||||||
|
current = nextElement;
|
||||||
|
}
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListNode reverseListRecursive(ListNode head) {
|
||||||
|
if (head == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (head.getNext() == null) {
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
ListNode node = reverseListRecursive(head.getNext());
|
||||||
|
head.getNext().setNext(head);
|
||||||
|
head.setNext(null);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.algorithms.linkedlist;
|
||||||
|
|
||||||
|
public class ListNode {
|
||||||
|
|
||||||
|
private int data;
|
||||||
|
private ListNode next;
|
||||||
|
|
||||||
|
ListNode(int data) {
|
||||||
|
this.data = data;
|
||||||
|
this.next = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListNode getNext() {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(int data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNext(ListNode next) {
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package com.baeldung.algorithms.play2048;
|
package com.baeldung.algorithms.play2048;
|
||||||
|
|
||||||
public class Play2048 {
|
public class Play2048 {
|
||||||
private static final int SIZE = 3;
|
private static final int SIZE = 4;
|
||||||
private static final int INITIAL_NUMBERS = 2;
|
private static final int INITIAL_NUMBERS = 2;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.algorithms.topkelements;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BruteForceTopKElementsFinder implements TopKElementsFinder<Integer> {
|
||||||
|
|
||||||
|
public List<Integer> findTopK(List<Integer> input, int k) {
|
||||||
|
List<Integer> array = new ArrayList<>(input);
|
||||||
|
List<Integer> topKList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < k; i++) {
|
||||||
|
int maxIndex = 0;
|
||||||
|
|
||||||
|
for (int j = 1; j < array.size(); j++) {
|
||||||
|
if (array.get(j) > array.get(maxIndex)) {
|
||||||
|
maxIndex = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
topKList.add(array.remove(maxIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
return topKList;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.algorithms.topkelements;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
public class MaxHeapTopKElementsFinder implements TopKElementsFinder<Integer> {
|
||||||
|
|
||||||
|
public List<Integer> findTopK(List<Integer> input, int k) {
|
||||||
|
PriorityQueue<Integer> maxHeap = new PriorityQueue<>();
|
||||||
|
|
||||||
|
input.forEach(number -> {
|
||||||
|
maxHeap.add(number);
|
||||||
|
|
||||||
|
if (maxHeap.size() > k) {
|
||||||
|
maxHeap.poll();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
List<Integer> topKList = new ArrayList<>(maxHeap);
|
||||||
|
Collections.reverse(topKList);
|
||||||
|
|
||||||
|
return topKList;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.baeldung.algorithms.topkelements;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface TopKElementsFinder<T extends Comparable<T>> {
|
||||||
|
List<T> findTopK(List<T> input, int k);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.baeldung.algorithms.topkelements;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TreeSetTopKElementsFinder implements TopKElementsFinder<Integer> {
|
||||||
|
|
||||||
|
public List<Integer> findTopK(List<Integer> input, int k) {
|
||||||
|
Set<Integer> sortedSet = new TreeSet<>(Comparator.reverseOrder());
|
||||||
|
sortedSet.addAll(input);
|
||||||
|
|
||||||
|
return sortedSet.stream().limit(k).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.baeldung.algorithms.linkedlist;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
public class LinkedListReversalUnitTest {
|
||||||
|
@Test
|
||||||
|
public void givenLinkedList_whenIterativeReverse_thenOutputCorrectResult() {
|
||||||
|
ListNode head = constructLinkedList();
|
||||||
|
ListNode node = head;
|
||||||
|
for (int i = 1; i <= 5; i++) {
|
||||||
|
assertNotNull(node);
|
||||||
|
assertEquals(i, node.getData());
|
||||||
|
node = node.getNext();
|
||||||
|
}
|
||||||
|
LinkedListReversal reversal = new LinkedListReversal();
|
||||||
|
node = reversal.reverseList(head);
|
||||||
|
for (int i = 5; i >= 1; i--) {
|
||||||
|
assertNotNull(node);
|
||||||
|
assertEquals(i, node.getData());
|
||||||
|
node = node.getNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLinkedList_whenRecursiveReverse_thenOutputCorrectResult() {
|
||||||
|
ListNode head = constructLinkedList();
|
||||||
|
ListNode node = head;
|
||||||
|
for (int i = 1; i <= 5; i++) {
|
||||||
|
assertNotNull(node);
|
||||||
|
assertEquals(i, node.getData());
|
||||||
|
node = node.getNext();
|
||||||
|
}
|
||||||
|
LinkedListReversal reversal = new LinkedListReversal();
|
||||||
|
node = reversal.reverseListRecursive(head);
|
||||||
|
for (int i = 5; i >= 1; i--) {
|
||||||
|
assertNotNull(node);
|
||||||
|
assertEquals(i, node.getData());
|
||||||
|
node = node.getNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ListNode constructLinkedList() {
|
||||||
|
ListNode head = null;
|
||||||
|
ListNode tail = null;
|
||||||
|
for (int i = 1; i <= 5; i++) {
|
||||||
|
ListNode node = new ListNode(i);
|
||||||
|
if (head == null) {
|
||||||
|
head = node;
|
||||||
|
} else {
|
||||||
|
tail.setNext(node);
|
||||||
|
}
|
||||||
|
tail = node;
|
||||||
|
}
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.baeldung.algorithms.topkelements;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Java6Assertions.assertThat;
|
||||||
|
|
||||||
|
public class TopKElementsFinderUnitTest {
|
||||||
|
private final TopKElementsFinder<Integer> bruteForceFinder = new BruteForceTopKElementsFinder();
|
||||||
|
private final TopKElementsFinder<Integer> maxHeapFinder = new MaxHeapTopKElementsFinder();
|
||||||
|
private final TopKElementsFinder<Integer> treeSetFinder = new TreeSetTopKElementsFinder();
|
||||||
|
|
||||||
|
private final int k = 4;
|
||||||
|
private final List<Integer> distinctIntegers = Arrays.asList(1, 2, 3, 9, 7, 6, 12);
|
||||||
|
private final List<Integer> distinctIntegersTopK = Arrays.asList(9, 7, 6, 12);
|
||||||
|
private final List<Integer> nonDistinctIntegers = Arrays.asList(1, 2, 3, 3, 9, 9, 7, 6, 12);
|
||||||
|
private final List<Integer> nonDistinctIntegersTopK = Arrays.asList(9, 9, 7, 12);
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayDistinctIntegers_whenBruteForceFindTopK_thenReturnKLargest() {
|
||||||
|
assertThat(bruteForceFinder.findTopK(distinctIntegers, k)).containsOnlyElementsOf(distinctIntegersTopK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayDistinctIntegers_whenMaxHeapFindTopK_thenReturnKLargest() {
|
||||||
|
assertThat(maxHeapFinder.findTopK(distinctIntegers, k)).containsOnlyElementsOf(distinctIntegersTopK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayDistinctIntegers_whenTreeSetFindTopK_thenReturnKLargest() {
|
||||||
|
assertThat(treeSetFinder.findTopK(distinctIntegers, k)).containsOnlyElementsOf(distinctIntegersTopK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayNonDistinctIntegers_whenBruteForceFindTopK_thenReturnKLargest() {
|
||||||
|
assertThat(bruteForceFinder.findTopK(nonDistinctIntegers, k)).containsOnlyElementsOf(nonDistinctIntegersTopK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayNonDistinctIntegers_whenMaxHeapFindTopK_thenReturnKLargest() {
|
||||||
|
assertThat(maxHeapFinder.findTopK(nonDistinctIntegers, k)).containsOnlyElementsOf(nonDistinctIntegersTopK);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
This module contains articles about searching algorithms.
|
This module contains articles about searching algorithms.
|
||||||
|
|
||||||
### Relevant articles:
|
### Relevant articles:
|
||||||
|
|
||||||
- [Binary Search Algorithm in Java](https://www.baeldung.com/java-binary-search)
|
- [Binary Search Algorithm in Java](https://www.baeldung.com/java-binary-search)
|
||||||
- [Depth First Search in Java](https://www.baeldung.com/java-depth-first-search)
|
- [Depth First Search in Java](https://www.baeldung.com/java-depth-first-search)
|
||||||
- [Interpolation Search in Java](https://www.baeldung.com/java-interpolation-search)
|
- [Interpolation Search in Java](https://www.baeldung.com/java-interpolation-search)
|
||||||
|
@ -11,3 +12,4 @@ This module contains articles about searching algorithms.
|
||||||
- [Monte Carlo Tree Search for Tic-Tac-Toe Game](https://www.baeldung.com/java-monte-carlo-tree-search)
|
- [Monte Carlo Tree Search for Tic-Tac-Toe Game](https://www.baeldung.com/java-monte-carlo-tree-search)
|
||||||
- [Range Search Algorithm in Java](https://www.baeldung.com/java-range-search)
|
- [Range Search Algorithm in Java](https://www.baeldung.com/java-range-search)
|
||||||
- [Fast Pattern Matching of Strings Using Suffix Tree](https://www.baeldung.com/java-pattern-matching-suffix-tree)
|
- [Fast Pattern Matching of Strings Using Suffix Tree](https://www.baeldung.com/java-pattern-matching-suffix-tree)
|
||||||
|
- [Find the Kth Smallest Element in Two Sorted Arrays](https://www.baeldung.com/java-kth-smallest-element-in-sorted-arrays)
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
package com.baeldung.algorithms.kthsmallest;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import static java.lang.Math.max;
|
||||||
|
import static java.lang.Math.min;
|
||||||
|
|
||||||
|
public class KthSmallest {
|
||||||
|
|
||||||
|
public static int findKthSmallestElement(int k, int[] list1, int[] list2) throws NoSuchElementException, IllegalArgumentException {
|
||||||
|
|
||||||
|
checkInput(k, list1, list2);
|
||||||
|
|
||||||
|
// we are looking for the minimum value
|
||||||
|
if(k == 1) {
|
||||||
|
return min(list1[0], list2[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we are looking for the maximum value
|
||||||
|
if(list1.length + list2.length == k) {
|
||||||
|
return max(list1[list1.length-1], list2[list2.length-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// swap lists if needed to make sure we take at least one element from list1
|
||||||
|
if(k <= list2.length && list2[k-1] < list1[0]) {
|
||||||
|
int[] list1_ = list1;
|
||||||
|
list1 = list2;
|
||||||
|
list2 = list1_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// correct left boundary if k is bigger than the size of list2
|
||||||
|
int left = k < list2.length ? 0 : k - list2.length - 1;
|
||||||
|
|
||||||
|
// the inital right boundary cannot exceed the list1
|
||||||
|
int right = min(k-1, list1.length - 1);
|
||||||
|
|
||||||
|
int nElementsList1, nElementsList2;
|
||||||
|
|
||||||
|
// binary search
|
||||||
|
do {
|
||||||
|
nElementsList1 = ((left + right) / 2) + 1;
|
||||||
|
nElementsList2 = k - nElementsList1;
|
||||||
|
|
||||||
|
if(nElementsList2 > 0) {
|
||||||
|
if (list1[nElementsList1 - 1] > list2[nElementsList2 - 1]) {
|
||||||
|
right = nElementsList1 - 2;
|
||||||
|
} else {
|
||||||
|
left = nElementsList1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(!kthSmallesElementFound(list1, list2, nElementsList1, nElementsList2));
|
||||||
|
|
||||||
|
return nElementsList2 == 0 ? list1[nElementsList1-1] : max(list1[nElementsList1-1], list2[nElementsList2-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean kthSmallesElementFound(int[] list1, int[] list2, int nElementsList1, int nElementsList2) {
|
||||||
|
|
||||||
|
// we do not take any element from the second list
|
||||||
|
if(nElementsList2 < 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(list1[nElementsList1-1] == list2[nElementsList2-1]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nElementsList1 == list1.length) {
|
||||||
|
return list1[nElementsList1-1] <= list2[nElementsList2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nElementsList2 == list2.length) {
|
||||||
|
return list2[nElementsList2-1] <= list1[nElementsList1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return list1[nElementsList1-1] <= list2[nElementsList2] && list2[nElementsList2-1] <= list1[nElementsList1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void checkInput(int k, int[] list1, int[] list2) throws NoSuchElementException, IllegalArgumentException {
|
||||||
|
|
||||||
|
if(list1 == null || list2 == null || k < 1) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(list1.length == 0 || list2.length == 0) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(k > list1.length + list2.length) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getKthElementSorted(int[] list1, int[] list2, int k) {
|
||||||
|
|
||||||
|
int length1 = list1.length, length2 = list2.length;
|
||||||
|
int[] combinedArray = new int[length1 + length2];
|
||||||
|
System.arraycopy(list1, 0, combinedArray, 0, list1.length);
|
||||||
|
System.arraycopy(list2, 0, combinedArray, list1.length, list2.length);
|
||||||
|
Arrays.sort(combinedArray);
|
||||||
|
|
||||||
|
return combinedArray[k-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getKthElementMerge(int[] list1, int[] list2, int k) {
|
||||||
|
|
||||||
|
int i1 = 0, i2 = 0;
|
||||||
|
|
||||||
|
while(i1 < list1.length && i2 < list2.length && (i1 + i2) < k) {
|
||||||
|
if(list1[i1] < list2[i2]) {
|
||||||
|
i1++;
|
||||||
|
} else {
|
||||||
|
i2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((i1 + i2) < k) {
|
||||||
|
return i1 < list1.length ? list1[k - i2 - 1] : list2[k - i1 - 1];
|
||||||
|
} else if(i1 > 0 && i2 > 0) {
|
||||||
|
return Math.max(list1[i1-1], list2[i2-1]);
|
||||||
|
} else {
|
||||||
|
return i1 == 0 ? list2[i2-1] : list1[i1-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,288 @@
|
||||||
|
package com.baeldung.algorithms.kthsmallest;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.function.Executable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static com.baeldung.algorithms.kthsmallest.KthSmallest.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class KthSmallestUnitTest {
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class Exceptions {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_at_least_one_list_is_null_then_an_exception_is_thrown() {
|
||||||
|
|
||||||
|
Executable executable1 = () -> findKthSmallestElement(1, null, null);
|
||||||
|
Executable executable2 = () -> findKthSmallestElement(1, new int[]{2}, null);
|
||||||
|
Executable executable3 = () -> findKthSmallestElement(1, null, new int[]{2});
|
||||||
|
|
||||||
|
assertThrows(IllegalArgumentException.class, executable1);
|
||||||
|
assertThrows(IllegalArgumentException.class, executable2);
|
||||||
|
assertThrows(IllegalArgumentException.class, executable3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_at_least_one_list_is_empty_then_an_exception_is_thrown() {
|
||||||
|
|
||||||
|
Executable executable1 = () -> findKthSmallestElement(1, new int[]{}, new int[]{2});
|
||||||
|
Executable executable2 = () -> findKthSmallestElement(1, new int[]{2}, new int[]{});
|
||||||
|
Executable executable3 = () -> findKthSmallestElement(1, new int[]{}, new int[]{});
|
||||||
|
|
||||||
|
assertThrows(IllegalArgumentException.class, executable1);
|
||||||
|
assertThrows(IllegalArgumentException.class, executable2);
|
||||||
|
assertThrows(IllegalArgumentException.class, executable3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_smaller_than_0_then_an_exception_is_thrown() {
|
||||||
|
Executable executable1 = () -> findKthSmallestElement(-1, new int[]{2}, new int[]{2});
|
||||||
|
assertThrows(IllegalArgumentException.class, executable1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_smaller_than_1_then_an_exception_is_thrown() {
|
||||||
|
Executable executable1 = () -> findKthSmallestElement(0, new int[]{2}, new int[]{2});
|
||||||
|
assertThrows(IllegalArgumentException.class, executable1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_bigger_then_the_two_lists_then_an_exception_is_thrown() {
|
||||||
|
Executable executable1 = () -> findKthSmallestElement(6, new int[]{1, 5, 6}, new int[]{2, 5});
|
||||||
|
assertThrows(NoSuchElementException.class, executable1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class K_is_smaller_than_the_size_of_list1_and_the_size_of_list2 {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_1_then_the_smallest_element_is_returned_from_list1() {
|
||||||
|
int result = findKthSmallestElement(1, new int[]{2, 7}, new int[]{3, 5});
|
||||||
|
assertEquals(2, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_1_then_the_smallest_element_is_returned_list2() {
|
||||||
|
int result = findKthSmallestElement(1, new int[]{3, 5}, new int[]{2, 7});
|
||||||
|
assertEquals(2, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_kth_element_is_smallest_element_and_occurs_in_both_lists() {
|
||||||
|
int[] list1 = new int[]{1, 2, 3};
|
||||||
|
int[] list2 = new int[]{1, 2, 3};
|
||||||
|
int result = findKthSmallestElement(1, list1, list2);
|
||||||
|
assertEquals(1, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_kth_element_is_smallest_element_and_occurs_in_both_lists2() {
|
||||||
|
int[] list1 = new int[]{1, 2, 3};
|
||||||
|
int[] list2 = new int[]{1, 2, 3};
|
||||||
|
int result = findKthSmallestElement(2, list1, list2);
|
||||||
|
assertEquals(1, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_kth_element_is_largest_element_and_occurs_in_both_lists_1() {
|
||||||
|
int[] list1 = new int[]{1, 2, 3};
|
||||||
|
int[] list2 = new int[]{1, 2, 3};
|
||||||
|
int result = findKthSmallestElement(5, list1, list2);
|
||||||
|
assertEquals(3, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_kth_element_is_largest_element_and_occurs_in_both_lists_2() {
|
||||||
|
int[] list1 = new int[]{1, 2, 3};
|
||||||
|
int[] list2 = new int[]{1, 2, 3};
|
||||||
|
int result = findKthSmallestElement(6, list1, list2);
|
||||||
|
assertEquals(3, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_kth_element_and_occurs_in_both_lists() {
|
||||||
|
int[] list1 = new int[]{1, 2, 3};
|
||||||
|
int[] list2 = new int[]{0, 2, 3};
|
||||||
|
int result = findKthSmallestElement(3, list1, list2);
|
||||||
|
assertEquals(2, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void and_kth_element_is_in_first_list() {
|
||||||
|
int[] list1 = new int[]{1,2,3,4};
|
||||||
|
int[] list2 = new int[]{1,3,4,5};
|
||||||
|
int result = findKthSmallestElement(3, list1, list2);
|
||||||
|
assertEquals(2, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void and_kth_is_in_second_list() {
|
||||||
|
int[] list1 = new int[]{1,3,4,4};
|
||||||
|
int[] list2 = new int[]{1,2,4,5};
|
||||||
|
int result = findKthSmallestElement(3, list1, list2);
|
||||||
|
assertEquals(2, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void and_elements_in_first_list_are_all_smaller_than_second_list() {
|
||||||
|
int[] list1 = new int[]{1,3,7,9};
|
||||||
|
int[] list2 = new int[]{11,12,14,15};
|
||||||
|
int result = findKthSmallestElement(3, list1, list2);
|
||||||
|
assertEquals(7, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void and_elements_in_first_list_are_all_smaller_than_second_list2() {
|
||||||
|
int[] list1 = new int[]{1,3,7,9};
|
||||||
|
int[] list2 = new int[]{11,12,14,15};
|
||||||
|
int result = findKthSmallestElement(4, list1, list2);
|
||||||
|
assertEquals(9, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void and_only_elements_from_second_list_are_part_of_result() {
|
||||||
|
int[] list1 = new int[]{11,12,14,15};
|
||||||
|
int[] list2 = new int[]{1,3,7,9};
|
||||||
|
int result = findKthSmallestElement(3, list1, list2);
|
||||||
|
assertEquals(7, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void and_only_elements_from_second_list_are_part_of_result2() {
|
||||||
|
int[] list1 = new int[]{11,12,14,15};
|
||||||
|
int[] list2 = new int[]{1,3,7,9};
|
||||||
|
int result = findKthSmallestElement(4, list1, list2);
|
||||||
|
assertEquals(9, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class K_is_bigger_than_the_size_of_at_least_one_of_the_lists {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void k_is_smaller_than_list1_and_bigger_than_list2() {
|
||||||
|
int[] list1 = new int[]{1, 2, 3, 4, 7, 9};
|
||||||
|
int[] list2 = new int[]{1, 2, 3};
|
||||||
|
int result = findKthSmallestElement(5, list1, list2);
|
||||||
|
assertEquals(3, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void k_is_bigger_than_list1_and_smaller_than_list2() {
|
||||||
|
int[] list1 = new int[]{1, 2, 3};
|
||||||
|
int[] list2 = new int[]{1, 2, 3, 4, 7, 9};
|
||||||
|
int result = findKthSmallestElement(5, list1, list2);
|
||||||
|
assertEquals(3, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_bigger_than_the_size_of_both_lists_and_elements_in_second_list_are_all_smaller_than_first_list() {
|
||||||
|
int[] list1 = new int[]{9, 11, 13, 55};
|
||||||
|
int[] list2 = new int[]{1, 2, 3, 7};
|
||||||
|
int result = findKthSmallestElement(6, list1, list2);
|
||||||
|
assertEquals(11, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_bigger_than_the_size_of_both_lists_and_elements_in_second_list_are_all_bigger_than_first_list() {
|
||||||
|
int[] list1 = new int[]{1, 2, 3, 7};
|
||||||
|
int[] list2 = new int[]{9, 11, 13, 55};
|
||||||
|
int result = findKthSmallestElement(6, list1, list2);
|
||||||
|
assertEquals(11, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_bigger_than_the_size_of_both_lists() {
|
||||||
|
int[] list1 = new int[]{3, 7, 9, 11, 55};
|
||||||
|
int[] list2 = new int[]{1, 2, 3, 7, 13};
|
||||||
|
int result = findKthSmallestElement(7, list1, list2);
|
||||||
|
assertEquals(9, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_bigger_than_the_size_of_both_lists_and_list1_has_more_elements_than_list2() {
|
||||||
|
int[] list1 = new int[]{3, 7, 9, 11, 55, 77, 100, 200};
|
||||||
|
int[] list2 = new int[]{1, 2, 3, 7, 13};
|
||||||
|
int result = findKthSmallestElement(11, list1, list2);
|
||||||
|
assertEquals(77, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void max_test() {
|
||||||
|
int[] list1 = new int[]{100, 200};
|
||||||
|
int[] list2 = new int[]{1, 2, 3};
|
||||||
|
int result = findKthSmallestElement(4, list1, list2);
|
||||||
|
assertEquals(100, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void max_test2() {
|
||||||
|
int[] list1 = new int[]{100, 200};
|
||||||
|
int[] list2 = new int[]{1, 2, 3};
|
||||||
|
int result = findKthSmallestElement(5, list1, list2);
|
||||||
|
assertEquals(200, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_smaller_than_the_size_of_both_lists_and_kth_element_in_list2() {
|
||||||
|
int[] list1 = new int[]{1, 2, 5};
|
||||||
|
int[] list2 = new int[]{1, 3, 4, 7};
|
||||||
|
int result = findKthSmallestElement(4, list1, list2);
|
||||||
|
assertEquals(3, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_smaller_than_the_size_of_both_lists_and_kth_element_is_smallest_in_list2() {
|
||||||
|
int[] list1 = new int[]{1, 2, 5};
|
||||||
|
int[] list2 = new int[]{3, 4, 7};
|
||||||
|
int result = findKthSmallestElement(3, list1, list2);
|
||||||
|
assertEquals(3, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void when_k_is_smaller_than_the_size_of_both_lists_and_kth_element_is_smallest_in_list23() {
|
||||||
|
int[] list1 = new int[]{3, 11, 27, 53, 90};
|
||||||
|
int[] list2 = new int[]{4, 20, 21, 100};
|
||||||
|
int result = findKthSmallestElement(5, list1, list2);
|
||||||
|
assertEquals(21, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
// public void randomTests() {
|
||||||
|
// IntStream.range(1, 100000).forEach(i -> random());
|
||||||
|
// }
|
||||||
|
|
||||||
|
private void random() {
|
||||||
|
|
||||||
|
Random random = new Random();
|
||||||
|
int length1 = (Math.abs(random.nextInt())) % 1000 + 1;
|
||||||
|
int length2 = (Math.abs(random.nextInt())) % 1000 + 1;
|
||||||
|
|
||||||
|
int[] list1 = sortedRandomIntArrayOfLength(length1);
|
||||||
|
int[] list2 = sortedRandomIntArrayOfLength(length2);
|
||||||
|
|
||||||
|
int k = (Math.abs(random.nextInt()) % (length1 + length2)) + 1 ;
|
||||||
|
|
||||||
|
int result = findKthSmallestElement(k, list1, list2);
|
||||||
|
|
||||||
|
int result2 = getKthElementSorted(list1, list2, k);
|
||||||
|
|
||||||
|
int result3 = getKthElementMerge(list1, list2, k);
|
||||||
|
|
||||||
|
assertEquals(result2, result);
|
||||||
|
assertEquals(result2, result3);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] sortedRandomIntArrayOfLength(int length) {
|
||||||
|
int[] intArray = new Random().ints(length).toArray();
|
||||||
|
Arrays.sort(intArray);
|
||||||
|
return intArray;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,4 +7,3 @@ This module contains articles about Apache CXF
|
||||||
- [Apache CXF Support for RESTful Web Services](https://www.baeldung.com/apache-cxf-rest-api)
|
- [Apache CXF Support for RESTful Web Services](https://www.baeldung.com/apache-cxf-rest-api)
|
||||||
- [A Guide to Apache CXF with Spring](https://www.baeldung.com/apache-cxf-with-spring)
|
- [A Guide to Apache CXF with Spring](https://www.baeldung.com/apache-cxf-with-spring)
|
||||||
- [Introduction to Apache CXF](https://www.baeldung.com/introduction-to-apache-cxf)
|
- [Introduction to Apache CXF](https://www.baeldung.com/introduction-to-apache-cxf)
|
||||||
- [Server-Sent Events (SSE) In JAX-RS](https://www.baeldung.com/java-ee-jax-rs-sse)
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
### Relevant Articles:
|
||||||
|
|
||||||
|
- [Server-Sent Events (SSE) In JAX-RS](https://www.baeldung.com/java-ee-jax-rs-sse)
|
|
@ -2,7 +2,7 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>apache-miscellaneous-1</artifactId>
|
<artifactId>apache-libraries</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<name>apache-libraries</name>
|
<name>apache-libraries</name>
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
This module contains articles about Apache POI
|
This module contains articles about Apache POI
|
||||||
|
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
|
||||||
- [Microsoft Word Processing in Java with Apache POI](https://www.baeldung.com/java-microsoft-word-with-apache-poi)
|
- [Microsoft Word Processing in Java with Apache POI](https://www.baeldung.com/java-microsoft-word-with-apache-poi)
|
||||||
- [Working with Microsoft Excel in Java](https://www.baeldung.com/java-microsoft-excel)
|
- [Working with Microsoft Excel in Java](https://www.baeldung.com/java-microsoft-excel)
|
||||||
- [Creating a MS PowerPoint Presentation in Java](https://www.baeldung.com/apache-poi-slideshow)
|
- [Creating a MS PowerPoint Presentation in Java](https://www.baeldung.com/apache-poi-slideshow)
|
||||||
- [Merge Cells in Excel Using Apache POI](https://www.baeldung.com/java-apache-poi-merge-cells)
|
- [Merge Cells in Excel Using Apache POI](https://www.baeldung.com/java-apache-poi-merge-cells)
|
||||||
- [Get String Value of Excel Cell with Apache POI](https://www.baeldung.com/java-apache-poi-cell-string-value)
|
- [Get String Value of Excel Cell with Apache POI](https://www.baeldung.com/java-apache-poi-cell-string-value)
|
||||||
- [Read Excel Cell Value Rather Than Formula With Apache POI](https://www.baeldung.com/apache-poi-read-cell-value-formula)
|
- [Read Excel Cell Value Rather Than Formula With Apache POI](https://www.baeldung.com/apache-poi-read-cell-value-formula)
|
||||||
|
- [Setting Formulas in Excel with Apache POI](https://www.baeldung.com/java-apache-poi-set-formulas)
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.poi.excel.setformula;
|
||||||
|
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFCell;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ExcelFormula {
|
||||||
|
public double setFormula(String fileLocation, XSSFWorkbook wb, String formula) throws IOException {
|
||||||
|
XSSFSheet sheet = wb.getSheetAt(0);
|
||||||
|
int lastCellNum = sheet.getRow(0).getLastCellNum();
|
||||||
|
XSSFCell formulaCell = sheet.getRow(0).createCell(lastCellNum);
|
||||||
|
formulaCell.setCellFormula(formula);
|
||||||
|
XSSFFormulaEvaluator formulaEvaluator = wb.getCreationHelper().createFormulaEvaluator();
|
||||||
|
formulaEvaluator.evaluateFormulaCell(formulaCell);
|
||||||
|
FileOutputStream fileOut = new FileOutputStream(new File(fileLocation));
|
||||||
|
wb.write(fileOut);
|
||||||
|
wb.close();
|
||||||
|
fileOut.close();
|
||||||
|
return formulaCell.getNumericCellValue();
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,51 @@
|
||||||
|
package com.baeldung.poi.excel.setformula;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.util.CellReference;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
class ExcelFormulaUnitTest {
|
||||||
|
private static String FILE_NAME = "com/baeldung/poi/excel/setformula/SetFormulaTest.xlsx";
|
||||||
|
private String fileLocation;
|
||||||
|
private ExcelFormula excelFormula;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() throws URISyntaxException {
|
||||||
|
fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME).toURI()).toString();
|
||||||
|
excelFormula = new ExcelFormula();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenExcelData_whenSetFormula_thenSuccess() throws IOException {
|
||||||
|
FileInputStream inputStream = new FileInputStream(new File(fileLocation));
|
||||||
|
XSSFWorkbook wb = new XSSFWorkbook(inputStream);
|
||||||
|
XSSFSheet sheet = wb.getSheetAt(0);
|
||||||
|
double resultColumnA = 0;
|
||||||
|
double resultColumnB = 0;
|
||||||
|
for (int row = 0; row <= sheet.getLastRowNum(); row++) {
|
||||||
|
resultColumnA += sheet.getRow(row).getCell(0).getNumericCellValue();
|
||||||
|
resultColumnB += sheet.getRow(row).getCell(1).getNumericCellValue();
|
||||||
|
}
|
||||||
|
String colNameA = CellReference.convertNumToColString(0);
|
||||||
|
String colNameB = CellReference.convertNumToColString(1);
|
||||||
|
String startCellA = colNameA + 1;
|
||||||
|
String stopCellA = colNameA + (sheet.getLastRowNum() + 1);
|
||||||
|
String sumFormulaForColumnA = String.format("SUM(%s:%s)", startCellA, stopCellA);
|
||||||
|
String startCellB = colNameB + 1;
|
||||||
|
String stopCellB = colNameB + (sheet.getLastRowNum() + 1);
|
||||||
|
String sumFormulaForColumnB = String.format("SUM(%s:%s)", startCellB, stopCellB);
|
||||||
|
|
||||||
|
double resultValue = excelFormula.setFormula(fileLocation, wb, sumFormulaForColumnA + "-" + sumFormulaForColumnB);
|
||||||
|
|
||||||
|
Assert.assertEquals(resultColumnA - resultColumnB, resultValue, 0d);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,4 +6,4 @@ This module contains articles about Apache Shiro
|
||||||
|
|
||||||
- [Introduction to Apache Shiro](https://www.baeldung.com/apache-shiro)
|
- [Introduction to Apache Shiro](https://www.baeldung.com/apache-shiro)
|
||||||
- [Permissions-Based Access Control with Apache Shiro](https://www.baeldung.com/apache-shiro-access-control)
|
- [Permissions-Based Access Control with Apache Shiro](https://www.baeldung.com/apache-shiro-access-control)
|
||||||
|
- [Spring Security vs Apache Shiro](https://www.baeldung.com/spring-security-vs-apache-shiro)
|
||||||
|
|
|
@ -39,10 +39,19 @@
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
<artifactId>jcl-over-slf4j</artifactId>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- spring-sec -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<apache-shiro-core-version>1.4.0</apache-shiro-core-version>
|
<apache-shiro-core-version>1.5.3</apache-shiro-core-version>
|
||||||
<log4j-version>1.2.17</log4j-version>
|
<log4j-version>1.2.17</log4j-version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package com.baeldung.comparison.shiro;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.shiro.authc.AuthenticationException;
|
||||||
|
import org.apache.shiro.authc.AuthenticationInfo;
|
||||||
|
import org.apache.shiro.authc.AuthenticationToken;
|
||||||
|
import org.apache.shiro.authc.SimpleAuthenticationInfo;
|
||||||
|
import org.apache.shiro.authc.UnknownAccountException;
|
||||||
|
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||||
|
import org.apache.shiro.authz.AuthorizationInfo;
|
||||||
|
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||||
|
import org.apache.shiro.realm.jdbc.JdbcRealm;
|
||||||
|
import org.apache.shiro.subject.PrincipalCollection;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class CustomRealm extends JdbcRealm {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(CustomRealm.class);
|
||||||
|
|
||||||
|
private Map<String, String> credentials = new HashMap<>();
|
||||||
|
private Map<String, Set<String>> roles = new HashMap<>();
|
||||||
|
private Map<String, Set<String>> permissions = new HashMap<>();
|
||||||
|
|
||||||
|
{
|
||||||
|
credentials.put("Tom", "password");
|
||||||
|
credentials.put("Jerry", "password");
|
||||||
|
|
||||||
|
roles.put("Jerry", new HashSet<>(Arrays.asList("ADMIN")));
|
||||||
|
roles.put("Tom", new HashSet<>(Arrays.asList("USER")));
|
||||||
|
|
||||||
|
permissions.put("ADMIN", new HashSet<>(Arrays.asList("READ", "WRITE")));
|
||||||
|
permissions.put("USER", new HashSet<>(Arrays.asList("READ")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
|
||||||
|
|
||||||
|
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
|
||||||
|
|
||||||
|
if (userToken.getUsername() == null || userToken.getUsername()
|
||||||
|
.isEmpty() || !credentials.containsKey(userToken.getUsername())) {
|
||||||
|
throw new UnknownAccountException("User doesn't exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SimpleAuthenticationInfo(userToken.getUsername(), credentials.get(userToken.getUsername()), getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
|
||||||
|
Set<String> roles = new HashSet<>();
|
||||||
|
Set<String> permissions = new HashSet<>();
|
||||||
|
|
||||||
|
for (Object user : principals) {
|
||||||
|
try {
|
||||||
|
roles.addAll(getRoleNamesForUser(null, (String) user));
|
||||||
|
permissions.addAll(getPermissions(null, null, roles));
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logger.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SimpleAuthorizationInfo authInfo = new SimpleAuthorizationInfo(roles);
|
||||||
|
authInfo.setStringPermissions(permissions);
|
||||||
|
return authInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Set<String> getRoleNamesForUser(Connection conn, String username) throws SQLException {
|
||||||
|
if (!roles.containsKey(username)) {
|
||||||
|
throw new SQLException("User doesn't exist");
|
||||||
|
}
|
||||||
|
return roles.get(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Set<String> getPermissions(Connection conn, String username, Collection<String> roles) throws SQLException {
|
||||||
|
Set<String> userPermissions = new HashSet<>();
|
||||||
|
|
||||||
|
for (String role : roles) {
|
||||||
|
if (!permissions.containsKey(role)) {
|
||||||
|
throw new SQLException("Role doesn't exist");
|
||||||
|
}
|
||||||
|
userPermissions.addAll(permissions.get(role));
|
||||||
|
}
|
||||||
|
return userPermissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.comparison.shiro;
|
||||||
|
|
||||||
|
import org.apache.shiro.realm.Realm;
|
||||||
|
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
|
||||||
|
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
|
||||||
|
public class ShiroApplication {
|
||||||
|
|
||||||
|
public static void main(String... args) {
|
||||||
|
SpringApplication.run(ShiroApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Realm customRealm() {
|
||||||
|
return new CustomRealm();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
|
||||||
|
DefaultShiroFilterChainDefinition filter = new DefaultShiroFilterChainDefinition();
|
||||||
|
|
||||||
|
filter.addPathDefinition("/home", "authc");
|
||||||
|
filter.addPathDefinition("/**", "anon");
|
||||||
|
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.baeldung.comparison.shiro.controllers;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.apache.shiro.authc.AuthenticationException;
|
||||||
|
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||||
|
import org.apache.shiro.subject.Subject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||||
|
|
||||||
|
import com.baeldung.comparison.shiro.models.UserCredentials;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class ShiroController {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(ShiroController.class);
|
||||||
|
|
||||||
|
@GetMapping("/")
|
||||||
|
public String getIndex() {
|
||||||
|
return "comparison/index";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/login")
|
||||||
|
public String showLoginPage() {
|
||||||
|
return "comparison/login";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/login")
|
||||||
|
public String doLogin(HttpServletRequest req, UserCredentials credentials, RedirectAttributes attr) {
|
||||||
|
|
||||||
|
Subject subject = SecurityUtils.getSubject();
|
||||||
|
|
||||||
|
if (!subject.isAuthenticated()) {
|
||||||
|
UsernamePasswordToken token = new UsernamePasswordToken(credentials.getUsername(), credentials.getPassword());
|
||||||
|
try {
|
||||||
|
subject.login(token);
|
||||||
|
} catch (AuthenticationException ae) {
|
||||||
|
logger.error(ae.getMessage());
|
||||||
|
attr.addFlashAttribute("error", "Invalid Credentials");
|
||||||
|
return "redirect:/login";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "redirect:/home";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/home")
|
||||||
|
public String getMeHome(Model model) {
|
||||||
|
|
||||||
|
addUserAttributes(model);
|
||||||
|
|
||||||
|
return "comparison/home";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/admin")
|
||||||
|
public String adminOnly(Model model) {
|
||||||
|
addUserAttributes(model);
|
||||||
|
|
||||||
|
Subject currentUser = SecurityUtils.getSubject();
|
||||||
|
if (currentUser.hasRole("ADMIN")) {
|
||||||
|
model.addAttribute("adminContent", "only admin can view this");
|
||||||
|
}
|
||||||
|
return "comparison/home";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/logout")
|
||||||
|
public String logout() {
|
||||||
|
Subject subject = SecurityUtils.getSubject();
|
||||||
|
subject.logout();
|
||||||
|
return "redirect:/";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addUserAttributes(Model model) {
|
||||||
|
Subject currentUser = SecurityUtils.getSubject();
|
||||||
|
String permission = "";
|
||||||
|
|
||||||
|
if (currentUser.hasRole("ADMIN")) {
|
||||||
|
model.addAttribute("role", "ADMIN");
|
||||||
|
} else if (currentUser.hasRole("USER")) {
|
||||||
|
model.addAttribute("role", "USER");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentUser.isPermitted("READ")) {
|
||||||
|
permission = permission + " READ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentUser.isPermitted("WRITE")) {
|
||||||
|
permission = permission + " WRITE";
|
||||||
|
}
|
||||||
|
model.addAttribute("username", currentUser.getPrincipal());
|
||||||
|
model.addAttribute("permission", permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.comparison.shiro.models;
|
||||||
|
|
||||||
|
public class UserCredentials {
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "username = " + getUsername();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.comparison.springsecurity;
|
||||||
|
|
||||||
|
import org.apache.shiro.spring.boot.autoconfigure.ShiroAnnotationProcessorAutoConfiguration;
|
||||||
|
import org.apache.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration;
|
||||||
|
import org.apache.shiro.spring.config.web.autoconfigure.ShiroWebAutoConfiguration;
|
||||||
|
import org.apache.shiro.spring.config.web.autoconfigure.ShiroWebFilterConfiguration;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication(exclude = {ShiroAutoConfiguration.class,
|
||||||
|
ShiroAnnotationProcessorAutoConfiguration.class,
|
||||||
|
ShiroWebAutoConfiguration.class,
|
||||||
|
ShiroWebFilterConfiguration.class})
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.baeldung.comparison.springsecurity.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
http.csrf().disable().authorizeRequests(authorize -> authorize.antMatchers("/index", "/login")
|
||||||
|
.permitAll()
|
||||||
|
.antMatchers("/home", "/logout")
|
||||||
|
.authenticated()
|
||||||
|
.antMatchers("/admin/**")
|
||||||
|
.hasRole("ADMIN"))
|
||||||
|
.formLogin(formLogin -> formLogin.loginPage("/login")
|
||||||
|
.failureUrl("/login-error"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||||
|
auth.inMemoryAuthentication()
|
||||||
|
.withUser("Jerry")
|
||||||
|
.password(passwordEncoder().encode("password"))
|
||||||
|
.authorities("READ", "WRITE")
|
||||||
|
.roles("ADMIN")
|
||||||
|
.and()
|
||||||
|
.withUser("Tom")
|
||||||
|
.password(passwordEncoder().encode("password"))
|
||||||
|
.authorities("READ")
|
||||||
|
.roles("USER");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package com.baeldung.comparison.springsecurity.web;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class SpringController {
|
||||||
|
|
||||||
|
@GetMapping("/")
|
||||||
|
public String getIndex() {
|
||||||
|
return "comparison/index";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/login")
|
||||||
|
public String showLoginPage() {
|
||||||
|
return "comparison/login";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/login-error")
|
||||||
|
public String loginError(Model model) {
|
||||||
|
model.addAttribute("error", "Invalid Credentials");
|
||||||
|
return "comparison/login";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/login")
|
||||||
|
public String doLogin(HttpServletRequest req) {
|
||||||
|
return "redirect:/home";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/home")
|
||||||
|
public String showHomePage(HttpServletRequest req, Model model) {
|
||||||
|
addUserAttributes(model);
|
||||||
|
return "comparison/home";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/admin")
|
||||||
|
public String adminOnly(HttpServletRequest req, Model model) {
|
||||||
|
addUserAttributes(model);
|
||||||
|
model.addAttribute("adminContent", "only admin can view this");
|
||||||
|
return "comparison/home";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addUserAttributes(Model model) {
|
||||||
|
Authentication auth = SecurityContextHolder.getContext()
|
||||||
|
.getAuthentication();
|
||||||
|
if (auth != null && !auth.getClass()
|
||||||
|
.equals(AnonymousAuthenticationToken.class)) {
|
||||||
|
User user = (User) auth.getPrincipal();
|
||||||
|
model.addAttribute("username", user.getUsername());
|
||||||
|
|
||||||
|
Collection<GrantedAuthority> authorities = user.getAuthorities();
|
||||||
|
|
||||||
|
for (GrantedAuthority authority : authorities) {
|
||||||
|
if (authority.getAuthority()
|
||||||
|
.contains("USER")) {
|
||||||
|
model.addAttribute("role", "USER");
|
||||||
|
model.addAttribute("permission", "READ");
|
||||||
|
} else if (authority.getAuthority()
|
||||||
|
.contains("ADMIN")) {
|
||||||
|
model.addAttribute("role", "ADMIN");
|
||||||
|
model.addAttribute("permission", "READ WRITE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung;
|
package com.baeldung.intro;
|
||||||
|
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.apache.shiro.authc.AuthenticationException;
|
import org.apache.shiro.authc.AuthenticationException;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung;
|
package com.baeldung.intro;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung;
|
package com.baeldung.intro;
|
||||||
|
|
||||||
import org.apache.shiro.realm.Realm;
|
import org.apache.shiro.realm.Realm;
|
||||||
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
|
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
|
||||||
|
@ -7,12 +7,13 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by smatt on 21/08/2017.
|
* Created by smatt on 21/08/2017.
|
||||||
*/
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
|
||||||
public class ShiroSpringApplication {
|
public class ShiroSpringApplication {
|
||||||
|
|
||||||
private static final transient Logger log = LoggerFactory.getLogger(ShiroSpringApplication.class);
|
private static final transient Logger log = LoggerFactory.getLogger(ShiroSpringApplication.class);
|
||||||
|
@ -29,7 +30,7 @@ public class ShiroSpringApplication {
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
|
public ShiroFilterChainDefinition filterChainDefinition() {
|
||||||
DefaultShiroFilterChainDefinition filter
|
DefaultShiroFilterChainDefinition filter
|
||||||
= new DefaultShiroFilterChainDefinition();
|
= new DefaultShiroFilterChainDefinition();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.baeldung.controllers;
|
package com.baeldung.intro.controllers;
|
||||||
|
|
||||||
import com.baeldung.models.UserCredentials;
|
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.apache.shiro.authc.AuthenticationException;
|
import org.apache.shiro.authc.AuthenticationException;
|
||||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||||
|
@ -13,6 +12,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||||
|
|
||||||
|
import com.baeldung.intro.models.UserCredentials;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.models;
|
package com.baeldung.intro.models;
|
||||||
|
|
||||||
public class UserCredentials {
|
public class UserCredentials {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.shiro.permissions.custom;
|
package com.baeldung.permissions.custom;
|
||||||
|
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.apache.shiro.authc.AuthenticationException;
|
import org.apache.shiro.authc.AuthenticationException;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.shiro.permissions.custom;
|
package com.baeldung.permissions.custom;
|
||||||
|
|
||||||
import org.apache.shiro.authz.Permission;
|
import org.apache.shiro.authz.Permission;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.shiro.permissions.custom;
|
package com.baeldung.permissions.custom;
|
||||||
|
|
||||||
import org.apache.shiro.authz.Permission;
|
import org.apache.shiro.authz.Permission;
|
||||||
import org.apache.shiro.authz.permission.PermissionResolver;
|
import org.apache.shiro.authz.permission.PermissionResolver;
|
|
@ -0,0 +1,19 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Home Page</title>
|
||||||
|
</head>
|
||||||
|
<body style="margin-left: 30px;">
|
||||||
|
<h1>Welcome ${username}!</h1>
|
||||||
|
<p><strong>Role</strong>: ${role}</p>
|
||||||
|
<p><strong>Permissions</strong></p>
|
||||||
|
<p>${permission}</p>
|
||||||
|
<a href="/admin">Admin only</a>
|
||||||
|
<#if adminContent??>
|
||||||
|
${adminContent}
|
||||||
|
</#if>
|
||||||
|
<br>
|
||||||
|
<form role="form" action="/logout" method="POST">
|
||||||
|
<input type="Submit" value="Logout" />
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Index</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Welcome Guest!</h1>
|
||||||
|
<br>
|
||||||
|
Go to the <a href="/home">secured page
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Login</title>
|
||||||
|
</head>
|
||||||
|
<body style="margin-left: 30px;">
|
||||||
|
<h3>Login</h3>
|
||||||
|
<br>
|
||||||
|
<form action="/login" method="post">
|
||||||
|
<#if (error?length > 0)??>
|
||||||
|
<p style="color:darkred;">${error}</p>
|
||||||
|
<#else>
|
||||||
|
</#if>
|
||||||
|
|
||||||
|
<label for="username">Username</label>
|
||||||
|
<br>
|
||||||
|
<input type="text" name="username">
|
||||||
|
<br><br>
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<br>
|
||||||
|
<input type="password" name="password">
|
||||||
|
<br><br>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.comparison.shiro;
|
||||||
|
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
|
||||||
|
import com.baeldung.comparison.shiro.ShiroApplication;
|
||||||
|
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@SpringBootTest(classes = { ShiroApplication.class })
|
||||||
|
public class SpringContextTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.comparison.springsecurity;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
|
||||||
|
import com.baeldung.comparison.springsecurity.Application;
|
||||||
|
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@SpringBootTest(classes = { Application.class })
|
||||||
|
public class SpringContextTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -74,6 +74,7 @@
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<version>3.3.0</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
|
|
|
@ -13,10 +13,6 @@
|
||||||
<relativePath>../parent-boot-2</relativePath>
|
<relativePath>../parent-boot-2</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<java.version>1.8</java.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -5,3 +5,4 @@ This module contains articles about AWS Lambda
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [Using AWS Lambda with API Gateway](https://www.baeldung.com/aws-lambda-api-gateway)
|
- [Using AWS Lambda with API Gateway](https://www.baeldung.com/aws-lambda-api-gateway)
|
||||||
- [Introduction to AWS Serverless Application Model](https://www.baeldung.com/aws-serverless)
|
- [Introduction to AWS Serverless Application Model](https://www.baeldung.com/aws-serverless)
|
||||||
|
- [How to Implement Hibernate in an AWS Lambda Function in Java](https://www.baeldung.com/java-aws-lambda-hibernate)
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>aws-lambda-examples</artifactId>
|
||||||
|
<version>0.1.0-SNAPSHOT</version>
|
||||||
|
<name>aws-lambda-examples</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../../</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.amazonaws</groupId>
|
||||||
|
<artifactId>aws-java-sdk-dynamodb</artifactId>
|
||||||
|
<version>${aws-java-sdk.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.amazonaws</groupId>
|
||||||
|
<artifactId>aws-java-sdk-core</artifactId>
|
||||||
|
<version>${aws-java-sdk.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.amazonaws</groupId>
|
||||||
|
<artifactId>aws-lambda-java-core</artifactId>
|
||||||
|
<version>${aws-lambda-java-core.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.amazonaws</groupId>
|
||||||
|
<artifactId>aws-lambda-java-events</artifactId>
|
||||||
|
<version>${aws-lambda-java-events.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>${gson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>${commons-io.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.json-simple</groupId>
|
||||||
|
<artifactId>json-simple</artifactId>
|
||||||
|
<version>${json-simple.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>${maven-shade-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<json-simple.version>1.1.1</json-simple.version>
|
||||||
|
<commons-io.version>2.5</commons-io.version>
|
||||||
|
<aws-lambda-java-events.version>1.3.0</aws-lambda-java-events.version>
|
||||||
|
<aws-lambda-java-core.version>1.2.0</aws-lambda-java-core.version>
|
||||||
|
<gson.version>2.8.2</gson.version>
|
||||||
|
<aws-java-sdk.version>1.11.241</aws-java-sdk.version>
|
||||||
|
<maven-shade-plugin.version>3.0.0</maven-shade-plugin.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -5,95 +5,19 @@
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>aws-lambda</artifactId>
|
<artifactId>aws-lambda</artifactId>
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
|
||||||
<name>aws-lambda</name>
|
<name>aws-lambda</name>
|
||||||
<packaging>jar</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<modules>
|
||||||
<dependency>
|
<module>lambda</module>
|
||||||
<groupId>com.amazonaws</groupId>
|
<module>shipping-tracker/ShippingFunction</module>
|
||||||
<artifactId>aws-java-sdk-dynamodb</artifactId>
|
</modules>
|
||||||
<version>${aws-java-sdk.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.amazonaws</groupId>
|
|
||||||
<artifactId>aws-java-sdk-core</artifactId>
|
|
||||||
<version>${aws-java-sdk.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.amazonaws</groupId>
|
|
||||||
<artifactId>aws-lambda-java-core</artifactId>
|
|
||||||
<version>${aws-lambda-java-core.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>commons-logging</artifactId>
|
|
||||||
<groupId>commons-logging</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.amazonaws</groupId>
|
|
||||||
<artifactId>aws-lambda-java-events</artifactId>
|
|
||||||
<version>${aws-lambda-java-events.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>commons-logging</artifactId>
|
|
||||||
<groupId>commons-logging</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.gson</groupId>
|
|
||||||
<artifactId>gson</artifactId>
|
|
||||||
<version>${gson.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-io</groupId>
|
|
||||||
<artifactId>commons-io</artifactId>
|
|
||||||
<version>${commons-io.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.googlecode.json-simple</groupId>
|
|
||||||
<artifactId>json-simple</artifactId>
|
|
||||||
<version>${json-simple.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
</project>
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>${maven-shade-plugin.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<json-simple.version>1.1.1</json-simple.version>
|
|
||||||
<commons-io.version>2.5</commons-io.version>
|
|
||||||
<aws-lambda-java-events.version>1.3.0</aws-lambda-java-events.version>
|
|
||||||
<aws-lambda-java-core.version>1.2.0</aws-lambda-java-core.version>
|
|
||||||
<gson.version>2.8.2</gson.version>
|
|
||||||
<aws-java-sdk.version>1.11.241</aws-java-sdk.version>
|
|
||||||
<maven-shade-plugin.version>3.0.0</maven-shade-plugin.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
.aws-sam/
|
|
@ -0,0 +1,73 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>ShippingFunction</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>Shipping Tracker Lambda Function</name>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<hibernate.version>5.4.21.Final</hibernate.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.amazonaws</groupId>
|
||||||
|
<artifactId>aws-lambda-java-core</artifactId>
|
||||||
|
<version>1.2.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.amazonaws</groupId>
|
||||||
|
<artifactId>aws-lambda-java-events</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
<version>2.11.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-core</artifactId>
|
||||||
|
<version>${hibernate.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-hikaricp</artifactId>
|
||||||
|
<version>${hibernate.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>42.2.16</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.1.1</version>
|
||||||
|
<configuration>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,108 @@
|
||||||
|
package com.baeldung.lambda.shipping;
|
||||||
|
|
||||||
|
import com.amazonaws.services.lambda.runtime.Context;
|
||||||
|
import com.amazonaws.services.lambda.runtime.RequestHandler;
|
||||||
|
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
|
||||||
|
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.*;
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.PASS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for requests to Lambda function.
|
||||||
|
*/
|
||||||
|
public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
|
||||||
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
|
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
|
||||||
|
try (SessionFactory sessionFactory = createSessionFactory()) {
|
||||||
|
ShippingService service = new ShippingService(sessionFactory, new ShippingDao());
|
||||||
|
return routeRequest(input, service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private APIGatewayProxyResponseEvent routeRequest(APIGatewayProxyRequestEvent input, ShippingService service) {
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
headers.put("Content-Type", "application/json");
|
||||||
|
headers.put("X-Custom-Header", "application/json");
|
||||||
|
|
||||||
|
Object result = "OK";
|
||||||
|
|
||||||
|
switch (input.getResource()) {
|
||||||
|
case "/consignment":
|
||||||
|
result = service.createConsignment(
|
||||||
|
fromJson(input.getBody(), Consignment.class));
|
||||||
|
break;
|
||||||
|
case "/consignment/{id}":
|
||||||
|
result = service.view(input.getPathParameters().get("id"));
|
||||||
|
break;
|
||||||
|
case "/consignment/{id}/item":
|
||||||
|
service.addItem(input.getPathParameters().get("id"),
|
||||||
|
fromJson(input.getBody(), Item.class));
|
||||||
|
break;
|
||||||
|
case "/consignment/{id}/checkin":
|
||||||
|
service.checkIn(input.getPathParameters().get("id"),
|
||||||
|
fromJson(input.getBody(), Checkin.class));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new APIGatewayProxyResponseEvent()
|
||||||
|
.withHeaders(headers)
|
||||||
|
.withStatusCode(200)
|
||||||
|
.withBody(toJson(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> String toJson(T object) {
|
||||||
|
try {
|
||||||
|
return OBJECT_MAPPER.writeValueAsString(object);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T fromJson(String json, Class<T> type) {
|
||||||
|
try {
|
||||||
|
return OBJECT_MAPPER.readValue(json, type);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SessionFactory createSessionFactory() {
|
||||||
|
Map<String, String> settings = new HashMap<>();
|
||||||
|
settings.put(URL, System.getenv("DB_URL"));
|
||||||
|
settings.put(DIALECT, "org.hibernate.dialect.PostgreSQLDialect");
|
||||||
|
settings.put(DEFAULT_SCHEMA, "shipping");
|
||||||
|
settings.put(DRIVER, "org.postgresql.Driver");
|
||||||
|
settings.put(USER, System.getenv("DB_USER"));
|
||||||
|
settings.put(PASS, System.getenv("DB_PASSWORD"));
|
||||||
|
settings.put("hibernate.hikari.connectionTimeout", "20000");
|
||||||
|
settings.put("hibernate.hikari.minimumIdle", "1");
|
||||||
|
settings.put("hibernate.hikari.maximumPoolSize", "2");
|
||||||
|
settings.put("hibernate.hikari.idleTimeout", "30000");
|
||||||
|
|
||||||
|
// commented out as we only need them on first use
|
||||||
|
// settings.put(HBM2DDL_AUTO, "create-only");
|
||||||
|
// settings.put(HBM2DDL_DATABASE_ACTION, "create");
|
||||||
|
|
||||||
|
StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
|
||||||
|
.applySettings(settings)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return new MetadataSources(registry)
|
||||||
|
.addAnnotatedClass(Consignment.class)
|
||||||
|
.addAnnotatedClass(Item.class)
|
||||||
|
.addAnnotatedClass(Checkin.class)
|
||||||
|
.buildMetadata()
|
||||||
|
.buildSessionFactory();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.lambda.shipping;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public class Checkin {
|
||||||
|
private String timeStamp;
|
||||||
|
private String location;
|
||||||
|
|
||||||
|
@Column(name = "timestamp")
|
||||||
|
public String getTimeStamp() {
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeStamp(String timeStamp) {
|
||||||
|
this.timeStamp = timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column(name = "location")
|
||||||
|
public String getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(String location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.baeldung.lambda.shipping;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static javax.persistence.FetchType.EAGER;
|
||||||
|
|
||||||
|
@Entity(name = "consignment")
|
||||||
|
@Table(name = "consignment")
|
||||||
|
public class Consignment {
|
||||||
|
private String id;
|
||||||
|
private String source;
|
||||||
|
private String destination;
|
||||||
|
private boolean isDelivered;
|
||||||
|
private List<Item> items = new ArrayList<>();
|
||||||
|
private List<Checkin> checkins = new ArrayList<>();
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "consignment_id")
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column(name = "source")
|
||||||
|
public String getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSource(String source) {
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column(name = "destination")
|
||||||
|
public String getDestination() {
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDestination(String destination) {
|
||||||
|
this.destination = destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column(name = "delivered", columnDefinition = "boolean")
|
||||||
|
public boolean isDelivered() {
|
||||||
|
return isDelivered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDelivered(boolean delivered) {
|
||||||
|
isDelivered = delivered;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ElementCollection(fetch = EAGER)
|
||||||
|
@CollectionTable(name = "consignment_item", joinColumns = @JoinColumn(name = "consignment_id"))
|
||||||
|
@OrderColumn(name = "item_index")
|
||||||
|
public List<Item> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(List<Item> items) {
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ElementCollection(fetch = EAGER)
|
||||||
|
@CollectionTable(name = "consignment_checkin", joinColumns = @JoinColumn(name = "consignment_id"))
|
||||||
|
@OrderColumn(name = "checkin_index")
|
||||||
|
public List<Checkin> getCheckins() {
|
||||||
|
return checkins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCheckins(List<Checkin> checkins) {
|
||||||
|
this.checkins = checkins;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.baeldung.lambda.shipping;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public class Item {
|
||||||
|
private String location;
|
||||||
|
private String description;
|
||||||
|
private String timeStamp;
|
||||||
|
|
||||||
|
@Column(name = "location")
|
||||||
|
public String getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(String location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column(name = "description")
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column(name = "timestamp")
|
||||||
|
public String getTimeStamp() {
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeStamp(String timeStamp) {
|
||||||
|
this.timeStamp = timeStamp;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.lambda.shipping;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class ShippingDao {
|
||||||
|
/**
|
||||||
|
* Save a consignment to the database
|
||||||
|
* @param consignment the consignment to save
|
||||||
|
*/
|
||||||
|
public void save(Session session, Consignment consignment) {
|
||||||
|
Transaction transaction = session.beginTransaction();
|
||||||
|
session.save(consignment);
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a consignment in the database by id
|
||||||
|
*/
|
||||||
|
public Optional<Consignment> find(Session session, String id) {
|
||||||
|
return Optional.ofNullable(session.get(Consignment.class, id));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.baeldung.lambda.shipping;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ShippingService {
|
||||||
|
private SessionFactory sessionFactory;
|
||||||
|
private ShippingDao shippingDao;
|
||||||
|
|
||||||
|
public ShippingService(SessionFactory sessionFactory, ShippingDao shippingDao) {
|
||||||
|
this.sessionFactory = sessionFactory;
|
||||||
|
this.shippingDao = shippingDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String createConsignment(Consignment consignment) {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
consignment.setDelivered(false);
|
||||||
|
consignment.setId(UUID.randomUUID().toString());
|
||||||
|
shippingDao.save(session, consignment);
|
||||||
|
return consignment.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItem(String consignmentId, Item item) {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
shippingDao.find(session, consignmentId)
|
||||||
|
.ifPresent(consignment -> addItem(session, consignment, item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addItem(Session session, Consignment consignment, Item item) {
|
||||||
|
consignment.getItems()
|
||||||
|
.add(item);
|
||||||
|
shippingDao.save(session, consignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkIn(String consignmentId, Checkin checkin) {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
shippingDao.find(session, consignmentId)
|
||||||
|
.ifPresent(consignment -> checkIn(session, consignment, checkin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkIn(Session session, Consignment consignment, Checkin checkin) {
|
||||||
|
consignment.getCheckins().add(checkin);
|
||||||
|
consignment.getCheckins().sort(Comparator.comparing(Checkin::getTimeStamp));
|
||||||
|
if (checkin.getLocation().equals(consignment.getDestination())) {
|
||||||
|
consignment.setDelivered(true);
|
||||||
|
}
|
||||||
|
shippingDao.save(session, consignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Consignment view(String consignmentId) {
|
||||||
|
try (Session session = sessionFactory.openSession()) {
|
||||||
|
return shippingDao.find(session, consignmentId)
|
||||||
|
.orElseGet(Consignment::new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
AWSTemplateFormatVersion: '2010-09-09'
|
||||||
|
Transform: AWS::Serverless-2016-10-31
|
||||||
|
Description: >
|
||||||
|
shipping-tracker
|
||||||
|
|
||||||
|
Sample SAM Template for shipping-tracker
|
||||||
|
|
||||||
|
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
|
||||||
|
Globals:
|
||||||
|
Function:
|
||||||
|
Timeout: 20
|
||||||
|
|
||||||
|
Resources:
|
||||||
|
ShippingFunction:
|
||||||
|
Type: AWS::Serverless::Function
|
||||||
|
Properties:
|
||||||
|
CodeUri: ShippingFunction
|
||||||
|
Handler: com.baeldung.lambda.shipping.App::handleRequest
|
||||||
|
Runtime: java8
|
||||||
|
MemorySize: 512
|
||||||
|
Environment:
|
||||||
|
Variables:
|
||||||
|
DB_URL: jdbc:postgresql://postgres/postgres
|
||||||
|
DB_USER: postgres
|
||||||
|
DB_PASSWORD: password
|
||||||
|
Events:
|
||||||
|
CreateConsignment:
|
||||||
|
Type: Api
|
||||||
|
Properties:
|
||||||
|
Path: /consignment
|
||||||
|
Method: post
|
||||||
|
AddItem:
|
||||||
|
Type: Api
|
||||||
|
Properties:
|
||||||
|
Path: /consignment/{id}/item
|
||||||
|
Method: post
|
||||||
|
CheckIn:
|
||||||
|
Type: Api
|
||||||
|
Properties:
|
||||||
|
Path: /consignment/{id}/checkin
|
||||||
|
Method: post
|
||||||
|
ViewConsignment:
|
||||||
|
Type: Api
|
||||||
|
Properties:
|
||||||
|
Path: /consignment/{id}
|
||||||
|
Method: get
|
||||||
|
|
27
cdi/pom.xml
27
cdi/pom.xml
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project
|
<project
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>cdi</artifactId>
|
<artifactId>cdi</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-spring-4</artifactId>
|
<artifactId>parent-spring-5</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<relativePath>../parent-spring-4</relativePath>
|
<relativePath>../parent-spring-5</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -26,28 +26,22 @@
|
||||||
<artifactId>weld-se-core</artifactId>
|
<artifactId>weld-se-core</artifactId>
|
||||||
<version>${weld-se-core.version}</version>
|
<version>${weld-se-core.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.hamcrest</groupId>
|
|
||||||
<artifactId>hamcrest</artifactId>
|
|
||||||
<version>${hamcrest.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.assertj</groupId>
|
<groupId>org.assertj</groupId>
|
||||||
<artifactId>assertj-core</artifactId>
|
<artifactId>assertj-core</artifactId>
|
||||||
<version>${assertj-core.version}</version>
|
<version>${assertj-core.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-context</artifactId>
|
|
||||||
<version>${spring.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjweaver</artifactId>
|
<artifactId>aspectjweaver</artifactId>
|
||||||
<version>${aspectjweaver.version}</version>
|
<version>${aspectjweaver.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context</artifactId>
|
||||||
|
<version>${spring.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-test</artifactId>
|
<artifactId>spring-test</artifactId>
|
||||||
|
@ -61,7 +55,6 @@
|
||||||
<weld-se-core.version>3.0.5.Final</weld-se-core.version>
|
<weld-se-core.version>3.0.5.Final</weld-se-core.version>
|
||||||
<aspectjweaver.version>1.9.2</aspectjweaver.version>
|
<aspectjweaver.version>1.9.2</aspectjweaver.version>
|
||||||
<assertj-core.version>3.10.0</assertj-core.version>
|
<assertj-core.version>3.10.0</assertj-core.version>
|
||||||
<spring.version>5.1.2.RELEASE</spring.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.example</groupId>
|
<groupId>com.example</groupId>
|
||||||
<artifactId>cf-uaa-oauth2-client</artifactId>
|
<artifactId>cf-uaa-oauth2-client</artifactId>
|
||||||
<name>uaa-client-webapp</name>
|
<name>cf-uaa-oauth2-client</name>
|
||||||
<description>Demo project for Spring Boot</description>
|
<description>Demo project for Spring Boot</description>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
### Relevant Articles:
|
||||||
|
|
||||||
|
- [How to Remove a Prefix From Strings in Groovy](https://www.baeldung.com/groovy-remove-string-prefix)
|
|
@ -0,0 +1,122 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>core-groovy-strings</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<name>core-groovy-strings</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.groovy</groupId>
|
||||||
|
<artifactId>groovy</artifactId>
|
||||||
|
<version>${groovy.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.groovy</groupId>
|
||||||
|
<artifactId>groovy-all</artifactId>
|
||||||
|
<version>${groovy-all.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.groovy</groupId>
|
||||||
|
<artifactId>groovy-dateutil</artifactId>
|
||||||
|
<version>${groovy.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.groovy</groupId>
|
||||||
|
<artifactId>groovy-sql</artifactId>
|
||||||
|
<version>${groovy-sql.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-runner</artifactId>
|
||||||
|
<version>${junit.platform.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hsqldb</groupId>
|
||||||
|
<artifactId>hsqldb</artifactId>
|
||||||
|
<version>${hsqldb.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.spockframework</groupId>
|
||||||
|
<artifactId>spock-core</artifactId>
|
||||||
|
<version>${spock-core.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.gmavenplus</groupId>
|
||||||
|
<artifactId>gmavenplus-plugin</artifactId>
|
||||||
|
<version>${gmavenplus-plugin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>addSources</goal>
|
||||||
|
<goal>addTestSources</goal>
|
||||||
|
<goal>compile</goal>
|
||||||
|
<goal>compileTests</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
|
<version>${maven-failsafe-plugin.version}</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-surefire-provider</artifactId>
|
||||||
|
<version>${junit.platform.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>junit5</id>
|
||||||
|
<goals>
|
||||||
|
<goal>integration-test</goal>
|
||||||
|
<goal>verify</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<includes>
|
||||||
|
<include>**/*Test5.java</include>
|
||||||
|
</includes>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>central</id>
|
||||||
|
<url>https://jcenter.bintray.com</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<junit.platform.version>1.0.0</junit.platform.version>
|
||||||
|
<groovy.version>2.5.6</groovy.version>
|
||||||
|
<groovy-all.version>2.5.6</groovy-all.version>
|
||||||
|
<groovy-sql.version>2.5.6</groovy-sql.version>
|
||||||
|
<hsqldb.version>2.4.0</hsqldb.version>
|
||||||
|
<spock-core.version>1.1-groovy-2.4</spock-core.version>
|
||||||
|
<gmavenplus-plugin.version>1.6</gmavenplus-plugin.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.baeldung.removeprefix
|
||||||
|
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class RemovePrefixTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCasePrefixIsRemoved_thenReturnTrue() {
|
||||||
|
def trimPrefix = {
|
||||||
|
it.startsWith('Groovy-') ? it.minus('Groovy-') : it
|
||||||
|
}
|
||||||
|
|
||||||
|
def actual = trimPrefix("Groovy-Tutorials at Baeldung")
|
||||||
|
def expected = "Tutorials at Baeldung"
|
||||||
|
|
||||||
|
Assert.assertEquals(expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenPrefixIsRemoved_thenReturnTrue() {
|
||||||
|
|
||||||
|
String prefix = "groovy-"
|
||||||
|
String trimPrefix = "Groovy-Tutorials at Baeldung"
|
||||||
|
def actual;
|
||||||
|
if(trimPrefix.startsWithIgnoreCase(prefix)) {
|
||||||
|
actual = trimPrefix.substring(prefix.length())
|
||||||
|
}
|
||||||
|
|
||||||
|
def expected = "Tutorials at Baeldung"
|
||||||
|
|
||||||
|
Assert.assertEquals(expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenPrefixIsRemovedUsingRegex_thenReturnTrue() {
|
||||||
|
|
||||||
|
def regex = ~"^([Gg])roovy-"
|
||||||
|
String trimPrefix = "Groovy-Tutorials at Baeldung"
|
||||||
|
String actual = trimPrefix - regex
|
||||||
|
|
||||||
|
def expected = "Tutorials at Baeldung"
|
||||||
|
|
||||||
|
Assert.assertEquals(expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenPrefixIsRemovedUsingReplaceFirst_thenReturnTrue() {
|
||||||
|
def regex = ~"^groovy"
|
||||||
|
String trimPrefix = "groovyTutorials at Baeldung's groovy page"
|
||||||
|
String actual = trimPrefix.replaceFirst(regex, "")
|
||||||
|
|
||||||
|
def expected = "Tutorials at Baeldung's groovy page"
|
||||||
|
|
||||||
|
Assert.assertEquals(expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenPrefixIsRemovedUsingReplaceAll_thenReturnTrue() {
|
||||||
|
|
||||||
|
String trimPrefix = "groovyTutorials at Baeldung groovy"
|
||||||
|
String actual = trimPrefix.replaceAll(/^groovy/, "")
|
||||||
|
|
||||||
|
def expected = "Tutorials at Baeldung groovy"
|
||||||
|
|
||||||
|
Assert.assertEquals(expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -13,4 +13,5 @@ This module contains articles about core Groovy concepts
|
||||||
- [Converting a String to a Date in Groovy](https://www.baeldung.com/groovy-string-to-date)
|
- [Converting a String to a Date in Groovy](https://www.baeldung.com/groovy-string-to-date)
|
||||||
- [Guide to I/O in Groovy](https://www.baeldung.com/groovy-io)
|
- [Guide to I/O in Groovy](https://www.baeldung.com/groovy-io)
|
||||||
- [Convert String to Integer in Groovy](https://www.baeldung.com/groovy-convert-string-to-integer)
|
- [Convert String to Integer in Groovy](https://www.baeldung.com/groovy-convert-string-to-integer)
|
||||||
|
- [Groovy Variable Scope](https://www.baeldung.com/groovy/variable-scope)
|
||||||
- [[More -->]](/core-groovy-2)
|
- [[More -->]](/core-groovy-2)
|
||||||
|
|
|
@ -9,3 +9,4 @@ This module contains articles about Java 10 core features
|
||||||
- [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another)
|
- [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another)
|
||||||
- [Deep Dive Into the New Java JIT Compiler – Graal](https://www.baeldung.com/graal-java-jit-compiler)
|
- [Deep Dive Into the New Java JIT Compiler – Graal](https://www.baeldung.com/graal-java-jit-compiler)
|
||||||
- [Copying Sets in Java](https://www.baeldung.com/java-copy-sets)
|
- [Copying Sets in Java](https://www.baeldung.com/java-copy-sets)
|
||||||
|
- [Converting between a List and a Set in Java](https://www.baeldung.com/convert-list-to-set-and-set-to-list)
|
||||||
|
|
|
@ -1,22 +1,29 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project
|
<project
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>core-java-10</artifactId>
|
<artifactId>core-java-10</artifactId>
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
<version>0.1.0-SNAPSHOT</version>
|
||||||
<name>core-java-10</name>
|
<name>core-java-10</name>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<url>http://maven.apache.org</url>
|
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung.core-java-modules</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>core-java-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<relativePath>../../</relativePath>
|
<relativePath>../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-collections4</artifactId>
|
||||||
|
<version>${commons-collections4.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -34,6 +41,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source.version>10</maven.compiler.source.version>
|
<maven.compiler.source.version>10</maven.compiler.source.version>
|
||||||
<maven.compiler.target.version>10</maven.compiler.target.version>
|
<maven.compiler.target.version>10</maven.compiler.target.version>
|
||||||
|
<commons-collections4.version>4.1</commons-collections4.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import junit.framework.TestSuite;
|
||||||
/**
|
/**
|
||||||
* Unit test for simple App.
|
* Unit test for simple App.
|
||||||
*/
|
*/
|
||||||
public class AppTest
|
public class AppUnitTest
|
||||||
extends TestCase
|
extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +15,7 @@ public class AppTest
|
||||||
*
|
*
|
||||||
* @param testName name of the test case
|
* @param testName name of the test case
|
||||||
*/
|
*/
|
||||||
public AppTest( String testName )
|
public AppUnitTest(String testName )
|
||||||
{
|
{
|
||||||
super( testName );
|
super( testName );
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ public class AppTest
|
||||||
*/
|
*/
|
||||||
public static Test suite()
|
public static Test suite()
|
||||||
{
|
{
|
||||||
return new TestSuite( AppTest.class );
|
return new TestSuite( AppUnitTest.class );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.baeldung.java10.collections.conversion;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class ListSetConversionUnitTest {
|
||||||
|
|
||||||
|
// Set -> List; List -> Set
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void givenUsingCoreJava_whenSetConvertedToList_thenCorrect() {
|
||||||
|
final Set<Integer> sourceSet = Sets.newHashSet(0, 1, 2, 3, 4, 5);
|
||||||
|
final List<Integer> targetList = new ArrayList<>(sourceSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void givenUsingCoreJava_whenListConvertedToSet_thenCorrect() {
|
||||||
|
final List<Integer> sourceList = Lists.newArrayList(0, 1, 2, 3, 4, 5);
|
||||||
|
final Set<Integer> targetSet = new HashSet<>(sourceList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenUsingJava10_whenSetConvertedToList_thenCorrect() {
|
||||||
|
final Set<Integer> sourceSet = Sets.newHashSet(0, 1, 2, 3, 4, 5);
|
||||||
|
final List<Integer> targetList = List.copyOf(sourceSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenUsingJava10_whenListConvertedToSet_thenCorrect() {
|
||||||
|
final List<Integer> sourceList = Lists.newArrayList(0, 1, 2, 3, 4, 5);
|
||||||
|
final Set<Integer> targetSet = Set.copyOf(sourceList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void givenUsingGuava_whenSetConvertedToList_thenCorrect() {
|
||||||
|
final Set<Integer> sourceSet = Sets.newHashSet(0, 1, 2, 3, 4, 5);
|
||||||
|
final List<Integer> targetList = Lists.newArrayList(sourceSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void givenUsingGuava_whenListConvertedToSet_thenCorrect() {
|
||||||
|
final List<Integer> sourceList = Lists.newArrayList(0, 1, 2, 3, 4, 5);
|
||||||
|
final Set<Integer> targetSet = Sets.newHashSet(sourceList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void givenUsingCommonsCollections_whenListConvertedToSet_thenCorrect() {
|
||||||
|
final List<Integer> sourceList = Lists.newArrayList(0, 1, 2, 3, 4, 5);
|
||||||
|
|
||||||
|
final Set<Integer> targetSet = new HashSet<>(6);
|
||||||
|
CollectionUtils.addAll(targetSet, sourceList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void givenUsingCommonsCollections_whenSetConvertedToList_thenCorrect() {
|
||||||
|
final Set<Integer> sourceSet = Sets.newHashSet(0, 1, 2, 3, 4, 5);
|
||||||
|
|
||||||
|
final List<Integer> targetList = new ArrayList<>(6);
|
||||||
|
CollectionUtils.addAll(targetList, sourceSet);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,5 +10,6 @@ public class CopyListServiceUnitTest {
|
||||||
@Test(expected = UnsupportedOperationException.class)
|
@Test(expected = UnsupportedOperationException.class)
|
||||||
public void whenModifyCopyOfList_thenThrowsException() {
|
public void whenModifyCopyOfList_thenThrowsException() {
|
||||||
List<Integer> copyList = List.copyOf(Arrays.asList(1, 2, 3, 4));
|
List<Integer> copyList = List.copyOf(Arrays.asList(1, 2, 3, 4));
|
||||||
|
copyList.add(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
## Core Java 11
|
||||||
|
|
||||||
|
This module contains articles about Java 11 core features
|
||||||
|
|
||||||
|
### Relevant articles
|
||||||
|
- [Guide to Java 8 Optional](https://www.baeldung.com/java-optional)
|
||||||
|
- [Guide to Java Reflection](http://www.baeldung.com/java-reflection)
|
||||||
|
- [Guide to Java 8’s Collectors](https://www.baeldung.com/java-8-collectors)
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>core-java-11-2</artifactId>
|
||||||
|
<version>0.1.0-SNAPSHOT</version>
|
||||||
|
<name>core-java-11-2</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../..</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>${guava.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<version>${assertj.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${maven.compiler.source.version}</source>
|
||||||
|
<target>${maven.compiler.target.version}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source.version>11</maven.compiler.source.version>
|
||||||
|
<maven.compiler.target.version>11</maven.compiler.target.version>
|
||||||
|
<guava.version>29.0-jre</guava.version>
|
||||||
|
<assertj.version>3.17.2</assertj.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
public abstract class Animal implements Eating {
|
public abstract class Animal implements Eating {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
public class Bird extends Animal {
|
public class Bird extends Animal {
|
||||||
private boolean walks;
|
private boolean walks;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
public interface Eating {
|
public interface Eating {
|
||||||
String eats();
|
String eats();
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
public class Goat extends Animal implements Locomotion {
|
public class Goat extends Animal implements Locomotion {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
@Greeter(greet="Good morning")
|
@Greeter(greet="Good morning")
|
||||||
public class Greetings {
|
public class Greetings {
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
public interface Locomotion {
|
public interface Locomotion {
|
||||||
String getLocomotion();
|
String getLocomotion();
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
public class Operations {
|
public class Operations {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java.reflection;
|
package com.baeldung.reflection;
|
||||||
|
|
||||||
public class Person {
|
public class Person {
|
||||||
private String name;
|
private String name;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue