Merge branch 'eugenp:master' into master
This commit is contained in:
commit
36ecf023d4
|
@ -32,9 +32,27 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>${maven.resources.plugin.version}</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<nonFilteredFileExtensions>
|
||||
<nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
|
||||
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
|
||||
</nonFilteredFileExtensions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<poi.version>5.2.0</poi.version>
|
||||
<jexcel.version>1.0.6</jexcel.version>
|
||||
<maven.resources.plugin.version>3.2.0</maven.resources.plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
Binary file not shown.
|
@ -12,7 +12,7 @@ import java.nio.file.Paths;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class CellBorderHandlerUnitTest {
|
||||
private static final String FILE_NAME = "cellstyle/CellStyleHandlerTest.xlsx";
|
||||
private static final String FILE_NAME = "cellstyle/CellStyleBorderHandlerTest.xlsx";
|
||||
private static final int SHEET_INDEX = 0;
|
||||
|
||||
private static CellBordersHandler cellBordersHandler;
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package com.baeldung.game;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Scanner;
|
||||
|
||||
class RockPaperScissorsGame {
|
||||
|
||||
private static Map<Integer, String> movesMap = new HashMap<Integer, String>() {{
|
||||
put(0, "rock");
|
||||
put(1, "paper");
|
||||
put(2, "scissors");
|
||||
}};
|
||||
|
||||
public static void main(String[] args) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
int wins = 0;
|
||||
int losses = 0;
|
||||
|
||||
System.out.println("Welcome to Rock-Paper-Scissors! Please enter \"rock\", \"paper\", \"scissors\", or \"quit\" to exit.");
|
||||
|
||||
while (true) {
|
||||
System.out.println("-------------------------");
|
||||
System.out.print("Enter your move: ");
|
||||
String playerMove = scanner.nextLine();
|
||||
|
||||
if (playerMove.equals("quit")) {
|
||||
System.out.println("You won " + wins + " times and lost " + losses + " times.");
|
||||
System.out.println("Thanks for playing! See you again.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!movesMap.containsValue(playerMove)) {
|
||||
System.out.println("Your move isn't valid!");
|
||||
continue;
|
||||
}
|
||||
|
||||
String computerMove = getComputerMove();
|
||||
|
||||
if (playerMove.equals(computerMove)) {
|
||||
System.out.println("It's a tie!");
|
||||
} else if (isPlayerWin(playerMove, computerMove)) {
|
||||
System.out.println("You won!");
|
||||
wins++;
|
||||
} else {
|
||||
System.out.println("You lost!");
|
||||
losses++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPlayerWin(String playerMove, String computerMove) {
|
||||
return playerMove.equals("rock") && computerMove.equals("scissors")
|
||||
|| (playerMove.equals("scissors") && computerMove.equals("paper"))
|
||||
|| (playerMove.equals("paper") && computerMove.equals("rock"));
|
||||
}
|
||||
|
||||
private static String getComputerMove() {
|
||||
Random random = new Random();
|
||||
int randomNumber = random.nextInt(3);
|
||||
String computerMove = movesMap.get(randomNumber);
|
||||
System.out.println("Computer move: " + computerMove);
|
||||
return computerMove;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.baeldung.uuid;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UuidHelper {
|
||||
|
||||
public static byte[] convertUUIDToBytes(UUID uuid) {
|
||||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
||||
bb.putLong(uuid.getMostSignificantBits());
|
||||
bb.putLong(uuid.getLeastSignificantBits());
|
||||
return bb.array();
|
||||
}
|
||||
|
||||
public static UUID convertBytesToUUID(byte[] bytes) {
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
|
||||
long high = byteBuffer.getLong();
|
||||
long low = byteBuffer.getLong();
|
||||
return new UUID(high, low);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
System.out.println("Original UUID: " + uuid);
|
||||
|
||||
byte[] bytes = convertUUIDToBytes(uuid);
|
||||
System.out.println("Converted byte array: " + Arrays.toString(bytes));
|
||||
|
||||
UUID uuidNew = convertBytesToUUID(bytes);
|
||||
System.out.println("Converted UUID: " + uuidNew);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.baeldung.maps.initialize;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class EmptyMapInitializer {
|
||||
|
||||
public static Map<String, String> articleMap;
|
||||
static {
|
||||
articleMap = new HashMap<>();
|
||||
}
|
||||
|
||||
public static Map<String, String> createEmptyMap() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
public void createMapUsingConstructors() {
|
||||
Map hashMap = new HashMap();
|
||||
Map linkedHashMap = new LinkedHashMap();
|
||||
Map treeMap = new TreeMap();
|
||||
}
|
||||
|
||||
public Map<String, String> createEmptyMapUsingMapsObject() {
|
||||
Map<String, String> emptyMap = Maps.newHashMap();
|
||||
return emptyMap;
|
||||
}
|
||||
|
||||
public Map createGenericEmptyMapUsingMapsObject() {
|
||||
Map genericEmptyMap = Maps.<String, Integer>newHashMap();
|
||||
return genericEmptyMap;
|
||||
}
|
||||
|
||||
public static Map<String, String> createMapUsingGuava() {
|
||||
Map<String, String> emptyMapUsingGuava =
|
||||
Maps.newHashMap(ImmutableMap.of());
|
||||
return emptyMapUsingGuava;
|
||||
}
|
||||
|
||||
public SortedMap<String, String> createEmptySortedMap() {
|
||||
SortedMap<String, String> sortedMap = Collections.emptySortedMap();
|
||||
return sortedMap;
|
||||
}
|
||||
|
||||
public NavigableMap<String, String> createEmptyNavigableMap() {
|
||||
NavigableMap<String, String> navigableMap = Collections.emptyNavigableMap();
|
||||
return navigableMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.baeldung.maps.initialize;
|
||||
|
||||
import java.util.Map;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class EmptyMapInitializerUnitTest {
|
||||
|
||||
@Test(expected=UnsupportedOperationException.class)
|
||||
public void givenEmptyMap_whenAddingEntries_throwsException() {
|
||||
Map<String, String> map = EmptyMapInitializer.createEmptyMap();
|
||||
map.put("key", "value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmptyMap_whenChecked_returnsTrue() {
|
||||
assertTrue(EmptyMapInitializer.articleMap.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmptyMap_whenCreatedUsingGuava_returnsEmptyOrNot() {
|
||||
Map<String, String> emptyMapUsingGuava =
|
||||
EmptyMapInitializer.createMapUsingGuava();
|
||||
assertTrue(emptyMapUsingGuava.isEmpty());
|
||||
emptyMapUsingGuava.put("key", "value");
|
||||
assertFalse(emptyMapUsingGuava.isEmpty());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.mapandhashmap;
|
||||
|
||||
import com.baeldung.mapandhashmap.printer.HashMapPrinter;
|
||||
import com.baeldung.mapandhashmap.printer.MapPrinter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
HashMap<String, String> hashMap = new HashMap<>();
|
||||
TreeMap<String, String> treeMap = new TreeMap<>();
|
||||
|
||||
HashMapPrinter hashMapPrinter = new HashMapPrinter();
|
||||
hashMapPrinter.printMap(hashMap);
|
||||
// hashMapPrinter.printMap(treeMap); Compile time error
|
||||
// hashMapPrinter.printMap(map); Compile time error
|
||||
|
||||
MapPrinter mapPrinter = new MapPrinter();
|
||||
mapPrinter.printMap(hashMap);
|
||||
mapPrinter.printMap(treeMap);
|
||||
mapPrinter.printMap(map);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class HashMapPrinter {
|
||||
|
||||
public void printMap(final HashMap<?, ?> map) {
|
||||
for (final Entry<?, ?> entry : map.entrySet()) {
|
||||
System.out.println(entry.getKey() + " " + entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class MapPrinter {
|
||||
|
||||
public void printMap(final Map<?, ?> map) {
|
||||
for (final Entry<?, ?> entry : map.entrySet()) {
|
||||
System.out.println(entry.getKey() + " " + entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class MapReporter {
|
||||
|
||||
private final Map<?, ?> map;
|
||||
|
||||
public MapReporter(final Map<?, ?> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public void printMap() {
|
||||
for (final Entry<?, ?> entry : this.map.entrySet()) {
|
||||
System.out.println(entry.getKey() + " " + entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class HashMapPrinterUnitTest {
|
||||
|
||||
private final HashMapPrinter mapPrinter = new HashMapPrinter();
|
||||
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
System.setOut(new PrintStream(outputStreamCaptor));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test hash map printer with HashMap")
|
||||
void testPrintHashMap() {
|
||||
// given
|
||||
String key = "HashMap";
|
||||
String value = "Main default implementation for the Map interface";
|
||||
String expected = key + " " + value;
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
mapPrinter.printMap(map);
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test hash map printer with LinkedHash")
|
||||
void testPrintLinkedHashMap() {
|
||||
// given
|
||||
String key = "LinkedHashMap";
|
||||
String value = "Use this implementation if you need keep the order of elements";
|
||||
String expected = key + " " + value;
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
mapPrinter.printMap(map);
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.TreeMap;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class MapPrinterUnitTest {
|
||||
|
||||
private final MapPrinter mapPrinter = new MapPrinter();
|
||||
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
System.setOut(new PrintStream(outputStreamCaptor));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test printer with TreeMap")
|
||||
void testPrintTreeMap() {
|
||||
// given
|
||||
String key = "TreeMap";
|
||||
String value = "Used when sorting is needed";
|
||||
String expected = key + " " + value;
|
||||
TreeMap<String, String> map = new TreeMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
mapPrinter.printMap(map);
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test printer with HashMap")
|
||||
void testPrintHashMap() {
|
||||
// given
|
||||
String key = "HashMap";
|
||||
String value = "Main default implementation for the Map interface";
|
||||
String expected = key + " " + value;
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
mapPrinter.printMap(map);
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test printer with LinkedHash")
|
||||
void testPrintLinkedHashMap() {
|
||||
// given
|
||||
String key = "LinkedHashMap";
|
||||
String value = "Use this implementation if you need keep the order of elements";
|
||||
String expected = key + " " + value;
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
mapPrinter.printMap(map);
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package com.baeldung.mapandhashmap.printer;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.TreeMap;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class MapReporterUnitTest {
|
||||
|
||||
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
System.setOut(new PrintStream(outputStreamCaptor));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test reporter with TreeMap")
|
||||
void testPrintTreeMap() {
|
||||
// given
|
||||
String key = "TreeMap";
|
||||
String value = "Used when sorting is needed";
|
||||
String expected = key + " " + value;
|
||||
TreeMap<String, String> map = new TreeMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
MapReporter mapReporter = new MapReporter(map);
|
||||
mapReporter.printMap();
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test reporter with HashMap")
|
||||
void testPrintHashMap() {
|
||||
// given
|
||||
String key = "HashMap";
|
||||
String value = "Main default implementation for the Map interface";
|
||||
String expected = key + " " + value;
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
MapReporter mapReporter = new MapReporter(map);
|
||||
mapReporter.printMap();
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test reporter with LinkedHash")
|
||||
void testPrintLinkedHashMap() {
|
||||
// given
|
||||
String key = "LinkedHashMap";
|
||||
String value = "Use this implementation if you need keep the order of elements";
|
||||
String expected = key + " " + value;
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||
map.put(key, value);
|
||||
// when
|
||||
MapReporter mapReporter = new MapReporter(map);
|
||||
mapReporter.printMap();
|
||||
// then
|
||||
String actual = outputStreamCaptor.toString().trim();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,25 +1,22 @@
|
|||
package com.baeldung.atomicstampedreference;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicStampedReference;
|
||||
|
||||
public class StampedAccount {
|
||||
|
||||
private AtomicInteger stamp = new AtomicInteger(0);
|
||||
private AtomicStampedReference<Integer> account = new AtomicStampedReference<>(0, 0);
|
||||
|
||||
public int getBalance() {
|
||||
return account.getReference();
|
||||
}
|
||||
|
||||
public int getStamp() {
|
||||
return account.getStamp();
|
||||
}
|
||||
private final AtomicInteger stamp = new AtomicInteger(0);
|
||||
private final AtomicStampedReference<Integer> account = new AtomicStampedReference<>(0, 0);
|
||||
|
||||
public boolean deposit(int funds) {
|
||||
int[] stamps = new int[1];
|
||||
int current = this.account.get(stamps);
|
||||
int newStamp = this.stamp.incrementAndGet();
|
||||
|
||||
// Thread is paused here to allow other threads to update the stamp and amount (for testing only)
|
||||
sleep();
|
||||
|
||||
return this.account.compareAndSet(current, current + funds, stamps[0], newStamp);
|
||||
}
|
||||
|
||||
|
@ -29,4 +26,19 @@ public class StampedAccount {
|
|||
int newStamp = this.stamp.incrementAndGet();
|
||||
return this.account.compareAndSet(current, current - funds, stamps[0], newStamp);
|
||||
}
|
||||
|
||||
public int getBalance() {
|
||||
return account.getReference();
|
||||
}
|
||||
|
||||
public int getStamp() {
|
||||
return account.getStamp();
|
||||
}
|
||||
|
||||
private static void sleep() {
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,38 @@
|
|||
package com.baeldung.atomicstampedreference;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ThreadStampedAccountUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenMultiThread_whenStampedAccount_thenSetBalance() throws InterruptedException {
|
||||
StampedAccount account = new StampedAccount();
|
||||
|
||||
Thread t = new Thread(() -> {
|
||||
while (!account.withdrawal(100))
|
||||
while (!account.deposit(100)) {
|
||||
Thread.yield();
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
Assert.assertTrue(account.deposit(100));
|
||||
t.join(1_000);
|
||||
Assert.assertFalse(t.isAlive());
|
||||
Assert.assertSame(0, account.getBalance());
|
||||
|
||||
Thread t2 = new Thread(() -> {
|
||||
while (!account.withdrawal(100)) {
|
||||
Thread.yield();
|
||||
}
|
||||
});
|
||||
t2.start();
|
||||
|
||||
t.join(10_000);
|
||||
t2.join(10_000);
|
||||
|
||||
assertFalse(t.isAlive());
|
||||
assertFalse(t2.isAlive());
|
||||
|
||||
assertEquals(0, account.getBalance());
|
||||
assertTrue(account.getStamp() > 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,17 @@ class LongRunningAction implements Runnable {
|
|||
public void run() {
|
||||
System.out.println("This is phase " + ph.getPhase());
|
||||
System.out.println("Thread " + threadName + " before long running action");
|
||||
ph.arriveAndAwaitAdvance();
|
||||
|
||||
try {
|
||||
Thread.sleep(20);
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("Thread " + threadName + " action completed and waiting for others");
|
||||
ph.arriveAndAwaitAdvance();
|
||||
System.out.println("Thread " + threadName + " proceeding in phase " + ph.getPhase());
|
||||
|
||||
ph.arriveAndDeregister();
|
||||
}
|
||||
}
|
|
@ -26,13 +26,20 @@ public class PhaserUnitTest {
|
|||
executorService.submit(new LongRunningAction("thread-3", ph));
|
||||
|
||||
//then
|
||||
System.out.println("Thread " + Thread.currentThread().getName() + " waiting for others");
|
||||
ph.arriveAndAwaitAdvance();
|
||||
System.out.println("Thread " + Thread.currentThread().getName() + " proceeding in phase " + ph.getPhase());
|
||||
|
||||
assertEquals(1, ph.getPhase());
|
||||
|
||||
//and
|
||||
executorService.submit(new LongRunningAction("thread-4", ph));
|
||||
executorService.submit(new LongRunningAction("thread-5", ph));
|
||||
|
||||
System.out.println("Thread " + Thread.currentThread().getName() + " waiting for others");
|
||||
ph.arriveAndAwaitAdvance();
|
||||
System.out.println("Thread " + Thread.currentThread().getName() + " proceeding in phase " + ph.getPhase());
|
||||
|
||||
assertEquals(2, ph.getPhase());
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.exception.missingreturnstatement;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MissingReturnStatement {
|
||||
public static void main(String[] args) {
|
||||
int a = -12;
|
||||
int result = pow(a);
|
||||
System.out.println(result);
|
||||
Map<String, Integer> dictionary = createDictionary();
|
||||
dictionary.forEach((s, integer) -> System.out.println(s + " " + integer));
|
||||
}
|
||||
|
||||
public static int pow(int number) {
|
||||
int pow = number * number;
|
||||
return pow;
|
||||
}
|
||||
|
||||
public static String checkNumber(int number) {
|
||||
if (number == 0) {
|
||||
return "It's equals to zero";
|
||||
}
|
||||
|
||||
for (int i = 0; i < number; i++) {
|
||||
if (i > 100) {
|
||||
return "It's a big number";
|
||||
}
|
||||
}
|
||||
return "It's a negative number";
|
||||
}
|
||||
|
||||
public static Map<String, Integer> createDictionary() {
|
||||
List<String> words = Arrays.asList("Hello", "World");
|
||||
return words.stream()
|
||||
.collect(Collectors.toMap(s -> s, s -> 1));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.baeldung.exception.missingreturnstatement;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class MissingReturnStatementUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenANumber_thenReturnItsPow() {
|
||||
int number = 10;
|
||||
int pow = MissingReturnStatement.pow(number);
|
||||
assertEquals(100, pow);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABigNumber_thenReturnItsType() {
|
||||
int number = 200;
|
||||
String type = MissingReturnStatement.checkNumber(number);
|
||||
assertEquals("It's a big number", type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenANegativeNumber_thenReturnItsType() {
|
||||
int number = -10;
|
||||
String type = MissingReturnStatement.checkNumber(number);
|
||||
assertEquals("It's a negative number", type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getStringDictionary_thenPrintValues() {
|
||||
Map<String, Integer> dictionary = MissingReturnStatement.createDictionary();
|
||||
assertEquals(2, dictionary.size());
|
||||
dictionary.forEach((s, integer) -> System.out.println(s + " - " + integer));
|
||||
}
|
||||
}
|
|
@ -259,110 +259,7 @@
|
|||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<!-- java instrumentation profiles to build jars -->
|
||||
<profile>
|
||||
<id>buildAgentLoader</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>agentLoader</classifier>
|
||||
<classesDirectory>target/classes</classesDirectory>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
</manifest>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
|
||||
<includes>
|
||||
<include>com/baeldung/instrumentation/application/AgentLoader.class</include>
|
||||
<include>com/baeldung/instrumentation/application/Launcher.class</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>buildApplication</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>application</classifier>
|
||||
<classesDirectory>target/classes</classesDirectory>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
</manifest>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
|
||||
<includes>
|
||||
<include>com/baeldung/instrumentation/application/MyAtm.class</include>
|
||||
<include>com/baeldung/instrumentation/application/MyAtmApplication.class</include>
|
||||
<include>com/baeldung/instrumentation/application/Launcher.class</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>buildAgent</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>agent</classifier>
|
||||
<classesDirectory>target/classes</classesDirectory>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
</manifest>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
|
||||
<includes>
|
||||
<include>com/baeldung/instrumentation/agent/AtmTransformer.class</include>
|
||||
<include>com/baeldung/instrumentation/agent/MyInstrumentationAgent.class</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<properties>
|
||||
|
|
|
@ -15,3 +15,13 @@ This module contains articles about working with the Java Virtual Machine (JVM).
|
|||
- [What Causes java.lang.OutOfMemoryError: unable to create new native thread](https://www.baeldung.com/java-outofmemoryerror-unable-to-create-new-native-thread)
|
||||
- [View Bytecode of a Class File in Java](https://www.baeldung.com/java-class-view-bytecode)
|
||||
- More articles: [[next -->]](/core-java-modules/core-java-jvm-2)
|
||||
|
||||
|
||||
To run the code for the Instrumentation: https://www.baeldung.com/java-instrumentation article:
|
||||
1- build the module
|
||||
2- run the module 3 times to build the 3 jars:
|
||||
mvn install -PbuildAgentLoader
|
||||
mvn install -PbuildApplication
|
||||
mvn install -PbuildAgent
|
||||
3- update the commands in the article with the exact names of the jars generated in the target folder
|
||||
4- update the path in the AgentLoader class with the path of the agent on your system
|
|
@ -57,6 +57,11 @@
|
|||
<artifactId>jol-core</artifactId>
|
||||
<version>${jol-core.version}</version>
|
||||
</dependency>
|
||||
<dependency> <!-- needed to bridge to slf4j for projects that use the log4j APIs directly -->
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
@ -66,5 +71,114 @@
|
|||
<asm.version>8.0.1</asm.version>
|
||||
<bcel.version>6.5.0</bcel.version>
|
||||
</properties>
|
||||
<profiles>
|
||||
<!-- java instrumentation profiles to build jars -->
|
||||
<profile>
|
||||
<id>buildAgentLoader</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>agentLoader</classifier>
|
||||
<classesDirectory>target/classes</classesDirectory>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<mainClass>com.baeldung.instrumentation.application.Launcher</mainClass>
|
||||
</manifest>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
|
||||
<includes>
|
||||
<include>com/baeldung/instrumentation/application/AgentLoader.class</include>
|
||||
<include>com/baeldung/instrumentation/application/Launcher.class</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>buildApplication</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>application</classifier>
|
||||
<classesDirectory>target/classes</classesDirectory>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<mainClass>com.baeldung.instrumentation.application.Launcher</mainClass>
|
||||
</manifest>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
|
||||
<includes>
|
||||
<include>com/baeldung/instrumentation/application/MyAtm.class</include>
|
||||
<include>com/baeldung/instrumentation/application/MyAtmApplication.class</include>
|
||||
<include>com/baeldung/instrumentation/application/Launcher.class</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>buildAgent</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>agent</classifier>
|
||||
<classesDirectory>target/classes</classesDirectory>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<mainClass>com.baeldung.instrumentation.application.Launcher</mainClass>
|
||||
</manifest>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
|
||||
<includes>
|
||||
<include>com/baeldung/instrumentation/agent/AtmTransformer.class</include>
|
||||
<include>com/baeldung/instrumentation/agent/MyInstrumentationAgent.class</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,5 @@
|
|||
Agent-Class: com.baeldung.instrumentation.agent.MyInstrumentationAgent
|
||||
Can-Redefine-Classes: true
|
||||
Can-Retransform-Classes: true
|
||||
Premain-Class: com.baeldung.instrumentation.agent.MyInstrumentationAgent
|
||||
Main-Class: com.baeldung.instrumentation.application.Launcher
|
|
@ -0,0 +1,29 @@
|
|||
package com.baeldung.truststore;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.PKIXParameters;
|
||||
|
||||
public class TrustStoreUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenOpeningTrustStore_thenExceptionIsThrown() throws Exception {
|
||||
KeyStore keyStore = getKeyStore();
|
||||
InvalidAlgorithmParameterException invalidAlgorithmParameterException =
|
||||
Assertions.assertThrows(InvalidAlgorithmParameterException.class, () -> new PKIXParameters(keyStore));
|
||||
Assertions.assertEquals("the trustAnchors parameter must be non-empty", invalidAlgorithmParameterException.getMessage());
|
||||
}
|
||||
|
||||
private KeyStore getKeyStore() throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException {
|
||||
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
ks.load(null, "changeIt".toCharArray());
|
||||
return ks;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
FROM nginx:latest
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
|
@ -0,0 +1,8 @@
|
|||
events {}
|
||||
|
||||
http {
|
||||
server {
|
||||
listen 80;
|
||||
index index.html;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
FROM nginx:latest
|
||||
COPY sample-site/html/* /etc/nginx/html/
|
||||
COPY config/nginx.conf /etc/nginx/nginx.conf
|
|
@ -0,0 +1,2 @@
|
|||
FROM sample-site-base:latest
|
||||
COPY html/* /etc/nginx/html/
|
|
@ -0,0 +1,3 @@
|
|||
FROM nginx:latest
|
||||
COPY html/* /etc/nginx/html/
|
||||
COPY config/nginx.conf /etc/nginx/nginx.conf
|
|
@ -0,0 +1,6 @@
|
|||
mkdir tmp-context
|
||||
cp -R ../html tmp-context/
|
||||
cp -R ../../config tmp-context/
|
||||
cp Dockerfile-script tmp-context/Dockerfile
|
||||
docker build -t sample-site:latest tmp-context
|
||||
rm -rf tmp-context
|
|
@ -0,0 +1,10 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Sample Site</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Welcome to the first page of the site</h2>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
description = 'gradle-source-vs-target-compatibility'
|
||||
|
||||
group 'com.baeldung'
|
||||
|
||||
java {
|
||||
sourceCompatibility = "1.6"
|
||||
targetCompatibility = "1.8"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.baeldung.helloworld;
|
||||
|
||||
public class HelloWorldApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello World!");
|
||||
}
|
||||
|
||||
}
|
|
@ -6,5 +6,6 @@ include 'greeter'
|
|||
include 'gradletaskdemo'
|
||||
include 'junit5'
|
||||
include 'gradle-employee-app'
|
||||
include 'gradle-source-vs-target-compatibility'
|
||||
|
||||
println 'This will be executed during the initialization phase.'
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package com.baeldung.map.invert;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class InvertHashMapExample {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Map<String, Integer> map = new HashMap<>();
|
||||
map.put("first", 1);
|
||||
map.put("second", 2);
|
||||
System.out.println(map);
|
||||
|
||||
invertMapUsingForLoop(map);
|
||||
invertMapUsingStreams(map);
|
||||
invertMapUsingMapper(map);
|
||||
|
||||
map.put("two", 2);
|
||||
invertMapUsingGroupingBy(map);
|
||||
}
|
||||
|
||||
public static <V, K> Map<V, K> invertMapUsingForLoop(Map<K, V> map) {
|
||||
Map<V, K> inversedMap = new HashMap<V, K>();
|
||||
for (Entry<K, V> entry : map.entrySet()) {
|
||||
inversedMap.put(entry.getValue(), entry.getKey());
|
||||
}
|
||||
System.out.println(inversedMap);
|
||||
return inversedMap;
|
||||
}
|
||||
|
||||
public static <V, K> Map<V, K> invertMapUsingStreams(Map<K, V> map) {
|
||||
Map<V, K> inversedMap = map.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Entry::getValue, Entry::getKey));
|
||||
System.out.println(inversedMap);
|
||||
return inversedMap;
|
||||
}
|
||||
|
||||
public static <K, V> Map<V, K> invertMapUsingMapper(Map<K, V> sourceMap) {
|
||||
Map<V, K> inversedMap = sourceMap.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Entry::getValue, Entry::getKey, (oldValue, newValue) -> oldValue));
|
||||
System.out.println(inversedMap);
|
||||
return inversedMap;
|
||||
}
|
||||
|
||||
public static <V, K> Map<V, List<K>> invertMapUsingGroupingBy(Map<K, V> map) {
|
||||
Map<V, List<K>> inversedMap = map.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
|
||||
System.out.println(inversedMap);
|
||||
return inversedMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.baeldung.map.invert;
|
||||
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class InvertHashMapUnitTest {
|
||||
|
||||
Map<String, Integer> sourceMap;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
sourceMap = new HashMap<>();
|
||||
sourceMap.put("Sunday", 0);
|
||||
sourceMap.put("Monday", 1);
|
||||
sourceMap.put("Tuesday", 2);
|
||||
sourceMap.put("Wednesday", 3);
|
||||
sourceMap.put("Thursday", 4);
|
||||
sourceMap.put("Friday", 5);
|
||||
sourceMap.put("Saturday", 6);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenSourceMap_whenUsingForLoop_returnsInvertedMap() {
|
||||
Map<Integer, String> inversedMap = InvertHashMapExample.invertMapUsingForLoop(sourceMap);
|
||||
|
||||
assertNotNull(inversedMap);
|
||||
assertEquals(sourceMap.size(), inversedMap.size());
|
||||
assertEquals("Monday", inversedMap.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenSourceMap_whenUsingStreams_returnsInvertedMap() {
|
||||
Map<Integer, String> inversedMap = InvertHashMapExample.invertMapUsingStreams(sourceMap);
|
||||
|
||||
assertNotNull(inversedMap);
|
||||
assertEquals(sourceMap.size(), inversedMap.size());
|
||||
assertEquals("Monday", inversedMap.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenSourceMap_whenUsingMapper_returnsInvertedMap() {
|
||||
Map<Integer, String> inversedMap = InvertHashMapExample.invertMapUsingMapper(sourceMap);
|
||||
|
||||
assertNotNull(inversedMap);
|
||||
assertEquals(sourceMap.size(), inversedMap.size());
|
||||
assertEquals("Monday", inversedMap.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenSourceMapWithDuplicateValues_whenUsingGroupBy_returnsInvertedMap() {
|
||||
sourceMap.put("MONDAY", 1);
|
||||
Map<Integer, List<String>> inversedMap = InvertHashMapExample.invertMapUsingGroupingBy(sourceMap);
|
||||
|
||||
assertNotNull(inversedMap);
|
||||
assertNotEquals(sourceMap.size(), inversedMap.size()); // duplicate keys are merged now
|
||||
assertEquals(2, inversedMap.get(1).size());
|
||||
assertTrue(inversedMap.get(1).contains("Monday"));
|
||||
assertTrue(inversedMap.get(1).contains("MONDAY"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#include "com_baeldung_jni_RegisterNativesHelloWorldJNI.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
JNIEXPORT jstring JNICALL hello (JNIEnv* env, jobject thisObject) {
|
||||
std::string hello = "Hello from registered native C++ !!";
|
||||
std::cout << hello << std::endl;
|
||||
return env->NewStringUTF(hello.c_str());
|
||||
}
|
||||
|
||||
static JNINativeMethod methods[] = {
|
||||
{"sayHello", "()Ljava/lang/String;", (void*) &hello },
|
||||
};
|
||||
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_baeldung_jni_RegisterNativesHelloWorldJNI_register (JNIEnv* env, jobject thsObject) {
|
||||
jclass clazz = env->FindClass("com/baeldung/jni/RegisterNativesHelloWorldJNI");
|
||||
|
||||
(env)->RegisterNatives(clazz, methods, sizeof(methods)/sizeof(methods[0]));
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class com_baeldung_jni_RegisterNativesHelloWorldJNI */
|
||||
|
||||
#ifndef _Included_com_baeldung_jni_RegisterNativesHelloWorldJNI
|
||||
#define _Included_com_baeldung_jni_RegisterNativesHelloWorldJNI
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: com_baeldung_jni_RegisterNativesHelloWorldJNI
|
||||
* Method: sayHello
|
||||
* Signature: ()Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_com_baeldung_jni_RegisterNativesHelloWorldJNI_sayHello
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
/*
|
||||
* Class: com_baeldung_jni_RegisterNativesHelloWorldJNI
|
||||
* Method: register
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_com_baeldung_jni_RegisterNativesHelloWorldJNI_register
|
||||
(JNIEnv *, jobject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -3,4 +3,5 @@
|
|||
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_HelloWorldJNI.cpp -o com_baeldung_jni_HelloWorldJNI.o
|
||||
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_ExampleParametersJNI.cpp -o com_baeldung_jni_ExampleParametersJNI.o
|
||||
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_ExampleObjectsJNI.cpp -o com_baeldung_jni_ExampleObjectsJNI.o
|
||||
g++ -dynamiclib -o ../../../native/macos/libnative.dylib com_baeldung_jni_HelloWorldJNI.o com_baeldung_jni_ExampleParametersJNI.o com_baeldung_jni_ExampleObjectsJNI.o -lc
|
||||
g++ -c -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin com_baeldung_jni_RegisterNativesHelloWorldJNI.cpp -o com_baeldung_jni_RegisterNativesHelloWorldJNI.o
|
||||
g++ -dynamiclib -o ../../../native/macos/libnative.dylib com_baeldung_jni_HelloWorldJNI.o com_baeldung_jni_ExampleParametersJNI.o com_baeldung_jni_ExampleObjectsJNI.o com_baeldung_jni_RegisterNativesHelloWorldJNI.o -lc
|
|
@ -0,0 +1,18 @@
|
|||
package com.baeldung.jni;
|
||||
|
||||
public class RegisterNativesHelloWorldJNI {
|
||||
|
||||
static {
|
||||
System.loadLibrary("native");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
RegisterNativesHelloWorldJNI helloWorldJNI = new RegisterNativesHelloWorldJNI();
|
||||
helloWorldJNI.register();
|
||||
helloWorldJNI.sayHello();
|
||||
}
|
||||
|
||||
public native String sayHello();
|
||||
|
||||
public native void register();
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.baeldung.jni.registernatives;
|
||||
|
||||
import com.baeldung.jni.RegisterNativesHelloWorldJNI;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class JNIRegisterNativesManualTest {
|
||||
@Before
|
||||
public void setup() {
|
||||
System.loadLibrary("native");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenRegisteredNativeHelloWorld_thenOutputIsAsExpected() {
|
||||
RegisterNativesHelloWorldJNI helloWorld = new RegisterNativesHelloWorldJNI();
|
||||
helloWorld.register();
|
||||
|
||||
String helloFromNative = helloWorld.sayHello();
|
||||
|
||||
assertNotNull(helloFromNative);
|
||||
assertTrue(helloFromNative.equals("Hello from registered native C++ !!"));
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring.version>5.3.13</spring.version>
|
||||
<spring.version>5.3.16</spring.version>
|
||||
<spring-security.version>5.6.0</spring-security.version>
|
||||
<spring-boot-starter-test.version>1.5.10.RELEASE</spring-boot-starter-test.version>
|
||||
</properties>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package com.baeldung.hibernate.scalarmethod;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
public class HibernateScalarExample {
|
||||
|
||||
private Session session;
|
||||
|
||||
public HibernateScalarExample(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public List<Object[]> fetchColumnWithNativeQuery() {
|
||||
return session.createNativeQuery("SELECT * FROM Student student")
|
||||
.list();
|
||||
}
|
||||
|
||||
public List<Object[]> fetchColumnWithScalar() {
|
||||
return session.createNativeQuery("SELECT * FROM Student student")
|
||||
.addScalar("studentId", StandardBasicTypes.LONG)
|
||||
.addScalar("name", StandardBasicTypes.STRING)
|
||||
.addScalar("age", StandardBasicTypes.INTEGER)
|
||||
.list();
|
||||
}
|
||||
|
||||
public List<String> fetchLimitedColumnWithScalar() {
|
||||
return session.createNativeQuery("SELECT * FROM Student student")
|
||||
.addScalar("name", StandardBasicTypes.STRING)
|
||||
.list();
|
||||
}
|
||||
|
||||
public List<Object[]> fetchColumnWithOverloadedScalar() {
|
||||
return session.createNativeQuery("SELECT * FROM Student student")
|
||||
.addScalar("name", StandardBasicTypes.STRING)
|
||||
.addScalar("age")
|
||||
.list();
|
||||
}
|
||||
|
||||
public Integer fetchAvgAgeWithScalar() {
|
||||
return (Integer) session.createNativeQuery("SELECT AVG(age) as avgAge FROM Student student")
|
||||
.addScalar("avgAge")
|
||||
.uniqueResult();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package com.baeldung.hibernate.scalarmethod;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.hibernate.HibernateUtil;
|
||||
import com.baeldung.hibernate.pojo.Student;
|
||||
|
||||
public class HibernateScalarExampleUnitTest {
|
||||
|
||||
private static Session session;
|
||||
private static Transaction transaction;
|
||||
private static final int DATA_SIZE = 50000;
|
||||
private static HibernateScalarExample scalarExample;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws IOException {
|
||||
session = HibernateUtil.getSessionFactory().openSession();
|
||||
transaction = session.beginTransaction();
|
||||
scalarExample = new HibernateScalarExample(session);
|
||||
session.createNativeQuery("delete from Student").executeUpdate();
|
||||
for (int i = 0; i < DATA_SIZE; i++) {
|
||||
Student student = new Student("John-" + i, generateRandomAge(5, 24));
|
||||
session.persist(student);
|
||||
}
|
||||
transaction.commit();
|
||||
transaction = session.beginTransaction();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
transaction.rollback();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenNativeQuery_whenNoScalarUsed_ThenFetchAll() {
|
||||
List<Object[]> list = scalarExample.fetchColumnWithNativeQuery();
|
||||
assertEquals(DATA_SIZE, list.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenNativeQuery_whenScalarUsed_ThenFetchAll() {
|
||||
List<Object[]> list = scalarExample.fetchColumnWithScalar();
|
||||
assertEquals(DATA_SIZE, list.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenNativeQuery_whenScalarUsed_ThenFetchLimitedColumns() {
|
||||
List<String> list = scalarExample.fetchLimitedColumnWithScalar();
|
||||
for (String colValue : list) {
|
||||
assertTrue(colValue.startsWith("John"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenNativeQuery_whenScalarUsedForSingleResult_ThenSingleValueReturned() {
|
||||
List<Object[]> list = scalarExample.fetchColumnWithOverloadedScalar();
|
||||
for (Object[] colArray : list) {
|
||||
assertEquals(2, colArray.length);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenScalarUsedForAvgAge_ThenSingleValueReturned() {
|
||||
Integer avgAge = scalarExample.fetchAvgAgeWithScalar();
|
||||
assertEquals(true, (avgAge >= 5 && avgAge <= 24));
|
||||
}
|
||||
|
||||
private static int generateRandomAge(int min, int max) {
|
||||
return new Random().nextInt(max - min + 1) + min;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
### Relevant Articles:
|
||||
|
||||
- [Configure and Use Multiple DataSources in Spring Boot](https://www.baeldung.com/spring-boot-configure-multiple-datasources)
|
||||
- [Introduction to Spring Data JDBC](https://www.baeldung.com/spring-data-jdbc-intro)
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
<!-- <module>spring-boot-keycloak</module> --> <!-- Fixing under JAVA-8271 -->
|
||||
<module>spring-boot-libraries</module>
|
||||
<module>spring-boot-libraries-2</module>
|
||||
<module>spring-boot-libraries-comparison</module>
|
||||
<module>spring-boot-logging-log4j2</module>
|
||||
<module>spring-boot-multiple-datasources</module>
|
||||
<module>spring-boot-mvc</module>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
### Relevant Articles:
|
||||
|
||||
- [HttpMessageNotWritableException: No Converter for [class …] With Preset Content-Type](https://www.baeldung.com/spring-no-converter-with-preset)
|
||||
- [Spring Boot: Customize the Jackson ObjectMapper](https://www.baeldung.com/spring-boot-customize-jackson-objectmapper)
|
||||
- [“HttpMessageNotWritableException: No converter found for return value of type”](https://www.baeldung.com/spring-no-converter-found)
|
||||
- [Creating a Read-Only Repository with Spring Data](https://www.baeldung.com/spring-data-read-only-repository)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
## Spring Boot Libraries
|
||||
|
||||
This module contains articles about various Spring Boot libraries Comparison
|
||||
|
||||
### Relevant Articles:
|
||||
|
||||
- [GraphQL vs REST](https://www.baeldung.com/graphql-vs-rest/)
|
|
@ -0,0 +1,46 @@
|
|||
<?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>spring-boot-libraries-comparison</artifactId>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.spring-boot-modules</groupId>
|
||||
<artifactId>spring-boot-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java</groupId>
|
||||
<artifactId>graphql-spring-boot-starter</artifactId>
|
||||
<version>${graphql-spring-boot-starter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java</groupId>
|
||||
<artifactId>graphql-java-tools</artifactId>
|
||||
<version>${graphql-java-tools.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java</groupId>
|
||||
<artifactId>graphiql-spring-boot-starter</artifactId>
|
||||
<version>${graphql-spring-boot-starter.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<properties>
|
||||
<graphql-spring-boot-starter.version>5.0.2</graphql-spring-boot-starter.version>
|
||||
<graphql-java-tools.version>5.2.4</graphql-java-tools.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.graphqlvsrest;
|
||||
|
||||
import com.baeldung.graphqlvsrest.configuration.GraphqlConfiguration;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
@SpringBootApplication
|
||||
@Import(GraphqlConfiguration.class)
|
||||
@EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class})
|
||||
public class GraphqlVsRestApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GraphqlVsRestApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.baeldung.graphqlvsrest.configuration;
|
||||
|
||||
import com.baeldung.graphqlvsrest.repository.OrderRepository;
|
||||
import com.baeldung.graphqlvsrest.resolver.Mutation;
|
||||
import com.baeldung.graphqlvsrest.resolver.ProductResolver;
|
||||
import com.baeldung.graphqlvsrest.resolver.Query;
|
||||
import com.baeldung.graphqlvsrest.repository.ProductRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class GraphqlConfiguration {
|
||||
|
||||
@Autowired
|
||||
ProductRepository productRepository;
|
||||
|
||||
@Autowired
|
||||
OrderRepository orderRepository;
|
||||
|
||||
@Bean
|
||||
public Query query() {
|
||||
return new Query(productRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ProductResolver productResolver(){
|
||||
return new ProductResolver(orderRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Mutation mutation() {
|
||||
return new Mutation(productRepository);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.graphqlvsrest.controller;
|
||||
|
||||
import com.baeldung.graphqlvsrest.entity.Order;
|
||||
import com.baeldung.graphqlvsrest.entity.Product;
|
||||
import com.baeldung.graphqlvsrest.model.ProductModel;
|
||||
import com.baeldung.graphqlvsrest.repository.OrderRepository;
|
||||
import com.baeldung.graphqlvsrest.repository.ProductRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("order")
|
||||
public class OrderController {
|
||||
|
||||
@Autowired
|
||||
OrderRepository orderRepository;
|
||||
|
||||
@GetMapping()
|
||||
public List<Order> getOrders(@RequestParam("product-id") Integer productId){
|
||||
return orderRepository.getOrdersByProduct(productId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.baeldung.graphqlvsrest.controller;
|
||||
|
||||
import com.baeldung.graphqlvsrest.entity.Product;
|
||||
import com.baeldung.graphqlvsrest.model.ProductModel;
|
||||
import com.baeldung.graphqlvsrest.repository.ProductRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("product")
|
||||
public class ProductController {
|
||||
|
||||
@Autowired
|
||||
ProductRepository productRepository;
|
||||
|
||||
@GetMapping
|
||||
public List<Product> getProducts(Pageable pageable){
|
||||
return productRepository.getProducts(pageable.getPageSize(), pageable.getPageNumber());
|
||||
}
|
||||
|
||||
@GetMapping("/{product-id}")
|
||||
public Product getProducts(@PathVariable("product-id") Integer productId){
|
||||
return productRepository.getProduct(productId);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public Product save(@RequestBody ProductModel productModel){
|
||||
return productRepository.save(productModel);
|
||||
}
|
||||
|
||||
@PutMapping("/{product-id}")
|
||||
public Product update(@PathVariable("product-id") Integer productId, @RequestBody ProductModel productModel){
|
||||
return productRepository.update(productId, productModel);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package com.baeldung.graphqlvsrest.entity;
|
||||
|
||||
public class Order {
|
||||
private Integer id;
|
||||
private Integer product_id;
|
||||
private String customer_uuid;
|
||||
private String status;
|
||||
private String address;
|
||||
private String creation_date;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getProduct_id() {
|
||||
return product_id;
|
||||
}
|
||||
|
||||
public void setProduct_id(Integer product_id) {
|
||||
this.product_id = product_id;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getCustomer_uuid() {
|
||||
return customer_uuid;
|
||||
}
|
||||
|
||||
public void setCustomer_uuid(String customer_uuid) {
|
||||
this.customer_uuid = customer_uuid;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getCreation_date() {
|
||||
return creation_date;
|
||||
}
|
||||
|
||||
public void setCreation_date(String creation_date) {
|
||||
this.creation_date = creation_date;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package com.baeldung.graphqlvsrest.entity;
|
||||
|
||||
import com.baeldung.graphqlvsrest.model.ProductModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Product {
|
||||
private Integer id;
|
||||
private String name;
|
||||
private String description;
|
||||
private String status;
|
||||
private String currency;
|
||||
private Double price;
|
||||
private List<String> image_url;
|
||||
private List<String> video_url;
|
||||
private Integer stock;
|
||||
private Float average_rating;
|
||||
|
||||
public Product(Integer id, ProductModel productModel) {
|
||||
this.id = id;
|
||||
this.name = productModel.getName();
|
||||
this.description = productModel.getDescription();
|
||||
this.currency = productModel.getCurrency();
|
||||
this.price = productModel.getPrice();
|
||||
this.stock = productModel.getStock();
|
||||
this.image_url = productModel.getImage_url();
|
||||
this.video_url = productModel.getVideo_url();
|
||||
this.average_rating = 0F;
|
||||
this.status = productModel.getStatus();
|
||||
}
|
||||
|
||||
public Product(){
|
||||
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(Double price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public List<String> getImage_url() {
|
||||
return image_url;
|
||||
}
|
||||
|
||||
public void setImage_url(List<String> image_url) {
|
||||
this.image_url = image_url;
|
||||
}
|
||||
|
||||
public List<String> getVideo_url() {
|
||||
return video_url;
|
||||
}
|
||||
|
||||
public void setVideo_url(List<String> video_url) {
|
||||
this.video_url = video_url;
|
||||
}
|
||||
|
||||
public Integer getStock() {
|
||||
return stock;
|
||||
}
|
||||
|
||||
public void setStock(Integer stock) {
|
||||
this.stock = stock;
|
||||
}
|
||||
|
||||
public Float getAverage_rating() {
|
||||
return average_rating;
|
||||
}
|
||||
|
||||
public void setAverage_rating(Float average_rating) {
|
||||
this.average_rating = average_rating;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package com.baeldung.graphqlvsrest.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ProductModel {
|
||||
private String name;
|
||||
private String description;
|
||||
private String status;
|
||||
private String currency;
|
||||
private Double price;
|
||||
private List<String> image_url;
|
||||
private List<String> video_url;
|
||||
private Integer stock;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public void setCurrency(String currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(Double price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public List<String> getImage_url() {
|
||||
return image_url;
|
||||
}
|
||||
|
||||
public void setImage_url(List<String> image_url) {
|
||||
this.image_url = image_url;
|
||||
}
|
||||
|
||||
public List<String> getVideo_url() {
|
||||
return video_url;
|
||||
}
|
||||
|
||||
public void setVideo_url(List<String> video_url) {
|
||||
this.video_url = video_url;
|
||||
}
|
||||
|
||||
public Integer getStock() {
|
||||
return stock;
|
||||
}
|
||||
|
||||
public void setStock(Integer stock) {
|
||||
this.stock = stock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ProductModel{" +
|
||||
"name='" + name + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
", status='" + status + '\'' +
|
||||
", currency='" + currency + '\'' +
|
||||
", price=" + price +
|
||||
", image_url=" + image_url +
|
||||
", video_url=" + video_url +
|
||||
", stock=" + stock +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.graphqlvsrest.repository;
|
||||
|
||||
import com.baeldung.graphqlvsrest.entity.Order;
|
||||
import com.baeldung.graphqlvsrest.entity.Product;
|
||||
import com.baeldung.graphqlvsrest.model.ProductModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface OrderRepository {
|
||||
List<Order> getOrdersByProduct(Integer productId);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.graphqlvsrest.repository;
|
||||
|
||||
import com.baeldung.graphqlvsrest.entity.Product;
|
||||
import com.baeldung.graphqlvsrest.model.ProductModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ProductRepository {
|
||||
List<Product> getProducts(Integer pageSize, Integer pageNumber);
|
||||
Product getProduct(Integer id);
|
||||
Product save(ProductModel productModel);
|
||||
Product update(Integer productId, ProductModel productModel);
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.baeldung.graphqlvsrest.repository.impl;
|
||||
|
||||
import com.baeldung.graphqlvsrest.entity.Order;
|
||||
import com.baeldung.graphqlvsrest.repository.OrderRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Repository
|
||||
public class OrderRepositoryImpl implements OrderRepository {
|
||||
|
||||
private static List<Order> orderList = new ArrayList<>();
|
||||
|
||||
public OrderRepositoryImpl() {
|
||||
for (int i = 1; i <= 100; i++){
|
||||
Order order = new Order();
|
||||
order.setId(i);
|
||||
order.setProduct_id(i%10);
|
||||
order.setAddress(UUID.randomUUID().toString());
|
||||
order.setCustomer_uuid(UUID.randomUUID().toString());
|
||||
order.setCreation_date(new Date(System.currentTimeMillis()).toString());
|
||||
order.setStatus("Delivered");
|
||||
orderList.add(order);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Order> getOrdersByProduct(Integer productId) {
|
||||
return orderList.stream().filter(order -> order.getProduct_id().equals(productId)).collect(Collectors.toList());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package com.baeldung.graphqlvsrest.repository.impl;
|
||||
|
||||
import com.baeldung.graphqlvsrest.entity.Product;
|
||||
import com.baeldung.graphqlvsrest.model.ProductModel;
|
||||
import com.baeldung.graphqlvsrest.repository.ProductRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Repository
|
||||
public class ProductRepositoryImpl implements ProductRepository {
|
||||
|
||||
private static List<Product> productList = new ArrayList<>();
|
||||
|
||||
public ProductRepositoryImpl() {
|
||||
for (int i = 1; i <= 10; i++){
|
||||
Product product = new Product();
|
||||
product.setId(i);
|
||||
product.setName(String.format("Product %d", i));
|
||||
product.setDescription(String.format("Product %d description", i));
|
||||
product.setCurrency(String.format("Product %d currency", i));
|
||||
product.setPrice(Double.valueOf(i^2));
|
||||
product.setStock(10);
|
||||
product.setAverage_rating(0F);
|
||||
product.setImage_url(Arrays.asList(String.format("www.baeldung.com/imageurl/%d", i)));
|
||||
product.setVideo_url(Arrays.asList(String.format("www.baeldung.com/videourl/%d", i)));
|
||||
productList.add(product);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Product> getProducts(Integer pageSize, Integer pageNumber) {
|
||||
return productList.stream().skip(pageSize*pageNumber).limit(pageSize).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Product getProduct(Integer id) {
|
||||
return productList.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Product save(ProductModel productModel) {
|
||||
Product product = new Product(productList.size()+1, productModel);
|
||||
productList.add(product);
|
||||
return product;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Product update(Integer productId, ProductModel productModel) {
|
||||
Product product = getProduct(productId);
|
||||
if (product != null){
|
||||
update(product, productModel);
|
||||
}
|
||||
return product;
|
||||
}
|
||||
|
||||
private void update(Product product, ProductModel productModel){
|
||||
if (productModel != null) {
|
||||
System.out.println(productModel.toString());
|
||||
Optional.ofNullable(productModel.getName()).ifPresent(product::setName);
|
||||
Optional.ofNullable(productModel.getDescription()).ifPresent(product::setDescription);
|
||||
Optional.ofNullable(productModel.getCurrency()).ifPresent(product::setCurrency);
|
||||
Optional.ofNullable(productModel.getImage_url()).ifPresent(product::setImage_url);
|
||||
Optional.ofNullable(productModel.getStock()).ifPresent(product::setStock);
|
||||
Optional.ofNullable(productModel.getStatus()).ifPresent(product::setStatus);
|
||||
Optional.ofNullable(productModel.getVideo_url()).ifPresent(product::setVideo_url);
|
||||
Optional.ofNullable(productModel.getPrice()).ifPresent(product::setPrice);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.baeldung.graphqlvsrest.resolver;
|
||||
|
||||
import com.baeldung.graphqlvsrest.entity.Product;
|
||||
import com.baeldung.graphqlvsrest.model.ProductModel;
|
||||
import com.baeldung.graphqlvsrest.repository.ProductRepository;
|
||||
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
|
||||
|
||||
public class Mutation implements GraphQLMutationResolver {
|
||||
|
||||
private ProductRepository productRepository;
|
||||
public Mutation(ProductRepository productRepository){
|
||||
this.productRepository = productRepository;
|
||||
}
|
||||
|
||||
public Product saveProduct(ProductModel productModel) {
|
||||
return productRepository.save(productModel);
|
||||
}
|
||||
|
||||
public Product updateProduct(Integer productId, ProductModel productModel) {
|
||||
return productRepository.update(productId, productModel);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.baeldung.graphqlvsrest.resolver;
|
||||
|
||||
import com.baeldung.graphqlvsrest.entity.Order;
|
||||
import com.baeldung.graphqlvsrest.entity.Product;
|
||||
import com.baeldung.graphqlvsrest.repository.OrderRepository;
|
||||
import com.coxautodev.graphql.tools.GraphQLResolver;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ProductResolver implements GraphQLResolver<Product> {
|
||||
private OrderRepository orderRepository;
|
||||
public ProductResolver(OrderRepository orderRepository){
|
||||
this.orderRepository = orderRepository;
|
||||
}
|
||||
public List<Order> getOrders(Product product){
|
||||
return orderRepository.getOrdersByProduct(product.getId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.baeldung.graphqlvsrest.resolver;
|
||||
|
||||
import com.baeldung.graphqlvsrest.entity.Order;
|
||||
import com.baeldung.graphqlvsrest.entity.Product;
|
||||
import com.baeldung.graphqlvsrest.repository.OrderRepository;
|
||||
import com.baeldung.graphqlvsrest.repository.ProductRepository;
|
||||
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Query implements GraphQLQueryResolver {
|
||||
|
||||
private ProductRepository productRepository;
|
||||
public Query(ProductRepository productRepository){
|
||||
this.productRepository = productRepository;
|
||||
}
|
||||
|
||||
public List<Product> getProducts(int pageSize, int pageNumber) {
|
||||
return productRepository.getProducts(pageSize, pageNumber);
|
||||
}
|
||||
|
||||
public Product getProduct(int id) {
|
||||
return productRepository.getProduct(id);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
type Product {
|
||||
id: ID
|
||||
name: String!
|
||||
description: String
|
||||
status: String
|
||||
currency: String!
|
||||
price: Float
|
||||
image_url: [String]
|
||||
video_url: [String]
|
||||
stock: Int
|
||||
average_rating: Float
|
||||
orders:[Order]
|
||||
}
|
||||
|
||||
type Order{
|
||||
id:ID
|
||||
product_id:Int
|
||||
customer_uuid:String
|
||||
address:String
|
||||
status:String
|
||||
creation_date:String
|
||||
}
|
||||
|
||||
input ProductModel {
|
||||
name: String!
|
||||
description: String
|
||||
status: String
|
||||
currency: String!
|
||||
price: Float
|
||||
image_url: [String]
|
||||
video_url: [String]
|
||||
stock: Int
|
||||
}
|
||||
|
||||
input ProductUpdateModel {
|
||||
name: String
|
||||
description: String
|
||||
status: String
|
||||
currency: String
|
||||
price: Float
|
||||
image_url: [String]
|
||||
video_url: [String]
|
||||
stock: Int
|
||||
}
|
||||
|
||||
|
||||
# The Root Query for the application
|
||||
type Query {
|
||||
products(size: Int, page: Int): [Product]!
|
||||
product(id: Int): Product!
|
||||
}
|
||||
|
||||
# The Root Mutation for the application
|
||||
type Mutation {
|
||||
saveProduct(product: ProductModel) : Product!
|
||||
updateProduct(id: Int, product: ProductUpdateModel) : Product!
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.antmatchers;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class AntMatchersExampleApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AntMatchersExampleApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.baeldung.antmatchers.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
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.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication()
|
||||
.withUser("admin").password(passwordEncoder().encode("password")).roles("USER", "ADMIN")
|
||||
.and()
|
||||
.withUser("user").password(passwordEncoder().encode("password")).roles("USER");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/products/**").permitAll()
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/customers/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.httpBasic();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.antmatchers.controllers;
|
||||
|
||||
import com.baeldung.antmatchers.dtos.Customer;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class CustomerController {
|
||||
|
||||
@GetMapping("/customers/{id}")
|
||||
public Customer getCustomerById(@PathVariable("id") String id) {
|
||||
return new Customer("Customer 1", "Address 1", "Phone 1");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.baeldung.antmatchers.controllers;
|
||||
|
||||
import com.baeldung.antmatchers.dtos.Product;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
public class ProductController {
|
||||
|
||||
@GetMapping("/products")
|
||||
public List<Product> getProducts() {
|
||||
return new ArrayList<>(Arrays.asList(
|
||||
new Product("Product 1", "Description 1", 1.0),
|
||||
new Product("Product 2", "Description 2", 2.0)
|
||||
));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.baeldung.antmatchers.dtos;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Customer implements Serializable {
|
||||
private String name;
|
||||
private String address;
|
||||
private String phone;
|
||||
|
||||
public Customer(String name, String address, String phone) {
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.baeldung.antmatchers.dtos;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Product implements Serializable {
|
||||
private String name;
|
||||
private String description;
|
||||
private double price;
|
||||
|
||||
public Product(String name, String description, double price) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(double price) {
|
||||
this.price = price;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.baeldung.antmatchers.controllers;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebMvcTest(value = CustomerController.class)
|
||||
class CustomerControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void getCustomerByIdUnauthorized() throws Exception {
|
||||
mockMvc.perform(get("/customers/1")).andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getCustomerByIdForbidden() throws Exception {
|
||||
mockMvc.perform(get("/customers/1").with(user("user").roles("USER")))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getCustomerByIdOk() throws Exception {
|
||||
mockMvc.perform(get("/customers/1").with(user("admin").roles("ADMIN")))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.antmatchers.controllers;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebMvcTest(value = ProductController.class)
|
||||
class ProductControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void getProducts() throws Exception {
|
||||
mockMvc.perform(get("/products"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
{
|
||||
"swagger" : "2.0",
|
||||
"info" : {
|
||||
"description" : "This is a Baeldung Document Enum Sample Code",
|
||||
"version" : "v1",
|
||||
"title" : "Baeldung - Document Enum",
|
||||
"contact" : {
|
||||
"name" : "Parikshit Murria",
|
||||
"email" : "pmurria@baeldung.com"
|
||||
},
|
||||
"license" : {
|
||||
"name" : "Apache 2.0",
|
||||
"url" : "https://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
}
|
||||
},
|
||||
"host" : "baeldung.com",
|
||||
"basePath" : "/api",
|
||||
"schemes" : [ "http", "https" ],
|
||||
"paths" : {
|
||||
"/hire" : {
|
||||
"post" : {
|
||||
"summary" : "This method is used to hire employee with a specific role",
|
||||
"description" : "",
|
||||
"operationId" : "hireEmployee",
|
||||
"produces" : [ "application/json" ],
|
||||
"parameters" : [ {
|
||||
"in" : "body",
|
||||
"name" : "body",
|
||||
"description" : "role",
|
||||
"required" : true,
|
||||
"schema" : {
|
||||
"$ref" : "#/definitions/Employee"
|
||||
}
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "successful operation",
|
||||
"schema" : {
|
||||
"type" : "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions" : {
|
||||
"Employee" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"role" : {
|
||||
"type" : "string",
|
||||
"enum" : [ "Engineer", "Clerk", "Driver", "Janitor" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -63,7 +63,7 @@
|
|||
<name>Apache 2.0</name>
|
||||
</license>
|
||||
</info>
|
||||
<swaggerDirectory>generated/swagger-ui</swaggerDirectory>
|
||||
<swaggerDirectory>${basedir}/target/swagger-ui</swaggerDirectory>
|
||||
</apiSource>
|
||||
</apiSources>
|
||||
</configuration>
|
||||
|
|
|
@ -177,5 +177,21 @@
|
|||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>gateway-url-rewrite</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>com.baeldung.springcloudgateway.rewrite.URLRewriteGatewayApplication</mainClass>
|
||||
<jvmArguments>-Dspring.profiles.active=url-rewrite</jvmArguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
package com.baeldung.springcloudgateway.rewrite;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Baeldung
|
||||
*
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class URLRewriteGatewayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(URLRewriteGatewayApplication.class)
|
||||
.profiles("url-rewrite")
|
||||
.run(args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.baeldung.springcloudgateway.rewrite.routes;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.gateway.route.RouteLocator;
|
||||
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@Configuration
|
||||
@Profile("url-rewrite")
|
||||
public class DynamicRewriteRoute {
|
||||
|
||||
@Value("${rewrite.backend.uri}")
|
||||
private String backendUri;
|
||||
private static Random rnd = new Random();
|
||||
|
||||
@Bean
|
||||
public RouteLocator dynamicZipCodeRoute(RouteLocatorBuilder builder) {
|
||||
return builder.routes()
|
||||
.route("dynamicRewrite", r ->
|
||||
r.path("/v2/zip/**")
|
||||
.filters(f -> f.filter((exchange, chain) -> {
|
||||
ServerHttpRequest req = exchange.getRequest();
|
||||
addOriginalRequestUrl(exchange, req.getURI());
|
||||
String path = req.getURI().getRawPath();
|
||||
String newPath = path.replaceAll(
|
||||
"/v2/zip/(?<zipcode>.*)",
|
||||
"/api/zip/${zipcode}-" + String.format("%03d", rnd.nextInt(1000)));
|
||||
ServerHttpRequest request = req.mutate().path(newPath).build();
|
||||
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, request.getURI());
|
||||
return chain.filter(exchange.mutate().request(request).build());
|
||||
}))
|
||||
.uri(backendUri))
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ public class WebFilterGatewayApplication {
|
|||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(WebFilterGatewayApplication.class)
|
||||
.profiles("webfilters")
|
||||
.profiles("url-rewrite")
|
||||
.run(args);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# Enable this profile to disable security
|
||||
spring:
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
|
||||
- org.springframework.boot.actuate.autoconfigure.ManagementSecurityAutoConfiguration
|
||||
- org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration
|
||||
- org.springframework.boot.actuate.autoconfigure.security.reactive.ReactiveManagementWebSecurityAutoConfiguration
|
|
@ -0,0 +1,11 @@
|
|||
spring:
|
||||
cloud:
|
||||
gateway:
|
||||
routes:
|
||||
- id: rewrite_v1
|
||||
uri: ${rewrite.backend.uri:http://example.com}
|
||||
predicates:
|
||||
- Path=/v1/customer/**
|
||||
filters:
|
||||
- RewritePath=/v1/customer/(?<segment>.*),/api/$\{segment}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
package com.baeldung.springcloudgateway.rewrite;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@ActiveProfiles({ "nosecurity", "url-rewrite" })
|
||||
class URLRewriteGatewayApplicationLiveTest {
|
||||
|
||||
// NOTE for Eclipse users: By default, Eclipse will complain about com.sun.** classes.
|
||||
// To solve this issue, follow instructions available at the :
|
||||
// https://stackoverflow.com/questions/13155734/eclipse-cant-recognize-com-sun-net-httpserver-httpserver-package
|
||||
private static HttpServer mockServer;
|
||||
private static Logger log = LoggerFactory.getLogger(URLRewriteGatewayApplicationLiveTest.class);
|
||||
|
||||
// Create a running HttpServer that echoes back the request URL.
|
||||
private static HttpServer startTestServer() {
|
||||
|
||||
try {
|
||||
log.info("[I26] Starting mock server");
|
||||
mockServer = HttpServer.create();
|
||||
mockServer.bind(new InetSocketAddress(0), 0);
|
||||
mockServer.createContext("/api", (xchg) -> {
|
||||
String uri = xchg.getRequestURI()
|
||||
.toString();
|
||||
log.info("[I23] Backend called: uri={}", uri);
|
||||
xchg.getResponseHeaders()
|
||||
.add("Content-Type", "text/plain");
|
||||
xchg.sendResponseHeaders(200, 0);
|
||||
OutputStream os = xchg.getResponseBody();
|
||||
os.write(uri.getBytes());
|
||||
os.flush();
|
||||
os.close();
|
||||
});
|
||||
|
||||
mockServer.start();
|
||||
InetSocketAddress localAddr = mockServer.getAddress();
|
||||
log.info("[I36] mock server started: local address={}", localAddr);
|
||||
|
||||
return mockServer;
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TIP: https://www.baeldung.com/spring-dynamicpropertysource
|
||||
@DynamicPropertySource
|
||||
static void registerBackendServer(DynamicPropertyRegistry registry) {
|
||||
registry.add("rewrite.backend.uri", () -> {
|
||||
HttpServer s = startTestServer();
|
||||
return "http://localhost:" + s.getAddress().getPort();
|
||||
});
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopMockBackend() throws Exception {
|
||||
log.info("[I40] Shutdown mock http server");
|
||||
mockServer.stop(5);
|
||||
}
|
||||
|
||||
@LocalServerPort
|
||||
private int localPort;
|
||||
|
||||
@Test
|
||||
void testWhenApiCall_thenRewriteSuccess(@Autowired WebTestClient webClient) {
|
||||
webClient.get()
|
||||
.uri("http://localhost:" + localPort + "/v1/customer/customer1")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.consumeWith((result) -> {
|
||||
String body = new String(result.getResponseBody());
|
||||
log.info("[I99] body={}", body);
|
||||
assertEquals("/api/customer1", body);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhenDslCall_thenRewriteSuccess(@Autowired WebTestClient webClient) {
|
||||
webClient.get()
|
||||
.uri("http://localhost:" + localPort + "/v2/zip/123456")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.consumeWith((result) -> {
|
||||
String body = new String(result.getResponseBody());
|
||||
log.info("[I99] body={}", body);
|
||||
assertTrue(body.matches("/api/zip/123456-\\d{3}"));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -48,7 +48,15 @@
|
|||
<dependency>
|
||||
<groupId>io.github.openfeign.form</groupId>
|
||||
<artifactId>feign-form-spring</artifactId>
|
||||
</dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-oauth2-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.cloud.openfeign.client;
|
||||
|
||||
import com.baeldung.cloud.openfeign.model.Payment;
|
||||
import com.baeldung.cloud.openfeign.oauthfeign.OAuthFeignConfig;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@FeignClient(name = "payment-client", url = "http://localhost:8081/resource-server-jwt", configuration = OAuthFeignConfig.class)
|
||||
public interface PaymentClient {
|
||||
|
||||
@RequestMapping(value = "/payments", method = RequestMethod.GET)
|
||||
List<Payment> getPayments();
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.baeldung.cloud.openfeign.controller;
|
||||
|
||||
import com.baeldung.cloud.openfeign.client.PaymentClient;
|
||||
import com.baeldung.cloud.openfeign.model.Payment;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
public class PaymentController {
|
||||
|
||||
private final PaymentClient paymentClient;
|
||||
|
||||
public PaymentController(PaymentClient paymentClient) {
|
||||
this.paymentClient = paymentClient;
|
||||
}
|
||||
|
||||
@GetMapping("/payments")
|
||||
public List<Payment> getPayments() {
|
||||
List<Payment> payments = paymentClient.getPayments();
|
||||
return payments;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.baeldung.cloud.openfeign.model;
|
||||
|
||||
public class Payment {
|
||||
|
||||
private String id;
|
||||
private double amount;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(double amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.cloud.openfeign.oauthfeign;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
|
||||
@Configuration
|
||||
public class OAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf()
|
||||
.disable()
|
||||
.oauth2Client();
|
||||
http
|
||||
.authorizeRequests().anyRequest().permitAll();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package com.baeldung.cloud.openfeign.oauthfeign;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
public class OAuthClientCredentialsFeignManager {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(OAuthClientCredentialsFeignManager.class);
|
||||
|
||||
private final OAuth2AuthorizedClientManager manager;
|
||||
private final Authentication principal;
|
||||
private final ClientRegistration clientRegistration;
|
||||
|
||||
public OAuthClientCredentialsFeignManager(OAuth2AuthorizedClientManager manager, ClientRegistration clientRegistration) {
|
||||
this.manager = manager;
|
||||
this.clientRegistration = clientRegistration;
|
||||
this.principal = createPrincipal();
|
||||
}
|
||||
|
||||
private Authentication createPrincipal() {
|
||||
return new Authentication() {
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDetails() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthenticated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return clientRegistration.getClientId();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
try {
|
||||
OAuth2AuthorizeRequest oAuth2AuthorizeRequest = OAuth2AuthorizeRequest
|
||||
.withClientRegistrationId(clientRegistration.getRegistrationId())
|
||||
.principal(principal)
|
||||
.build();
|
||||
OAuth2AuthorizedClient client = manager.authorize(oAuth2AuthorizeRequest);
|
||||
if (isNull(client)) {
|
||||
throw new IllegalStateException("client credentials flow on " + clientRegistration.getRegistrationId() + " failed, client is null");
|
||||
}
|
||||
return client.getAccessToken().getTokenValue();
|
||||
} catch (Exception exp) {
|
||||
logger.error("client credentials error " + exp.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.baeldung.cloud.openfeign.oauthfeign;
|
||||
|
||||
import feign.RequestInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.oauth2.client.*;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
|
||||
@Configuration
|
||||
public class OAuthFeignConfig {
|
||||
|
||||
public static final String CLIENT_REGISTRATION_ID = "keycloak";
|
||||
|
||||
private final OAuth2AuthorizedClientService oAuth2AuthorizedClientService;
|
||||
private final ClientRegistrationRepository clientRegistrationRepository;
|
||||
|
||||
public OAuthFeignConfig(OAuth2AuthorizedClientService oAuth2AuthorizedClientService,
|
||||
ClientRegistrationRepository clientRegistrationRepository) {
|
||||
this.oAuth2AuthorizedClientService = oAuth2AuthorizedClientService;
|
||||
this.clientRegistrationRepository = clientRegistrationRepository;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RequestInterceptor requestInterceptor() {
|
||||
ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId(CLIENT_REGISTRATION_ID);
|
||||
OAuthClientCredentialsFeignManager clientCredentialsFeignManager =
|
||||
new OAuthClientCredentialsFeignManager(authorizedClientManager(), clientRegistration);
|
||||
return requestTemplate -> {
|
||||
requestTemplate.header("Authorization", "Bearer " + clientCredentialsFeignManager.getAccessToken());
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
OAuth2AuthorizedClientManager authorizedClientManager() {
|
||||
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
|
||||
.clientCredentials()
|
||||
.build();
|
||||
|
||||
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
|
||||
new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, oAuth2AuthorizedClientService);
|
||||
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
|
||||
return authorizedClientManager;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,3 +1,10 @@
|
|||
server.port=8085
|
||||
spring.main.allow-bean-definition-overriding=true
|
||||
spring.application.name= openfeign
|
||||
logging.level.com.baeldung.cloud.openfeign.client: DEBUG
|
||||
feign.hystrix.enabled=true
|
||||
|
||||
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=client_credentials
|
||||
spring.security.oauth2.client.registration.keycloak.client-id=payment-app
|
||||
spring.security.oauth2.client.registration.keycloak.client-secret=863e9de4-33d4-4471-b35e-f8d2434385bb
|
||||
spring.security.oauth2.client.provider.keycloak.token-uri=http://localhost:8083/auth/realms/master/protocol/openid-connect/token
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package com.baeldung.cloud.openfeign;
|
||||
|
||||
import com.baeldung.cloud.openfeign.client.PaymentClient;
|
||||
import com.baeldung.cloud.openfeign.model.Payment;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class PaymentClientUnitTest {
|
||||
|
||||
@Autowired
|
||||
private PaymentClient paymentClient;
|
||||
|
||||
@Test
|
||||
public void whenGetPayment_thenListPayments() {
|
||||
|
||||
List<Payment> payments = paymentClient.getPayments();
|
||||
|
||||
assertFalse(payments.isEmpty());
|
||||
}
|
||||
|
||||
}
|
|
@ -64,11 +64,6 @@
|
|||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-commons</artifactId>
|
||||
</dependency>
|
||||
<!-- deployment -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</dependency>
|
||||
<!-- web -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
|
@ -154,17 +149,9 @@
|
|||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.cargo</groupId>
|
||||
<artifactId>cargo-maven2-plugin</artifactId>
|
||||
<version>${cargo-maven2-plugin.version}</version>
|
||||
<artifactId>cargo-maven3-plugin</artifactId>
|
||||
<version>${cargo-maven3-plugin.version}</version>
|
||||
<configuration>
|
||||
<wait>true</wait>
|
||||
<container>
|
||||
<containerId>jetty8x</containerId>
|
||||
<type>embedded</type>
|
||||
<systemProperties>
|
||||
<!-- <provPersistenceTarget>cargo</provPersistenceTarget> -->
|
||||
</systemProperties>
|
||||
</container>
|
||||
<configuration>
|
||||
<properties>
|
||||
<cargo.servlet.port>8082</cargo.servlet.port>
|
||||
|
@ -194,15 +181,32 @@
|
|||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>live</id>
|
||||
<id>cargo-integration</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>none</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*LiveTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.cargo</groupId>
|
||||
<artifactId>cargo-maven2-plugin</artifactId>
|
||||
<configuration>
|
||||
<wait>false</wait>
|
||||
</configuration>
|
||||
<artifactId>cargo-maven3-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>start-server</id>
|
||||
|
@ -232,7 +236,7 @@
|
|||
<!-- util -->
|
||||
<javassist.version>3.25.0-GA</javassist.version>
|
||||
<!-- Maven plugins -->
|
||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||
<cargo-maven3-plugin.version>1.9.9</cargo-maven3-plugin.version>
|
||||
<apt-maven-plugin.version>1.1.3</apt-maven-plugin.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.cargo;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class CargoPluginLiveTest {
|
||||
|
||||
@Test
|
||||
void givenCargoProfile_expectTestRuns() {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue