Merge branch 'eugenp:master' into JAVA-26280
This commit is contained in:
commit
ef027438e9
|
@ -0,0 +1,129 @@
|
|||
package com.baeldung.algorithms.connect4;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GameBoard {
|
||||
private final List<List<Piece>> columns;
|
||||
|
||||
private final int rows;
|
||||
|
||||
public GameBoard(int columns, int rows) {
|
||||
this.rows = rows;
|
||||
this.columns = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < columns; ++i) {
|
||||
this.columns.add(new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
public int getRows() {
|
||||
return rows;
|
||||
}
|
||||
|
||||
public int getColumns() {
|
||||
return columns.size();
|
||||
}
|
||||
|
||||
public Piece getCell(int x, int y) {
|
||||
assert(x >= 0 && x < getColumns());
|
||||
assert(y >= 0 && y < getRows());
|
||||
|
||||
List<Piece> column = columns.get(x);
|
||||
|
||||
if (column.size() > y) {
|
||||
return column.get(y);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean move(int x, Piece player) {
|
||||
assert(x >= 0 && x < getColumns());
|
||||
|
||||
List<Piece> column = columns.get(x);
|
||||
|
||||
if (column.size() >= this.rows) {
|
||||
throw new IllegalArgumentException("That column is full");
|
||||
}
|
||||
|
||||
column.add(player);
|
||||
|
||||
return checkWin(x, column.size() - 1, player);
|
||||
}
|
||||
|
||||
private boolean checkWin(int x, int y, Piece player) {
|
||||
// Vertical line
|
||||
if (checkLine(x, y, 0, -1, player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int offset = 0; offset < 4; ++offset) {
|
||||
// Horizontal line
|
||||
if (checkLine(x - 3 + offset, y, 1, 0, player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Leading diagonal
|
||||
if (checkLine(x - 3 + offset, y + 3 - offset, 1, -1, player)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Trailing diagonal
|
||||
if (checkLine(x - 3 + offset, y - 3 + offset, 1, 1, player)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkLine(int x1, int y1, int xDiff, int yDiff, Piece player) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int x = x1 + (xDiff * i);
|
||||
int y = y1 + (yDiff * i);
|
||||
|
||||
if (x < 0 || x > columns.size() - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (y < 0 || y > rows - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (player != getCell(x, y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (int y = getRows() - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < getColumns(); ++x) {
|
||||
Piece piece = getCell(x, y);
|
||||
|
||||
result.append("|");
|
||||
if (piece == null) {
|
||||
result.append(" ");
|
||||
} else if (piece == Piece.PLAYER_1) {
|
||||
result.append("X");
|
||||
} else if (piece == Piece.PLAYER_2) {
|
||||
result.append("O");
|
||||
}
|
||||
}
|
||||
|
||||
result.append("|\n");
|
||||
for (int i = 0; i < getColumns(); ++i) {
|
||||
result.append("+-");
|
||||
}
|
||||
result.append("+\n");
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.baeldung.algorithms.connect4;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class GameUnitTest {
|
||||
@Test
|
||||
public void blankGame() {
|
||||
GameBoard gameBoard = new GameBoard(8, 6);
|
||||
|
||||
System.out.println(gameBoard);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void playedGame() {
|
||||
GameBoard gameBoard = new GameBoard(8, 6);
|
||||
|
||||
assertFalse(gameBoard.move(3, Piece.PLAYER_1));
|
||||
assertFalse(gameBoard.move(2, Piece.PLAYER_2));
|
||||
|
||||
assertFalse(gameBoard.move(4, Piece.PLAYER_1));
|
||||
assertFalse(gameBoard.move(3, Piece.PLAYER_2));
|
||||
|
||||
assertFalse(gameBoard.move(5, Piece.PLAYER_1));
|
||||
assertFalse(gameBoard.move(6, Piece.PLAYER_2));
|
||||
|
||||
assertFalse(gameBoard.move(5, Piece.PLAYER_1));
|
||||
assertFalse(gameBoard.move(4, Piece.PLAYER_2));
|
||||
|
||||
assertFalse(gameBoard.move(5, Piece.PLAYER_1));
|
||||
assertFalse(gameBoard.move(5, Piece.PLAYER_2));
|
||||
|
||||
assertFalse(gameBoard.move(6, Piece.PLAYER_1));
|
||||
assertTrue(gameBoard.move(4, Piece.PLAYER_2));
|
||||
|
||||
System.out.println(gameBoard);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.baeldung.algorithms.connect4;
|
||||
|
||||
public enum Piece {
|
||||
PLAYER_1,
|
||||
PLAYER_2
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package com.baeldung.rounddate;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
public class RoundDate {
|
||||
public static Date getDate(int year, int month, int day, int hour, int minute) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.YEAR, year);
|
||||
calendar.set(Calendar.MONTH, month);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, day);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour);
|
||||
calendar.set(Calendar.MINUTE, minute);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static Date roundToDay(Date date) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static Date roundToNearestUnit(Date date, int unit) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
|
||||
switch (unit) {
|
||||
case Calendar.HOUR:
|
||||
int minute = calendar.get(Calendar.MINUTE);
|
||||
if (minute >= 0 && minute < 15) {
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
} else if (minute >= 15 && minute < 45) {
|
||||
calendar.set(Calendar.MINUTE, 30);
|
||||
} else {
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.add(Calendar.HOUR_OF_DAY, 1);
|
||||
}
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
break;
|
||||
|
||||
case Calendar.DAY_OF_MONTH:
|
||||
int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
||||
if (hour >= 12) {
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
break;
|
||||
|
||||
case Calendar.MONTH:
|
||||
int day = calendar.get(Calendar.DAY_OF_MONTH);
|
||||
if (day >= 15) {
|
||||
calendar.add(Calendar.MONTH, 1);
|
||||
}
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static LocalDateTime roundToStartOfMonthUsingLocalDateTime(LocalDateTime dateTime) {
|
||||
return dateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
}
|
||||
|
||||
public static LocalDateTime roundToEndOfWeekUsingLocalDateTime(LocalDateTime dateTime) {
|
||||
return dateTime.with(TemporalAdjusters.next(DayOfWeek.SATURDAY))
|
||||
.withHour(23)
|
||||
.withMinute(59)
|
||||
.withSecond(59)
|
||||
.withNano(999);
|
||||
}
|
||||
|
||||
public static ZonedDateTime roundToStartOfMonthUsingZonedDateTime(ZonedDateTime dateTime) {
|
||||
return dateTime.withDayOfMonth(1)
|
||||
.withHour(0)
|
||||
.withMinute(0)
|
||||
.withSecond(0)
|
||||
.with(ChronoField.MILLI_OF_SECOND, 0)
|
||||
.with(ChronoField.MICRO_OF_SECOND, 0)
|
||||
.with(ChronoField.NANO_OF_SECOND, 0);
|
||||
}
|
||||
|
||||
public static ZonedDateTime roundToEndOfWeekUsingZonedDateTime(ZonedDateTime dateTime) {
|
||||
return dateTime.with(TemporalAdjusters.next(DayOfWeek.SATURDAY))
|
||||
.withHour(23)
|
||||
.withMinute(59)
|
||||
.withSecond(59)
|
||||
.with(ChronoField.MILLI_OF_SECOND, 999)
|
||||
.with(ChronoField.MICRO_OF_SECOND, 999)
|
||||
.with(ChronoField.NANO_OF_SECOND, 999);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.baeldung.rounddate;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class DateRoundingUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenDate_whenRoundToDay_thenBeginningOfDay() {
|
||||
Date date = RoundDate.getDate(2023, Calendar.JANUARY, 27, 14, 30);
|
||||
Date result = RoundDate.roundToDay(date);
|
||||
assertEquals(RoundDate.getDate(2023, Calendar.JANUARY, 27, 0, 0), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDate_whenRoundToNearestUnit_thenNearestUnit() {
|
||||
Date date = RoundDate.getDate(2023, Calendar.JANUARY, 27, 14, 12);
|
||||
Date result = RoundDate.roundToNearestUnit(date, Calendar.DAY_OF_MONTH);
|
||||
Date expected = RoundDate.getDate(2023, Calendar.JANUARY, 28, 0, 0);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLocalDateTime_whenRoundToStartOfMonth_thenStartOfMonth() {
|
||||
LocalDateTime dateTime = LocalDateTime.of(2023, 1, 27, 14, 12);
|
||||
LocalDateTime result = RoundDate.roundToStartOfMonthUsingLocalDateTime(dateTime);
|
||||
LocalDateTime expected = LocalDateTime.of(2023, 1, 1, 0, 0, 0);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void givenZonedDateTime_whenRoundToStartOfMonth_thenStartOfMonth() {
|
||||
ZonedDateTime dateTime = ZonedDateTime.of(2023, 1, 27, 14, 12, 0, 0, ZoneId.systemDefault());
|
||||
ZonedDateTime result = RoundDate.roundToStartOfMonthUsingZonedDateTime(dateTime);
|
||||
ZonedDateTime expected = ZonedDateTime.of(2023, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault());
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLocalDateTime_whenRoundToEndOfWeek_thenEndOfWeek() {
|
||||
LocalDateTime dateTime = LocalDateTime.of(2023, 1, 27, 14, 12);
|
||||
LocalDateTime result = RoundDate.roundToEndOfWeekUsingLocalDateTime(dateTime);
|
||||
LocalDateTime expected = LocalDateTime.of(2023, 1, 28, 23, 59, 59, 999);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenZonedDateTime_whenRoundToEndOfWeek_thenEndOfWeek() {
|
||||
ZonedDateTime dateTime = ZonedDateTime.of(2023, 1, 27, 14, 12, 0, 0, ZoneId.systemDefault());
|
||||
ZonedDateTime result = RoundDate.roundToEndOfWeekUsingZonedDateTime(dateTime);
|
||||
ZonedDateTime expected = ZonedDateTime.of(2023, 1, 28, 23, 59, 59, 999, ZoneId.systemDefault());
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
}
|
|
@ -79,5 +79,18 @@
|
|||
<version>1.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>
|
||||
--add-opens java.base/java.util=ALL-UNNAMED
|
||||
</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package com.baeldung.map.linkedhashmapfirstandlastentry;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class GetFirstAndLastEntryFromLinkedHashMapUnitTest {
|
||||
private static final LinkedHashMap<String, String> THE_MAP = new LinkedHashMap<>();
|
||||
|
||||
static {
|
||||
THE_MAP.put("key one", "a1 b1 c1");
|
||||
THE_MAP.put("key two", "a2 b2 c2");
|
||||
THE_MAP.put("key three", "a3 b3 c3");
|
||||
THE_MAP.put("key four", "a4 b4 c4");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenIteratingEntrySet_thenGetExpectedResult() {
|
||||
Entry<String, String> firstEntry = THE_MAP.entrySet().iterator().next();
|
||||
assertEquals("key one", firstEntry.getKey());
|
||||
assertEquals("a1 b1 c1", firstEntry.getValue());
|
||||
|
||||
Entry<String, String> lastEntry = null;
|
||||
Iterator<Entry<String, String>> it = THE_MAP.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
lastEntry = it.next();
|
||||
}
|
||||
|
||||
assertNotNull(lastEntry);
|
||||
assertEquals("key four", lastEntry.getKey());
|
||||
assertEquals("a4 b4 c4", lastEntry.getValue());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenConvertingEntriesToArray_thenGetExpectedResult() {
|
||||
|
||||
Entry<String, String>[] theArray = new Entry[THE_MAP.size()];
|
||||
THE_MAP.entrySet().toArray(theArray);
|
||||
|
||||
Entry<String, String> firstEntry = theArray[0];
|
||||
assertEquals("key one", firstEntry.getKey());
|
||||
assertEquals("a1 b1 c1", firstEntry.getValue());
|
||||
|
||||
Entry<String, String> lastEntry = theArray[THE_MAP.size() - 1];
|
||||
assertEquals("key four", lastEntry.getKey());
|
||||
assertEquals("a4 b4 c4", lastEntry.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingStreamAPI_thenGetExpectedResult() {
|
||||
Entry<String, String> firstEntry = THE_MAP.entrySet().stream().findFirst().get();
|
||||
assertEquals("key one", firstEntry.getKey());
|
||||
assertEquals("a1 b1 c1", firstEntry.getValue());
|
||||
|
||||
Entry<String, String> lastEntry = THE_MAP.entrySet().stream().skip(THE_MAP.size() - 1).findFirst().get();
|
||||
|
||||
assertNotNull(lastEntry);
|
||||
assertEquals("key four", lastEntry.getKey());
|
||||
assertEquals("a4 b4 c4", lastEntry.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingReflection_thenGetExpectedResult() throws NoSuchFieldException, IllegalAccessException {
|
||||
Field head = THE_MAP.getClass().getDeclaredField("head");
|
||||
head.setAccessible(true);
|
||||
Entry<String, String> firstEntry = (Entry<String, String>) head.get(THE_MAP);
|
||||
assertEquals("key one", firstEntry.getKey());
|
||||
assertEquals("a1 b1 c1", firstEntry.getValue());
|
||||
|
||||
Field tail = THE_MAP.getClass().getDeclaredField("tail");
|
||||
tail.setAccessible(true);
|
||||
Entry<String, String> lastEntry = (Entry<String, String>) tail.get(THE_MAP);
|
||||
assertEquals("key four", lastEntry.getKey());
|
||||
assertEquals("a4 b4 c4", lastEntry.getValue());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.baeldung.generictype;
|
||||
|
||||
/**
|
||||
* @param <T> The type of the first value in the {@code Pair<T,S>}.
|
||||
* @param <S> The type of the second value in the {@code Pair<T,S>}.
|
||||
*/
|
||||
|
||||
public class Pair<T, S> {
|
||||
public T first;
|
||||
public S second;
|
||||
|
||||
/**
|
||||
* Constructs a new Pair object with the specified values.
|
||||
*
|
||||
* @param a The first value.
|
||||
* @param b The second value.
|
||||
*/
|
||||
|
||||
public Pair(T a, S b) {
|
||||
first = a;
|
||||
second = b;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.baeldung.jndi;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.jndi.JndiTemplate;
|
||||
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
|
||||
|
||||
import javax.naming.*;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import java.util.Enumeration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class JndiNamingUnitTest {
|
||||
|
||||
private static InitialContext context;
|
||||
private static DriverManagerDataSource dataSource;
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() throws Exception {
|
||||
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
|
||||
dataSource = new DriverManagerDataSource("jdbc:h2:mem:mydb");
|
||||
builder.activate();
|
||||
|
||||
JndiTemplate jndiTemplate = new JndiTemplate();
|
||||
context = (InitialContext) jndiTemplate.getContext();
|
||||
|
||||
dataSource.setDriverClassName("org.h2.Driver");
|
||||
context.bind("java:comp/env/jdbc/datasource", dataSource);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenACompositeName_whenAddingAnElement_thenNameIsAdded() throws Exception {
|
||||
Name objectName = new CompositeName("java:comp/env/jdbc");
|
||||
|
||||
Enumeration<String> items = objectName.getAll();
|
||||
while(items.hasMoreElements()) {
|
||||
System.out.println(items.nextElement());
|
||||
}
|
||||
|
||||
objectName.add("New Name");
|
||||
|
||||
assertEquals("env", objectName.get(1));
|
||||
assertEquals("New Name", objectName.get(objectName.size() - 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenContext_whenLookupByName_thenReturnsValidObject() throws Exception {
|
||||
DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/datasource");
|
||||
|
||||
assertNotNull(ds);
|
||||
assertNotNull(ds.getConnection());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenSubContext_whenLookupByName_thenReturnsValidObject() throws Exception {
|
||||
Context subContext = (Context) context.lookup("java:comp/env");
|
||||
DataSource ds = (DataSource) subContext.lookup("jdbc/datasource");
|
||||
|
||||
assertNotNull(ds);
|
||||
assertNotNull(ds.getConnection());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDown() throws Exception {
|
||||
context.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package com.baeldung.genericnumberscomparator;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class GenericNumbersComparatorUnitTest {
|
||||
|
||||
public int compareDouble(Number num1, Number num2) {
|
||||
return Double.compare(num1.doubleValue(), num2.doubleValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseCompareDouble_thenWillExecuteComparison() {
|
||||
assertEquals(0, compareDouble(5, 5.0));
|
||||
}
|
||||
|
||||
public int compareTo(Integer int1, Integer int2) {
|
||||
return int1.compareTo(int2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseCompareTo_thenWillExecuteComparison() {
|
||||
assertEquals(-1, compareTo(5, 7));
|
||||
}
|
||||
|
||||
Map<Class<? extends Number>, BiFunction<Number, Number, Integer>> comparisonMap = new HashMap<>();
|
||||
|
||||
public int compareUsingMap(Number num1, Number num2) {
|
||||
comparisonMap.put(Integer.class, (a, b) -> ((Integer) num1).compareTo((Integer) num2));
|
||||
|
||||
return comparisonMap.get(num1.getClass())
|
||||
.apply(num1, num2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseCompareUsingMap_thenWillExecuteComparison() {
|
||||
assertEquals(-1, compareUsingMap(5, 7));
|
||||
}
|
||||
|
||||
public interface NumberComparator {
|
||||
int compare(Number num1, Number num2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseProxy_thenWillExecuteComparison() {
|
||||
NumberComparator proxy = (NumberComparator) Proxy.newProxyInstance(NumberComparator.class.getClassLoader(), new Class[] { NumberComparator.class },
|
||||
(p, method, args) -> Double.compare(((Number) args[0]).doubleValue(), ((Number) args[1]).doubleValue()));
|
||||
assertEquals(0, proxy.compare(5, 5.0));
|
||||
}
|
||||
|
||||
public int compareUsingReflection(Number num1, Number num2) throws Exception {
|
||||
Method method = num1.getClass()
|
||||
.getMethod("compareTo", num1.getClass());
|
||||
return (int) method.invoke(num1, num2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseCompareUsingReflection_thenWillExecuteComparison() throws Exception {
|
||||
assertEquals(-1, compareUsingReflection(5, 7));
|
||||
}
|
||||
|
||||
interface NumberComparatorFactory {
|
||||
Comparator<Number> getComparator();
|
||||
}
|
||||
|
||||
class IntegerComparatorFactory implements NumberComparatorFactory {
|
||||
@Override
|
||||
public Comparator<Number> getComparator() {
|
||||
return (num1, num2) -> ((Integer) num1).compareTo((Integer) num2);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseComparatorFactory_thenWillExecuteComparison() {
|
||||
NumberComparatorFactory factory = new IntegerComparatorFactory();
|
||||
Comparator<Number> comparator = factory.getComparator();
|
||||
assertEquals(-1, comparator.compare(5, 7));
|
||||
}
|
||||
|
||||
Function<Number, Double> toDouble = Number::doubleValue;
|
||||
BiPredicate<Number, Number> isEqual = (num1, num2) -> toDouble.apply(num1)
|
||||
.equals(toDouble.apply(num2));
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseIsEqual_thenWillExecuteComparison() {
|
||||
assertEquals(true, isEqual.test(5, 5.0));
|
||||
}
|
||||
|
||||
private Number someNumber = 5;
|
||||
private Number anotherNumber = 5.0;
|
||||
|
||||
Optional<Number> optNum1 = Optional.ofNullable(someNumber);
|
||||
Optional<Number> optNum2 = Optional.ofNullable(anotherNumber);
|
||||
int comparisonResult = optNum1.flatMap(n1 -> optNum2.map(n2 -> Double.compare(n1.doubleValue(), n2.doubleValue())))
|
||||
.orElse(0);
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseComparisonResult_thenWillExecuteComparison() {
|
||||
assertEquals(0, comparisonResult);
|
||||
}
|
||||
|
||||
private boolean someCondition = true;
|
||||
Function<Number, ?> dynamicFunction = someCondition ? Number::doubleValue : Number::intValue;
|
||||
Comparator<Number> dynamicComparator = (num1, num2) -> ((Comparable) dynamicFunction.apply(num1)).compareTo(dynamicFunction.apply(num2));
|
||||
|
||||
@Test
|
||||
void givenNumbers_whenUseDynamicComparator_thenWillExecuteComparison() {
|
||||
assertEquals(0, dynamicComparator.compare(5, 5.0));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.baeldung.optionalsasparameterrecords;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public record Product(String name, double price, Optional<String> description) {
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.optionalsasparameterrecords;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class OptionalAsRecordParameterUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenRecordCreationWithOptional_thenCreateItProperly() {
|
||||
var emptyDescriptionProduct = new Product("television", 1699.99, Optional.empty());
|
||||
Assertions.assertEquals("television", emptyDescriptionProduct.name());
|
||||
Assertions.assertEquals(1699.99, emptyDescriptionProduct.price());
|
||||
Assertions.assertNull(emptyDescriptionProduct.description().orElse(null));
|
||||
}
|
||||
}
|
|
@ -85,7 +85,7 @@ public class AlphanumericPerformanceBenchmark {
|
|||
|
||||
public boolean isAlphanumeric(final int codePoint) {
|
||||
return (codePoint >= 65 && codePoint <= 90) ||
|
||||
(codePoint >= 97 && codePoint <= 172) ||
|
||||
(codePoint >= 97 && codePoint <= 122) ||
|
||||
(codePoint >= 48 && codePoint <= 57);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.mutablestrings;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
|
||||
public class CharsetUsageExample {
|
||||
|
||||
public ByteBuffer encodeString(String inputString) {
|
||||
Charset charset = Charset.forName("UTF-8");
|
||||
CharsetEncoder encoder = charset.newEncoder();
|
||||
|
||||
CharBuffer charBuffer = CharBuffer.wrap(inputString);
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(50);
|
||||
|
||||
encoder.encode(charBuffer, byteBuffer, true); // true indicates the end of input
|
||||
byteBuffer.flip();
|
||||
return byteBuffer;
|
||||
}
|
||||
|
||||
public String decodeString(ByteBuffer byteBuffer) {
|
||||
Charset charset = Charset.forName("UTF-8");
|
||||
CharsetDecoder decoder = charset.newDecoder();
|
||||
CharBuffer decodedCharBuffer = CharBuffer.allocate(50);
|
||||
decoder.decode(byteBuffer, decodedCharBuffer, true);
|
||||
decodedCharBuffer.flip();
|
||||
|
||||
return decodedCharBuffer.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.baeldung.mutablestrings;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class MutableStringUsingCharset {
|
||||
|
||||
private final AtomicReference<CharBuffer> cbRef = new AtomicReference<>();
|
||||
private final Charset myCharset = new Charset("mycharset", null) {
|
||||
@Override
|
||||
public boolean contains(Charset cs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharsetDecoder newDecoder() {
|
||||
return new CharsetDecoder(this, 1.0f, 1.0f) {
|
||||
@Override
|
||||
protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
|
||||
cbRef.set(out);
|
||||
while (in.remaining() > 0) {
|
||||
out.append((char) in.get());
|
||||
}
|
||||
return CoderResult.UNDERFLOW;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharsetEncoder newEncoder() {
|
||||
CharsetEncoder cd = new CharsetEncoder(this, 1.0f, 1.0f) {
|
||||
@Override
|
||||
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
|
||||
while (in.hasRemaining()) {
|
||||
if (!out.hasRemaining()) {
|
||||
return CoderResult.OVERFLOW;
|
||||
}
|
||||
char currentChar = in.get();
|
||||
if (currentChar > 127) {
|
||||
return CoderResult.unmappableForLength(1);
|
||||
}
|
||||
out.put((byte) currentChar);
|
||||
}
|
||||
return CoderResult.UNDERFLOW;
|
||||
}
|
||||
};
|
||||
return cd;
|
||||
}
|
||||
};
|
||||
|
||||
public String createModifiableString(String s) {
|
||||
return new String(s.getBytes(), myCharset);
|
||||
}
|
||||
|
||||
public void modifyString() {
|
||||
CharBuffer cb = cbRef.get();
|
||||
cb.position(0);
|
||||
cb.put("xyz");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.baeldung.mutablestrings;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import com.google.errorprone.annotations.DoNotCall;
|
||||
|
||||
public class MutableStrings {
|
||||
|
||||
/**
|
||||
* This involves using Reflection to change String fields and it is not encouraged to use this in programs.
|
||||
* @throws NoSuchFieldException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
@DoNotCall
|
||||
public void mutableUsingReflection() throws NoSuchFieldException, IllegalAccessException {
|
||||
String myString = "Hello World";
|
||||
String otherString = new String("Hello World");
|
||||
Field f = String.class.getDeclaredField("value");
|
||||
f.setAccessible(true);
|
||||
f.set(myString, "Hi World".toCharArray());
|
||||
System.out.println(otherString);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.mutablestring;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.mutablestrings.CharsetUsageExample;
|
||||
|
||||
public class CharsetUsageUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenCharset_whenStringIsEncodedAndDecoded_thenGivesCorrectResult() {
|
||||
CharsetUsageExample ch = new CharsetUsageExample();
|
||||
String inputString = "hello दुनिया";
|
||||
String result = ch.decodeString(ch.encodeString(inputString));
|
||||
Assertions.assertEquals(inputString, result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.baeldung.mutablestring;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.mutablestrings.MutableStringUsingCharset;
|
||||
|
||||
public class MutableStringUsingCharsetUnitTest {
|
||||
@Test
|
||||
@Disabled
|
||||
/**
|
||||
* This test is disabled as it works well for Java 8 and below
|
||||
*/
|
||||
public void givenCustomCharSet_whenStringUpdated_StringGetsMutated() throws Exception {
|
||||
MutableStringUsingCharset ms = new MutableStringUsingCharset();
|
||||
String s = ms.createModifiableString("Hello");
|
||||
Assert.assertEquals("Hello", s);
|
||||
ms.modifyString();
|
||||
Assert.assertEquals("something", s);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,3 +14,4 @@ Listed here there are only those articles that does not fit into other core-java
|
|||
- [Java String Interview Questions and Answers](https://www.baeldung.com/java-string-interview-questions)
|
||||
- [Java Multi-line String](https://www.baeldung.com/java-multiline-string)
|
||||
- [Reuse StringBuilder for Efficiency](https://www.baeldung.com/java-reuse-stringbuilder-for-efficiency)
|
||||
- [How to Iterate Over the String Characters in Java](https://www.baeldung.com/java-iterate-string-characters)
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package com.baeldung.stringIterator;
|
||||
|
||||
import java.text.*;
|
||||
import java.util.*;
|
||||
|
||||
public class StringIterator {
|
||||
|
||||
public static String javaCharArray(String str){
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (char c : str.toCharArray()) {
|
||||
result.append(c);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String javaforLoop(String str) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char c = str.charAt(i);
|
||||
result.append(c);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String java8forEach(String str){
|
||||
StringBuilder result = new StringBuilder();
|
||||
str.chars().forEach(name -> {
|
||||
result.append((char) name);
|
||||
});
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String javaCharacterIterator(String str){
|
||||
StringBuilder result = new StringBuilder();
|
||||
CharacterIterator it = new StringCharacterIterator(str);
|
||||
while (it.current() != CharacterIterator.DONE) {
|
||||
result.append(it.current());
|
||||
it.next();
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.baeldung.stringIterator;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class StringIteratorTest {
|
||||
|
||||
@Test
|
||||
public void whenUseCharArrayMethod_thenIterate() {
|
||||
String input = "Hello, Baeldung!";
|
||||
String expectedOutput = "Hello, Baeldung!";
|
||||
String result = StringIterator.javaCharArray(input);
|
||||
assertEquals(expectedOutput, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUseJavaForLoop_thenIterate() {
|
||||
String input = "Hello, Baeldung!";
|
||||
String expectedOutput = "Hello, Baeldung!";
|
||||
String result = StringIterator.javaForLoop(input);
|
||||
assertEquals(expectedOutput, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUseForEachMethod_thenIterate() {
|
||||
String input = "Hello, Baeldung!";
|
||||
String expectedOutput = "Hello, Baeldung!";
|
||||
String result = StringIterator.java8ForEach(input);
|
||||
assertEquals(expectedOutput, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUseCharacterIterator_thenIterate() {
|
||||
String input = "Hello, Baeldung!";
|
||||
String expectedOutput = "Hello, Baeldung!";
|
||||
String result = StringIterator.javaCharacterIterator(input);
|
||||
assertEquals(expectedOutput, result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
version: '3'
|
||||
services:
|
||||
frontend:
|
||||
build: ./frontend
|
||||
ports:
|
||||
- "80:80"
|
||||
zookeeper:
|
||||
image: confluentinc/cp-zookeeper:latest
|
||||
environment:
|
||||
ZOOKEEPER_CLIENT_PORT: 2181
|
||||
ZOOKEEPER_TICK_TIME: 2000
|
||||
ports:
|
||||
- 22181:2181
|
||||
kafka:
|
||||
image: confluentinc/cp-kafka:latest
|
||||
container_name: kafka-broker
|
||||
depends_on:
|
||||
- zookeeper
|
||||
ports:
|
||||
- 29092:29092
|
||||
environment:
|
||||
KAFKA_BROKER_ID: 1
|
||||
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
|
||||
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka-broker:9092,PLAINTEXT_HOST://localhost:29092
|
||||
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
|
||||
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
|
||||
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
|
||||
mongodb:
|
||||
container_name: mongo-db
|
||||
image: mongo:6.0
|
||||
volumes:
|
||||
- ~/mongo:/data/db
|
||||
ports:
|
||||
- "27017:27017"
|
||||
healthcheck:
|
||||
test: exit 0
|
||||
order-service:
|
||||
build: ./order-service
|
||||
ports:
|
||||
- "8080:8080"
|
||||
depends_on:
|
||||
mongodb:
|
||||
condition: service_healthy
|
||||
inventory-service:
|
||||
build: ./inventory-service
|
||||
ports:
|
||||
- "8081:8081"
|
||||
depends_on:
|
||||
mongodb:
|
||||
condition: service_healthy
|
||||
shipping-service:
|
||||
build: ./shipping-service
|
||||
ports:
|
||||
- "8082:8082"
|
||||
depends_on:
|
||||
mongodb:
|
||||
condition: service_healthy
|
|
@ -1,3 +1,3 @@
|
|||
FROM openjdk:8-jdk-alpine
|
||||
COPY target/inventory-service-async-0.0.1-SNAPSHOT.jar app.jar
|
||||
COPY target/inventory-service-0.0.1-SNAPSHOT.jar app.jar
|
||||
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=docker","/app.jar"]
|
|
@ -1,3 +1,3 @@
|
|||
FROM openjdk:8-jdk-alpine
|
||||
COPY target/order-service-async-0.0.1-SNAPSHOT.jar app.jar
|
||||
COPY target/order-service-0.0.1-SNAPSHOT.jar app.jar
|
||||
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=docker","/app.jar"]
|
|
@ -1,3 +1,3 @@
|
|||
FROM openjdk:8-jdk-alpine
|
||||
COPY target/shipping-service-async-0.0.1-SNAPSHOT.jar app.jar
|
||||
COPY target/shipping-service-0.0.1-SNAPSHOT.jar app.jar
|
||||
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=docker","/app.jar"]
|
|
@ -26,6 +26,11 @@
|
|||
<version>${reactor.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor.addons</groupId>
|
||||
<artifactId>reactor-extra</artifactId>
|
||||
<version>${reactor.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
@ -35,7 +40,7 @@
|
|||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<reactor.version>3.4.17</reactor.version>
|
||||
<reactor.version>3.5.1</reactor.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,48 @@
|
|||
package com.baeldung.math;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import reactor.math.MathFlux;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
public class MathFluxOperationsUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenFluxOfNumbers_whenCalculatingSum_thenExpectCorrectResult() {
|
||||
Flux<Integer> numbers = Flux.just(1, 2, 3, 4, 5);
|
||||
Mono<Integer> sumMono = MathFlux.sumInt(numbers);
|
||||
StepVerifier.create(sumMono)
|
||||
.expectNext(15)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFluxOfNumbers_whenCalculatingAverage_thenExpectCorrectResult() {
|
||||
Flux<Integer> numbers = Flux.just(1, 2, 3, 4, 5);
|
||||
Mono<Double> averageMono = MathFlux.averageDouble(numbers);
|
||||
StepVerifier.create(averageMono)
|
||||
.expectNext(3.0)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFluxOfNumbers_whenFindingMinElement_thenExpectCorrectResult() {
|
||||
Flux<Integer> numbers = Flux.just(3, 1, 5, 2, 4);
|
||||
Mono<Integer> minMono = MathFlux.min(numbers);
|
||||
StepVerifier.create(minMono)
|
||||
.expectNext(1)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFluxOfNumbers_whenFindingMaxElement_thenExpectCorrectResult() {
|
||||
Flux<Integer> numbers = Flux.just(3, 1, 5, 2, 4);
|
||||
Mono<Integer> maxMono = MathFlux.max(numbers);
|
||||
StepVerifier.create(maxMono)
|
||||
.expectNext(5)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
}
|
|
@ -91,6 +91,10 @@
|
|||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>${aspectjweaver.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.restvalidation;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackages = { "com.baeldung.restvalidation" })
|
||||
public class RestValidationApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(RestValidationApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.baeldung.restvalidation.config;
|
||||
|
||||
import javax.validation.MessageInterpolator;
|
||||
|
||||
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
import org.springframework.validation.beanvalidation.MessageSourceResourceBundleLocator;
|
||||
|
||||
@Configuration
|
||||
public class MessageConfig {
|
||||
|
||||
@Bean
|
||||
public MessageSource messageSource() {
|
||||
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
|
||||
messageSource.setBasename("classpath:CustomValidationMessages");
|
||||
messageSource.setDefaultEncoding("UTF-8");
|
||||
return messageSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageInterpolator getMessageInterpolator(MessageSource messageSource) {
|
||||
MessageSourceResourceBundleLocator resourceBundleLocator = new MessageSourceResourceBundleLocator(messageSource);
|
||||
ResourceBundleMessageInterpolator messageInterpolator = new ResourceBundleMessageInterpolator(resourceBundleLocator);
|
||||
return new RecursiveLocaleContextMessageInterpolator(messageInterpolator);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalValidatorFactoryBean getValidator(MessageInterpolator messageInterpolator) {
|
||||
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
|
||||
bean.setMessageInterpolator(messageInterpolator);
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.baeldung.restvalidation.config;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.validation.MessageInterpolator;
|
||||
|
||||
import org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator;
|
||||
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
|
||||
|
||||
public class RecursiveLocaleContextMessageInterpolator extends AbstractMessageInterpolator {
|
||||
|
||||
private static final Pattern PATTERN_PLACEHOLDER = Pattern.compile("\\{([^}]+)\\}");
|
||||
|
||||
private final MessageInterpolator interpolator;
|
||||
|
||||
public RecursiveLocaleContextMessageInterpolator(ResourceBundleMessageInterpolator interpolator) {
|
||||
this.interpolator = interpolator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String interpolate(MessageInterpolator.Context context, Locale locale, String message) {
|
||||
int level = 0;
|
||||
while (containsPlaceholder(message) && (level++ < 2)) {
|
||||
message = this.interpolator.interpolate(message, context, locale);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
private boolean containsPlaceholder(String code) {
|
||||
Matcher matcher = PATTERN_PLACEHOLDER.matcher(code);
|
||||
return matcher.find();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.baeldung.restvalidation.response;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class InputFieldError {
|
||||
private String field;
|
||||
private String message;
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung.restvalidation.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class UpdateUserResponse {
|
||||
|
||||
private List<InputFieldError> fieldErrors;
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.restvalidation.service1;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class User {
|
||||
|
||||
@NotEmpty
|
||||
private String email;
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.baeldung.restvalidation.service1;
|
||||
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.baeldung.restvalidation.response.InputFieldError;
|
||||
import com.baeldung.restvalidation.response.UpdateUserResponse;
|
||||
|
||||
@RestController
|
||||
public class UserService1 {
|
||||
|
||||
@PutMapping(value = "/user1", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<UpdateUserResponse> updateUser(@RequestBody @Valid User user,
|
||||
BindingResult bindingResult) {
|
||||
if (bindingResult.hasFieldErrors()) {
|
||||
|
||||
List<InputFieldError> fieldErrorList = bindingResult.getFieldErrors().stream()
|
||||
.map(error -> new InputFieldError(error.getField(), error.getDefaultMessage()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
UpdateUserResponse updateResponse = new UpdateUserResponse(fieldErrorList);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(updateResponse);
|
||||
}
|
||||
else {
|
||||
// Update logic...
|
||||
return ResponseEntity.status(HttpStatus.OK).build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.restvalidation.service2;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class User {
|
||||
|
||||
@NotEmpty(message = "{validation.email.notEmpty}")
|
||||
private String email;
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.baeldung.restvalidation.service2;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.restvalidation.response.InputFieldError;
|
||||
import com.baeldung.restvalidation.response.UpdateUserResponse;
|
||||
|
||||
@RestController
|
||||
public class UserService2 {
|
||||
|
||||
@PutMapping(value = "/user2", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<UpdateUserResponse> updateUser(@RequestBody @Valid User user,
|
||||
BindingResult bindingResult) {
|
||||
if (bindingResult.hasFieldErrors()) {
|
||||
|
||||
List<InputFieldError> fieldErrorList = bindingResult.getFieldErrors().stream()
|
||||
.map(error -> new InputFieldError(error.getField(), error.getDefaultMessage()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
UpdateUserResponse updateResponse = new UpdateUserResponse(fieldErrorList);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(updateResponse);
|
||||
}
|
||||
else {
|
||||
// Update logic...
|
||||
return ResponseEntity.status(HttpStatus.OK).build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.baeldung.restvalidation.service3;
|
||||
|
||||
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
|
||||
import static java.lang.annotation.ElementType.CONSTRUCTOR;
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.ElementType.PARAMETER;
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
|
||||
@Documented
|
||||
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
|
||||
@Retention(RUNTIME)
|
||||
@Constraint(validatedBy = { FieldNotEmptyValidator.class })
|
||||
public @interface FieldNotEmpty {
|
||||
|
||||
String message() default "{validation.notEmpty}";
|
||||
|
||||
String field() default "Field";
|
||||
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.restvalidation.service3;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
public class FieldNotEmptyValidator implements ConstraintValidator<FieldNotEmpty, Object> {
|
||||
|
||||
private String message;
|
||||
private String field;
|
||||
|
||||
@Override
|
||||
public boolean isValid(Object value, ConstraintValidatorContext context) {
|
||||
return (value != null && !value.toString().trim().isEmpty());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.restvalidation.service3;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class User {
|
||||
|
||||
@FieldNotEmpty(message = "{validation.notEmpty}", field = "{field.personalEmail}")
|
||||
private String email;
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.baeldung.restvalidation.service3;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.restvalidation.response.InputFieldError;
|
||||
import com.baeldung.restvalidation.response.UpdateUserResponse;
|
||||
|
||||
@RestController
|
||||
public class UserService3 {
|
||||
|
||||
@PutMapping(value = "/user3", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<UpdateUserResponse> updateUser(@RequestBody @Valid User user,
|
||||
BindingResult bindingResult) {
|
||||
if (bindingResult.hasFieldErrors()) {
|
||||
|
||||
List<InputFieldError> fieldErrorList = bindingResult.getFieldErrors().stream()
|
||||
.map(error -> new InputFieldError(error.getField(), error.getDefaultMessage()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
UpdateUserResponse updateResponse = new UpdateUserResponse(fieldErrorList);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(updateResponse);
|
||||
}
|
||||
else {
|
||||
// Update logic...
|
||||
return ResponseEntity.status(HttpStatus.OK).build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
field.personalEmail=Personal Email
|
||||
validation.notEmpty={field} cannot be empty
|
||||
validation.email.notEmpty=Email cannot be empty
|
|
@ -0,0 +1,3 @@
|
|||
field.personalEmail=個人電郵
|
||||
validation.notEmpty={field}不能是空白
|
||||
validation.email.notEmpty=電郵不能留空
|
|
@ -0,0 +1 @@
|
|||
javax.validation.constraints.NotEmpty.message=The field cannot be empty
|
|
@ -0,0 +1 @@
|
|||
javax.validation.constraints.NotEmpty.message=本欄不能留空
|
|
@ -0,0 +1,75 @@
|
|||
package com.baeldung.restvalidation.service1;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import com.baeldung.restvalidation.RestValidationApplication;
|
||||
import com.baeldung.restvalidation.response.InputFieldError;
|
||||
import com.baeldung.restvalidation.response.UpdateUserResponse;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = RestValidationApplication.class)
|
||||
class UserService1IntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
|
||||
@Test
|
||||
void whenUpdateValidEmail_thenReturnsOK() {
|
||||
|
||||
// When
|
||||
ResponseEntity<UpdateUserResponse> responseEntity = updateUser(new User("test@email.com"), null);
|
||||
|
||||
// Then
|
||||
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUpdateEmptyEmail_thenReturnsErrorMessageInEnglish() {
|
||||
|
||||
// When
|
||||
ResponseEntity<UpdateUserResponse> responseEntity = updateUser(new User(""), null);
|
||||
|
||||
// Then
|
||||
InputFieldError error = responseEntity.getBody().getFieldErrors().get(0);
|
||||
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
|
||||
assertEquals("The field cannot be empty", error.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUpdateEmptyEmailWithLanguageHeaderEqualsToZh_thenReturnsErrorMessageInChinese() {
|
||||
|
||||
// When
|
||||
ResponseEntity<UpdateUserResponse> responseEntity = updateUser(new User(""), "zh-tw");
|
||||
|
||||
// Then
|
||||
InputFieldError error = responseEntity.getBody().getFieldErrors().get(0);
|
||||
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
|
||||
assertEquals("本欄不能留空", error.getMessage());
|
||||
}
|
||||
|
||||
private ResponseEntity<UpdateUserResponse> updateUser(User user, String language) {
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
if (Objects.nonNull(language)) {
|
||||
headers.set(HttpHeaders.ACCEPT_LANGUAGE, language);
|
||||
}
|
||||
|
||||
return restTemplate.exchange(
|
||||
"/user1",
|
||||
HttpMethod.PUT,
|
||||
new HttpEntity<>(user, headers),
|
||||
UpdateUserResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package com.baeldung.restvalidation.service2;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import com.baeldung.restvalidation.RestValidationApplication;
|
||||
import com.baeldung.restvalidation.response.InputFieldError;
|
||||
import com.baeldung.restvalidation.response.UpdateUserResponse;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = RestValidationApplication.class)
|
||||
class UserService2IntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
|
||||
@Test
|
||||
void whenUpdateValidEmail_thenReturnsOK() {
|
||||
|
||||
// When
|
||||
ResponseEntity<UpdateUserResponse> responseEntity = updateUser(new User("test@email.com"), null);
|
||||
|
||||
// Then
|
||||
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUpdateEmptyEmail_thenReturnsErrorMessageInEnglish() {
|
||||
|
||||
// When
|
||||
ResponseEntity<UpdateUserResponse> responseEntity = updateUser(new User(""), null);
|
||||
|
||||
// Then
|
||||
InputFieldError error = responseEntity.getBody().getFieldErrors().get(0);
|
||||
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
|
||||
assertEquals("Email cannot be empty", error.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUpdateEmptyEmailWithLanguageHeaderEqualsToZh_thenReturnsErrorMessageInChinese() {
|
||||
|
||||
// When
|
||||
ResponseEntity<UpdateUserResponse> responseEntity = updateUser(new User(""), "zh-tw");
|
||||
|
||||
// Then
|
||||
InputFieldError error = responseEntity.getBody().getFieldErrors().get(0);
|
||||
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
|
||||
assertEquals("電郵不能留空", error.getMessage());
|
||||
}
|
||||
|
||||
private ResponseEntity<UpdateUserResponse> updateUser(User user, String language) {
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
if (Objects.nonNull(language)) {
|
||||
headers.set(HttpHeaders.ACCEPT_LANGUAGE, language);
|
||||
}
|
||||
|
||||
return restTemplate.exchange(
|
||||
"/user2",
|
||||
HttpMethod.PUT,
|
||||
new HttpEntity<>(user, headers),
|
||||
UpdateUserResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package com.baeldung.restvalidation.service3;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import com.baeldung.restvalidation.RestValidationApplication;
|
||||
import com.baeldung.restvalidation.response.InputFieldError;
|
||||
import com.baeldung.restvalidation.response.UpdateUserResponse;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = RestValidationApplication.class)
|
||||
class UserService3IntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate restTemplate;
|
||||
|
||||
@Test
|
||||
void whenUpdateValidEmail_thenReturnsOK() {
|
||||
|
||||
// When
|
||||
ResponseEntity<UpdateUserResponse> responseEntity = updateUser(new User("test@email.com"), null);
|
||||
|
||||
// Then
|
||||
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUpdateEmptyEmail_thenReturnsErrorMessageInEnglish() {
|
||||
|
||||
// When
|
||||
ResponseEntity<UpdateUserResponse> responseEntity = updateUser(new User(""), null);
|
||||
|
||||
// Then
|
||||
InputFieldError error = responseEntity.getBody().getFieldErrors().get(0);
|
||||
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
|
||||
assertEquals("Personal Email cannot be empty", error.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUpdateEmptyEmailWithLanguageHeaderEqualsToZh_thenReturnsErrorMessageInChinese() {
|
||||
|
||||
// When
|
||||
ResponseEntity<UpdateUserResponse> responseEntity = updateUser(new User(""), "zh-tw");
|
||||
|
||||
// Then
|
||||
InputFieldError error = responseEntity.getBody().getFieldErrors().get(0);
|
||||
assertEquals(HttpStatus.BAD_REQUEST, responseEntity.getStatusCode());
|
||||
assertEquals("個人電郵不能是空白", error.getMessage());
|
||||
}
|
||||
|
||||
private ResponseEntity<UpdateUserResponse> updateUser(User user, String language) {
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
if (Objects.nonNull(language)) {
|
||||
headers.set(HttpHeaders.ACCEPT_LANGUAGE, language);
|
||||
}
|
||||
|
||||
return restTemplate.exchange(
|
||||
"/user3",
|
||||
HttpMethod.PUT,
|
||||
new HttpEntity<>(user, headers),
|
||||
UpdateUserResponse.class
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -16,10 +16,12 @@
|
|||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||
|
@ -30,16 +32,25 @@
|
|||
<artifactId>spring-cloud-contract-wiremock</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-stub-runner</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baeldung.spring.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-producer</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<classifier>stubs</classifier>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>*</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
|
|
@ -1,24 +1,18 @@
|
|||
package com.baeldung.spring.cloud.springcloudcontractconsumer.controller;
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
|
||||
import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
|
||||
import org.springframework.cloud.contract.stubrunner.junit.StubRunnerRule;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
|
@ -26,42 +20,16 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
|
||||
@AutoConfigureMockMvc
|
||||
@AutoConfigureJsonTesters
|
||||
@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.LOCAL,
|
||||
ids = "com.baeldung.spring.cloud:spring-cloud-contract-producer:+:stubs:8090")
|
||||
public class BasicMathControllerIntegrationTest {
|
||||
|
||||
@Rule
|
||||
public StubRunnerRule rule = new StubRunnerRule().downloadStub(
|
||||
"com.baeldung.spring.cloud",
|
||||
"spring-cloud-contract-producer")
|
||||
.withPort(8090).failOnNoStubs(true);
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
private static WireMockServer wireMockServer;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void setupClass() {
|
||||
WireMockConfiguration wireMockConfiguration = WireMockConfiguration.options().port(8090); // Use the same port as in your code
|
||||
|
||||
wireMockServer = new WireMockServer(wireMockConfiguration);
|
||||
wireMockServer.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardownClass() {
|
||||
wireMockServer.stop();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
wireMockServer.stubFor(get(urlEqualTo("/validate/prime-number?number=1"))
|
||||
.willReturn(aResponse()
|
||||
.withStatus(200)
|
||||
.withHeader("Content-Type", "application/json")
|
||||
.withBody("Odd")));
|
||||
|
||||
wireMockServer.stubFor(get(urlEqualTo("/validate/prime-number?number=2"))
|
||||
.willReturn(aResponse()
|
||||
.withStatus(200)
|
||||
.withHeader("Content-Type", "application/json")
|
||||
.withBody("Even")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void given_WhenPassEvenNumberInQueryParam_ThenReturnEven() throws Exception {
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-spring-5</artifactId>
|
||||
<artifactId>parent-spring-6</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-spring-5</relativePath>
|
||||
<relativePath>../parent-spring-6</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -46,11 +46,6 @@
|
|||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>${javax.inject.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
@ -84,9 +79,8 @@
|
|||
</build>
|
||||
|
||||
<properties>
|
||||
<spring-boot.version>2.6.1</spring-boot.version>
|
||||
<spring-boot.version>3.1.2</spring-boot.version>
|
||||
<aspectj-plugin.version>1.14.0</aspectj-plugin.version>
|
||||
<javax.inject.version>1</javax.inject.version>
|
||||
<log4j2.version>2.17.1</log4j2.version>
|
||||
</properties>
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.baeldung.di.aspectj;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Transient;
|
||||
|
||||
@Entity
|
||||
@Configurable(preConstruction = true)
|
||||
|
|
|
@ -3,8 +3,8 @@ package com.baeldung.wiring.configuration.inject;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.baeldung.wiring.configuration.inject;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.baeldung.wiring.configuration.inject;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
|
@ -5,7 +5,7 @@ import static org.junit.Assert.assertNotNull;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
|
@ -9,7 +9,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
|||
|
||||
import com.baeldung.wiring.configuration.ApplicationContextTestResourceQualifier;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
|||
|
||||
import com.baeldung.wiring.configuration.ApplicationContextTestResourceNameType;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
|||
|
||||
import com.baeldung.wiring.configuration.ApplicationContextTestResourceNameType;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
|||
|
||||
import com.baeldung.wiring.configuration.ApplicationContextTestResourceNameType;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
|
@ -9,7 +9,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
|||
|
||||
import com.baeldung.wiring.configuration.ApplicationContextTestResourceQualifier;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
|||
|
||||
import com.baeldung.wiring.configuration.ApplicationContextTestResourceNameType;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-spring-5</artifactId>
|
||||
<artifactId>parent-spring-6</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-spring-5</relativePath>
|
||||
<relativePath>../parent-spring-6</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -45,8 +45,10 @@
|
|||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<spring-boot.version>2.6.1</spring-boot.version>
|
||||
<spring-boot.version>3.1.2</spring-boot.version>
|
||||
<log4j2.version>2.17.1</log4j2.version>
|
||||
<org.slf4j.version>2.0.9</org.slf4j.version>
|
||||
<logback.version>1.4.11</logback.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -7,7 +7,7 @@ import org.springframework.test.context.ContextConfiguration;
|
|||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = DynamicAutowireConfig.class)
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<artifactId>parent-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
<relativePath>../parent-boot-3</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.baeldung.sampleabstract;
|
|||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
public abstract class BallService {
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-spring-5</artifactId>
|
||||
<artifactId>parent-spring-6</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-spring-5</relativePath>
|
||||
<relativePath>../parent-spring-6</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -48,11 +48,6 @@
|
|||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>${javax.inject.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
|
@ -71,7 +66,7 @@
|
|||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test</artifactId>
|
||||
<version>${mockito.spring.boot.version}</version>
|
||||
<version>${spring-boot.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -89,11 +84,6 @@
|
|||
<!-- <groupId>org.springframework</groupId> -->
|
||||
<!-- <artifactId>spring-context</artifactId> -->
|
||||
<!-- </dependency> -->
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>${annotation-api.version}</version>
|
||||
</dependency>
|
||||
<!-- <!– test scoped –> -->
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>org.springframework</groupId> -->
|
||||
|
@ -143,11 +133,7 @@
|
|||
<properties>
|
||||
<start-class>org.baeldung.org.baeldung.sample.App</start-class>
|
||||
<!-- Spring -->
|
||||
<annotation-api.version>1.3.2</annotation-api.version>
|
||||
<mockito.spring.boot.version>1.4.4.RELEASE</mockito.spring.boot.version>
|
||||
<javax.inject.version>1</javax.inject.version>
|
||||
<spring-boot.version>1.5.2.RELEASE</spring-boot.version>
|
||||
<mockito.version>1.10.19</mockito.version>
|
||||
<spring-boot.version>3.1.2</spring-boot.version>
|
||||
<aspectjweaver.version>1.9.5</aspectjweaver.version>
|
||||
</properties>
|
||||
|
||||
|
|
Loading…
Reference in New Issue