Merge branch 'master' of github.com:eugenp/tutorials

This commit is contained in:
Karsten Silz 2020-05-15 18:43:12 +01:00
commit 4bd863d1b2
44 changed files with 508 additions and 103 deletions

View File

@ -13,4 +13,5 @@ This module contains articles about core Groovy concepts
- [Metaprogramming in Groovy](https://www.baeldung.com/groovy-metaprogramming) - [Metaprogramming in Groovy](https://www.baeldung.com/groovy-metaprogramming)
- [A Quick Guide to Working with Web Services in Groovy](https://www.baeldung.com/groovy-web-services) - [A Quick Guide to Working with Web Services in Groovy](https://www.baeldung.com/groovy-web-services)
- [Categories in Groovy](https://www.baeldung.com/groovy-categories) - [Categories in Groovy](https://www.baeldung.com/groovy-categories)
- [How to Determine the Data Type in Groovy](https://www.baeldung.com/groovy-determine-data-type)
- [[<-- Prev]](/core-groovy) - [[<-- Prev]](/core-groovy)

View File

@ -8,3 +8,4 @@ This module contains articles about Java 14.
- [Java Text Blocks](https://www.baeldung.com/java-text-blocks) - [Java Text Blocks](https://www.baeldung.com/java-text-blocks)
- [Pattern Matching for instanceof in Java 14](https://www.baeldung.com/java-pattern-matching-instanceof) - [Pattern Matching for instanceof in Java 14](https://www.baeldung.com/java-pattern-matching-instanceof)
- [Helpful NullPointerExceptions in Java 14](https://www.baeldung.com/java-14-nullpointerexception) - [Helpful NullPointerExceptions in Java 14](https://www.baeldung.com/java-14-nullpointerexception)
- [Foreign Memory Access API in Java 14](https://www.baeldung.com/java-foreign-memory-access)

View File

@ -11,4 +11,5 @@ This module contains articles about advanced topics about multithreading with co
- [Guide to Work Stealing in Java](https://www.baeldung.com/java-work-stealing) - [Guide to Work Stealing in Java](https://www.baeldung.com/java-work-stealing)
- [Asynchronous Programming in Java](https://www.baeldung.com/java-asynchronous-programming) - [Asynchronous Programming in Java](https://www.baeldung.com/java-asynchronous-programming)
- [Java Thread Deadlock and Livelock](https://www.baeldung.com/java-deadlock-livelock) - [Java Thread Deadlock and Livelock](https://www.baeldung.com/java-deadlock-livelock)
- [Guide to AtomicStampedReference in Java](https://www.baeldung.com/java-atomicstampedreference)
- [[<-- previous]](/core-java-modules/core-java-concurrency-advanced-2) - [[<-- previous]](/core-java-modules/core-java-concurrency-advanced-2)

View File

@ -0,0 +1,41 @@
package com.baeldung.weeknumber;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class WeekNumberUsingCalendar {
public int getWeekNumberFrom(String day, String dateFormat, Locale locale) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
Calendar calendar = Calendar.getInstance(locale);
Date date = sdf.parse(day);
calendar.setTime(date);
return calendar.get(Calendar.WEEK_OF_YEAR);
}
public int getWeekNumberFrom(int year, int month, int day, Locale locale) {
Calendar calendar = Calendar.getInstance(locale);
calendar.set(year, month, day);
return calendar.get(Calendar.WEEK_OF_YEAR);
}
public int getWeekNumberFrom(int year, int month, int day, int firstDayOfWeek, int minimalDaysInFirstWeek, Locale locale) {
Calendar calendar = Calendar.getInstance(locale);
calendar.setFirstDayOfWeek(firstDayOfWeek);
calendar.setMinimalDaysInFirstWeek(minimalDaysInFirstWeek);
calendar.set(year, month, day);
return calendar.get(Calendar.WEEK_OF_YEAR);
}
public static void main(String[] args) {
WeekNumberUsingCalendar calendar = new WeekNumberUsingCalendar();
System.out.println(calendar.getWeekNumberFrom(2020, 2, 22, Locale.CANADA));
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.weeknumber;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.WeekFields;
import java.util.Locale;
public class WeekNumberUsingLocalDate {
public Integer getWeekNumberUsingWeekFiedsFrom(String day, String dayFormat, Locale locale) {
LocalDate date = LocalDate.parse(day, DateTimeFormatter.ofPattern(dayFormat));
return date.get(WeekFields.of(locale)
.weekOfYear());
}
public Integer getWeekNumberUsinWeekFieldsFrom(int year, int month, int day, Locale locale) {
LocalDate date = LocalDate.of(year, month, day);
return date.get(WeekFields.of(locale)
.weekOfYear());
}
public Integer getWeekNumberUsingChronoFieldFrom(int year, int month, int day) {
LocalDate date = LocalDate.of(year, month, day);
return date.get(ChronoField.ALIGNED_WEEK_OF_YEAR);
}
}

View File

@ -0,0 +1,46 @@
package com.baeldung.weeknumber;
import static org.junit.Assert.assertEquals;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Locale;
import org.junit.Test;
public class WeekNumberUsingCalendarUnitTest {
@Test
public void givenDateInStringAndDateFormatUsingLocaleItaly_thenGettingWeekNumberUsingCalendarIsCorrectlyReturned() throws ParseException {
WeekNumberUsingCalendar calendar = new WeekNumberUsingCalendar();
assertEquals(12, calendar.getWeekNumberFrom("20200322", "yyyyMMdd", Locale.ITALY));
}
@Test
public void givenDateInStringAndDateFormatUsingLocaleCanada_thenGettingWeekNumberUsingCalendarIsCorrectlyReturned() throws ParseException {
WeekNumberUsingCalendar calendar = new WeekNumberUsingCalendar();
assertEquals(13, calendar.getWeekNumberFrom("20200322", "yyyyMMdd", Locale.CANADA));
}
@Test
public void givenDateInYearMonthDayNumbersLocaleItaly_thenGettingWeekNumberUsingCalendarIsCorrectlyReturned() {
WeekNumberUsingCalendar calendar = new WeekNumberUsingCalendar();
assertEquals(12, calendar.getWeekNumberFrom(2020, 2, 22, Locale.ITALY));
}
@Test
public void givenDateInYearMonthDayNumbersLocaleItalyChangingWeekCalculationSettings_thenGettingWeekNumberUsingCalendarIsCorrectlyReturned() {
WeekNumberUsingCalendar calendar = new WeekNumberUsingCalendar();
assertEquals(13, calendar.getWeekNumberFrom(2020, 2, 22, Calendar.SUNDAY, 4, Locale.ITALY));
}
@Test
public void givenDateInYearMonthDayNumbersLocaleCanada_thenGettingWeekNumberUsingCalendarIsCorrectlyReturned() {
WeekNumberUsingCalendar calendar = new WeekNumberUsingCalendar();
assertEquals(13, calendar.getWeekNumberFrom(2020, 2, 22, Locale.CANADA));
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.weeknumber;
import static org.junit.Assert.assertEquals;
import java.util.Locale;
import org.junit.Test;
public class WeekNumberUsingLocalDateUnitTest {
@Test
public void givenDateInStringAndDateFormatUsingWeekFieldsWithLocaleItaly_thenGettingWeekNumberUsingLocalDateIsCorrectlyReturned() {
WeekNumberUsingLocalDate localDate = new WeekNumberUsingLocalDate();
assertEquals(12, localDate.getWeekNumberUsingWeekFiedsFrom("20200322", "yyyyMMdd", Locale.ITALY)
.longValue());
}
@Test
public void givenDateInStringAndDateFormatUsingWeekFieldsWithLocaleCanada_thenGettingWeekNumberUsingLocalDateIsCorrectlyReturned() {
WeekNumberUsingLocalDate localDate = new WeekNumberUsingLocalDate();
assertEquals(13, localDate.getWeekNumberUsingWeekFiedsFrom("20200322", "yyyyMMdd", Locale.CANADA)
.longValue());
}
@Test
public void givenDateInStringAndDateFormatUsingChronoFieds_thenGettingWeekNumberUsingLocalDateIsCorrectlyReturned() {
WeekNumberUsingLocalDate localDate = new WeekNumberUsingLocalDate();
assertEquals(12, localDate.getWeekNumberUsingChronoFieldFrom(2020, 3, 22)
.longValue());
}
@Test
public void givenDateInYearMonthDayNumbersUsingWeekFieldsWithLocaleItaly_thenGettingWeekNumberUsingLocalDateIsCorrectlyReturned() {
WeekNumberUsingLocalDate localDate = new WeekNumberUsingLocalDate();
assertEquals(12, localDate.getWeekNumberUsinWeekFieldsFrom(2020, 3, 22, Locale.ITALY)
.longValue());
}
@Test
public void givenDateInYearMonthDayNumbersUsingWeekFieldsWithLocaleCanada_thenGettingWeekNumberUsingLocalDateIsCorrectlyReturned() {
WeekNumberUsingLocalDate localDate = new WeekNumberUsingLocalDate();
assertEquals(13, localDate.getWeekNumberUsinWeekFieldsFrom(2020, 3, 22, Locale.CANADA)
.longValue());
}
}

View File

@ -10,3 +10,4 @@
- [Difference Between Java Matcher find() and matches()](https://www.baeldung.com/java-matcher-find-vs-matches) - [Difference Between Java Matcher find() and matches()](https://www.baeldung.com/java-matcher-find-vs-matches)
- [How to Use Regular Expressions to Replace Tokens in Strings](https://www.baeldung.com/java-regex-token-replacement) - [How to Use Regular Expressions to Replace Tokens in Strings](https://www.baeldung.com/java-regex-token-replacement)
- [Regular Expressions \s and \s+ in Java](https://www.baeldung.com/java-regex-s-splus) - [Regular Expressions \s and \s+ in Java](https://www.baeldung.com/java-regex-s-splus)
- [Validate Phone Numbers With Java Regex](https://www.baeldung.com/java-regex-validate-phone-numbers)

View File

@ -4,8 +4,10 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotEquals;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -39,6 +41,27 @@ public class EncodeDecodeUnitTest {
} }
@Test
public void givenJavaBase64_whenEncodedStream_thenDecodedStreamOK() throws IOException {
try (OutputStream os = java.util.Base64.getEncoder().wrap(new FileOutputStream(OUT_FILE));
FileInputStream fis = new FileInputStream(IN_FILE)) {
byte[] bytes = new byte[1024];
int read;
while ((read = fis.read(bytes)) > -1) {
os.write(bytes, 0, read);
}
}
byte[] encoded = java.util.Base64.getEncoder().encode(inFileBytes);
byte[] encodedOnDisk = Files.readAllBytes(Paths.get(OUT_FILE));
assertArrayEquals(encoded, encodedOnDisk);
byte[] decoded = java.util.Base64.getDecoder().decode(encoded);
byte[] decodedOnDisk = java.util.Base64.getDecoder().decode(encodedOnDisk);
assertArrayEquals(decoded, decodedOnDisk);
}
@Test @Test
public void givenApacheCommons_givenJavaBase64_whenEncoded_thenDecodedOK() throws IOException { public void givenApacheCommons_givenJavaBase64_whenEncoded_thenDecodedOK() throws IOException {

View File

@ -9,3 +9,4 @@ This module contains articles about core Kotlin collections.
- [Converting a List to Map in Kotlin](https://www.baeldung.com/kotlin-list-to-map) - [Converting a List to Map in Kotlin](https://www.baeldung.com/kotlin-list-to-map)
- [Filtering Kotlin Collections](https://www.baeldung.com/kotlin-filter-collection) - [Filtering Kotlin Collections](https://www.baeldung.com/kotlin-filter-collection)
- [Collection Transformations in Kotlin](https://www.baeldung.com/kotlin-collection-transformations) - [Collection Transformations in Kotlin](https://www.baeldung.com/kotlin-collection-transformations)
- [Difference between fold and reduce in Kotlin](https://www.baeldung.com/kotlin/fold-vs-reduce)

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Building a Java Application With Gradle](https://www.baeldung.com/gradle-building-a-java-app)

View File

@ -4,4 +4,5 @@ This module contains articles about conversions among Collection types and array
### Relevant Articles: ### Relevant Articles:
- [Array to String Conversions](https://www.baeldung.com/java-array-to-string) - [Array to String Conversions](https://www.baeldung.com/java-array-to-string)
- More articles: [[<-- prev]](../java-collections-conversions) - [Mapping Lists with ModelMapper](https://www.baeldung.com/java-modelmapper-lists)
- More articles: [[<-- prev]](../java-collections-conversions)

View File

@ -11,3 +11,4 @@ This module contains articles about JEE 7.
- [Introduction to Testing with Arquillian](https://www.baeldung.com/arquillian) - [Introduction to Testing with Arquillian](https://www.baeldung.com/arquillian)
- [Java EE 7 Batch Processing](https://www.baeldung.com/java-ee-7-batch-processing) - [Java EE 7 Batch Processing](https://www.baeldung.com/java-ee-7-batch-processing)
- [The Difference Between CDI and EJB Singleton](https://www.baeldung.com/jee-cdi-vs-ejb-singleton) - [The Difference Between CDI and EJB Singleton](https://www.baeldung.com/jee-cdi-vs-ejb-singleton)
- [Invoking a SOAP Web Service in Java](https://www.baeldung.com/java-soap-web-service)

View File

@ -4,6 +4,7 @@ This module contains articles about jsoup.
### Relevant Articles: ### Relevant Articles:
- [Parsing HTML in Java with Jsoup](https://www.baeldung.com/java-with-jsoup) - [Parsing HTML in Java with Jsoup](https://www.baeldung.com/java-with-jsoup)
- [How to add proxy support to Jsoup?](https://www.baeldung.com/java-jsoup-proxy)
### Build the Project ### Build the Project

View File

@ -7,7 +7,7 @@ import java.net.Proxy;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
import org.junit.Test; import org.junit.Test;
public class JsoupProxyIntegrationTest { public class JsoupProxyLiveTest {
@Test @Test
public void whenUsingHostAndPort_thenConnect() throws IOException { public void whenUsingHostAndPort_thenConnect() throws IOException {

3
kaniko/README.md Normal file
View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [An Introduction to Kaniko](https://www.baeldung.com/ops/kaniko)

View File

@ -11,7 +11,8 @@ This module contains articles about libraries for data processing in Java.
- [Guide to JMapper](https://www.baeldung.com/jmapper) - [Guide to JMapper](https://www.baeldung.com/jmapper)
- [An Introduction to SuanShu](https://www.baeldung.com/suanshu) - [An Introduction to SuanShu](https://www.baeldung.com/suanshu)
- [Intro to Derive4J](https://www.baeldung.com/derive4j) - [Intro to Derive4J](https://www.baeldung.com/derive4j)
More articles: [[<-- prev]](/../libraries-data) - [Java-R Integration](https://www.baeldung.com/java-r-integration)
- More articles: [[<-- prev]](/../libraries-data)
##### Building the project ##### Building the project
You can build the project from the command line using: *mvn clean install*, or in an IDE. If you have issues with the derive4j imports in your IDE, you have to add the folder: *target/generated-sources/annotations* to the project build path in your IDE. You can build the project from the command line using: *mvn clean install*, or in an IDE. If you have issues with the derive4j imports in your IDE, you have to add the folder: *target/generated-sources/annotations* to the project build path in your IDE.

View File

@ -24,6 +24,8 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL;
import static com.baeldung.dbunit.ConnectionSettings.PASSWORD;
import static com.baeldung.dbunit.ConnectionSettings.USER;
import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.joining;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.dbunit.Assertion.assertEqualsIgnoreCols; import static org.dbunit.Assertion.assertEqualsIgnoreCols;
@ -33,12 +35,14 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
private static final Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class); private static final Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class);
private Connection connection;
@Override @Override
protected DataSource getDataSource() { protected DataSource getDataSource() {
JdbcDataSource dataSource = new JdbcDataSource(); JdbcDataSource dataSource = new JdbcDataSource();
dataSource.setURL(JDBC_URL); dataSource.setURL(JDBC_URL);
dataSource.setUser("sa"); dataSource.setUser(USER);
dataSource.setPassword(""); dataSource.setPassword(PASSWORD);
return dataSource; return dataSource;
} }
@ -62,6 +66,7 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
connection = getConnection().getConnection();
} }
@After @After
@ -71,9 +76,7 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
@Test @Test
public void givenDataSet_whenSelect_thenFirstTitleIsGreyTShirt() throws SQLException { public void givenDataSet_whenSelect_thenFirstTitleIsGreyTShirt() throws SQLException {
final Connection connection = getDataSource().getConnection(); ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1");
final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1");
assertThat(rs.next()).isTrue(); assertThat(rs.next()).isTrue();
assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt");
@ -81,58 +84,59 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
@Test @Test
public void givenDataSetEmptySchema_whenDataSetCreated_thenTablesAreEqual() throws Exception { public void givenDataSetEmptySchema_whenDataSetCreated_thenTablesAreEqual() throws Exception {
final IDataSet expectedDataSet = getDataSet(); IDataSet expectedDataSet = getDataSet();
final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); ITable expectedTable = expectedDataSet.getTable("CLIENTS");
final IDataSet databaseDataSet = getConnection().createDataSet(); IDataSet databaseDataSet = getConnection().createDataSet();
final ITable actualTable = databaseDataSet.getTable("CLIENTS"); ITable actualTable = databaseDataSet.getTable("CLIENTS");
Assertion.assertEquals(expectedTable, actualTable); Assertion.assertEquals(expectedTable, actualTable);
} }
@Test @Test
public void givenDataSet_whenInsert_thenTableHasNewClient() throws Exception { public void givenDataSet_whenInsert_thenTableHasNewClient() throws Exception {
try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-user.xml")) { try (InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-user.xml")) {
final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); // given
final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is);
final Connection conn = getDataSource().getConnection(); ITable expectedTable = expectedDataSet.getTable("CLIENTS");
Connection conn = getDataSource().getConnection();
// when
conn.createStatement() conn.createStatement()
.executeUpdate( .executeUpdate("INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')");
"INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); ITable actualData = getConnection()
final ITable actualData = getConnection() .createQueryTable("result_name", "SELECT * FROM CLIENTS WHERE last_name='Jansen'");
.createQueryTable(
"result_name",
"SELECT * FROM CLIENTS WHERE last_name='Jansen'");
// then
assertEqualsIgnoreCols(expectedTable, actualData, new String[] { "id" }); assertEqualsIgnoreCols(expectedTable, actualData, new String[] { "id" });
} }
} }
@Test @Test
public void givenDataSet_whenDelete_thenItemIsDeleted() throws Exception { public void givenDataSet_whenDelete_thenItemIsDeleted() throws Exception {
final Connection connection = getConnection().getConnection(); try (InputStream is = DataSourceDBUnitTest.class.getClassLoader()
.getResourceAsStream("dbunit/items_exp_delete.xml")) {
try (final InputStream is = DataSourceDBUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { // given
ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS");
// when
connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); connection.createStatement().executeUpdate("delete from ITEMS where id = 2");
final IDataSet databaseDataSet = getConnection().createDataSet(); // then
IDataSet databaseDataSet = getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("ITEMS"); ITable actualTable = databaseDataSet.getTable("ITEMS");
Assertion.assertEquals(expectedTable, actualTable); Assertion.assertEquals(expectedTable, actualTable);
} }
} }
@Test @Test
public void givenDataSet_whenUpdate_thenItemHasNewName() throws Exception { public void givenDataSet_whenUpdate_thenItemHasNewName() throws Exception {
final Connection connection = getConnection().getConnection(); try (InputStream is = DataSourceDBUnitTest.class.getClassLoader()
.getResourceAsStream("dbunit/items_exp_rename.xml")) {
try (final InputStream is = DataSourceDBUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { // given
ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS");
connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1");
final IDataSet databaseDataSet = getConnection().createDataSet(); IDataSet databaseDataSet = getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("ITEMS"); ITable actualTable = databaseDataSet.getTable("ITEMS");
Assertion.assertEquals(expectedTable, actualTable); Assertion.assertEquals(expectedTable, actualTable);
@ -140,22 +144,24 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
} }
@Test @Test
public void givenDataSet_whenInsertUnexpectedData_thenFailOnAllUnexpectedValues() throws Exception { public void givenDataSet_whenInsertUnexpectedData_thenFail() throws Exception {
try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-multiple-failures.xml")) { try (InputStream is = getClass().getClassLoader()
final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); .getResourceAsStream("dbunit/expected-multiple-failures.xml")) {
final ITable expectedTable = expectedDataSet.getTable("ITEMS");
final Connection conn = getDataSource().getConnection();
final DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler();
conn.createStatement().executeUpdate( // given
"INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is);
final ITable actualData = getConnection().createDataSet().getTable("ITEMS"); ITable expectedTable = expectedDataSet.getTable("ITEMS");
Connection conn = getDataSource().getConnection();
DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler();
// when
conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')");
ITable actualData = getConnection().createDataSet().getTable("ITEMS");
// then
Assertion.assertEquals(expectedTable, actualData, collectingHandler); Assertion.assertEquals(expectedTable, actualData, collectingHandler);
if (!collectingHandler.getDiffList().isEmpty()) { if (!collectingHandler.getDiffList().isEmpty()) {
String message = (String) collectingHandler String message = (String) collectingHandler.getDiffList().stream()
.getDiffList()
.stream()
.map(d -> formatDifference((Difference) d)).collect(joining("\n")); .map(d -> formatDifference((Difference) d)).collect(joining("\n"));
logger.error(() -> message); logger.error(() -> message);
} }
@ -163,6 +169,8 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase {
} }
private static String formatDifference(Difference diff) { private static String formatDifference(Difference diff) {
return "expected value in " + diff.getExpectedTable().getTableMetaData().getTableName() + "." + diff.getColumnName() + " row " + diff.getRowIndex() + ":" + diff.getExpectedValue() + ", but was: " + diff.getActualValue(); return "expected value in " + diff.getExpectedTable().getTableMetaData().getTableName() + "." + diff
.getColumnName() + " row " + diff.getRowIndex() + ":" + diff.getExpectedValue() + ", but was: " + diff
.getActualValue();
} }
} }

View File

@ -31,13 +31,15 @@ public class OldSchoolDbUnitTest {
private static IDatabaseTester tester = null; private static IDatabaseTester tester = null;
private Connection connection;
@BeforeClass @BeforeClass
public static void setUp() throws Exception { public static void setUp() throws Exception {
tester = initDatabaseTester(); tester = initDatabaseTester();
} }
private static IDatabaseTester initDatabaseTester() throws Exception { private static IDatabaseTester initDatabaseTester() throws Exception {
final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD);
tester.setDataSet(initDataSet()); tester.setDataSet(initDataSet());
tester.setSetUpOperation(DatabaseOperation.REFRESH); tester.setSetUpOperation(DatabaseOperation.REFRESH);
tester.setTearDownOperation(DatabaseOperation.DELETE_ALL); tester.setTearDownOperation(DatabaseOperation.DELETE_ALL);
@ -45,7 +47,7 @@ public class OldSchoolDbUnitTest {
} }
private static IDataSet initDataSet() throws Exception { private static IDataSet initDataSet() throws Exception {
try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { try (InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) {
return new FlatXmlDataSetBuilder().build(is); return new FlatXmlDataSetBuilder().build(is);
} }
} }
@ -53,6 +55,7 @@ public class OldSchoolDbUnitTest {
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
tester.onSetup(); tester.onSetup();
connection = tester.getConnection().getConnection();
} }
@After @After
@ -62,94 +65,100 @@ public class OldSchoolDbUnitTest {
@Test @Test
public void givenDataSet_whenSelect_thenFirstTitleIsGreyTShirt() throws Exception { public void givenDataSet_whenSelect_thenFirstTitleIsGreyTShirt() throws Exception {
final Connection connection = tester.getConnection().getConnection(); ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1");
final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1");
assertThat(rs.next()).isTrue(); assertThat(rs.next()).isTrue();
assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt");
} }
@Test @Test
public void givenDataSet_whenInsert_thenGetResultsAreStillEqualIfIgnoringColumnsWithDifferentProduced() throws Exception { public void givenDataSet_whenInsert_thenGetResultsAreStillEqualIfIgnoringColumnsWithDifferentProduced()
final Connection connection = tester.getConnection().getConnection(); throws Exception {
final String[] excludedColumns = { "id", "produced" }; String[] excludedColumns = { "id", "produced" };
try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-ignoring-registered_at.xml")) { try (InputStream is = getClass().getClassLoader()
final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); .getResourceAsStream("dbunit/expected-ignoring-registered_at.xml")) {
final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable( // given
expectedDataSet.getTable("ITEMS"), excludedColumns); IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is);
ITable expectedTable = DefaultColumnFilter
.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns);
connection.createStatement().executeUpdate( // when
"INSERT INTO ITEMS (title, price, produced) VALUES('Necklace', 199.99, now())"); connection.createStatement()
.executeUpdate("INSERT INTO ITEMS (title, price, produced) VALUES('Necklace', 199.99, now())");
final IDataSet databaseDataSet = tester.getConnection().createDataSet();
final ITable actualTable = DefaultColumnFilter.excludedColumnsTable(
databaseDataSet.getTable("ITEMS"), excludedColumns);
// then
IDataSet databaseDataSet = tester.getConnection().createDataSet();
ITable actualTable = DefaultColumnFilter
.excludedColumnsTable(databaseDataSet.getTable("ITEMS"), excludedColumns);
Assertion.assertEquals(expectedTable, actualTable); Assertion.assertEquals(expectedTable, actualTable);
} }
} }
@Test @Test
public void givenDataSet_whenDelete_thenItemIsRemoved() throws Exception { public void givenDataSet_whenDelete_thenItemIsRemoved() throws Exception {
final Connection connection = tester.getConnection().getConnection(); try (InputStream is = OldSchoolDbUnitTest.class.getClassLoader()
.getResourceAsStream("dbunit/items_exp_delete.xml")) {
try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { // given
ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS");
// when
connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); connection.createStatement().executeUpdate("delete from ITEMS where id = 2");
final IDataSet databaseDataSet = tester.getConnection().createDataSet(); // then
IDataSet databaseDataSet = tester.getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("ITEMS"); ITable actualTable = databaseDataSet.getTable("ITEMS");
assertEquals(expectedTable, actualTable); assertEquals(expectedTable, actualTable);
} }
} }
@Test @Test
public void givenDataSet_whenDelete_thenItemIsRemovedAndResultsEqualIfProducedIsIgnored() throws Exception { public void givenDataSet_whenProductIgnoredAndDelete_thenItemIsRemoved() throws Exception {
final Connection connection = tester.getConnection().getConnection(); try (InputStream is = OldSchoolDbUnitTest.class.getClassLoader()
.getResourceAsStream("dbunit/items_exp_delete_no_produced.xml")) {
try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete_no_produced.xml")) { // given
final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS");
// when
connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); connection.createStatement().executeUpdate("delete from ITEMS where id = 2");
final IDataSet databaseDataSet = tester.getConnection().createDataSet(); // then
IDataSet databaseDataSet = tester.getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("ITEMS"); ITable actualTable = databaseDataSet.getTable("ITEMS");
actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" });
assertEquals(expectedTable, actualTable); assertEquals(expectedTable, actualTable);
} }
} }
@Test @Test
public void givenDataSet_whenUpdate_thenItemHasNewName() throws Exception { public void givenDataSet_whenUpdate_thenItemHasNewName() throws Exception {
final Connection connection = tester.getConnection().getConnection(); try (InputStream is = OldSchoolDbUnitTest.class.getClassLoader()
.getResourceAsStream("dbunit/items_exp_rename.xml")) {
try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { // given
final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS");
// when
connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1");
final IDataSet databaseDataSet = tester.getConnection().createDataSet(); // then
IDataSet databaseDataSet = tester.getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("ITEMS"); ITable actualTable = databaseDataSet.getTable("ITEMS");
assertEquals(expectedTable, actualTable); assertEquals(expectedTable, actualTable);
} }
} }
@Test @Test
public void givenDataSet_whenUpdateWithNoProduced_thenItemHasNewName() throws Exception { public void givenDataSet_whenUpdateWithNoProduced_thenItemHasNewName() throws Exception {
final Connection connection = tester.getConnection().getConnection(); try (InputStream is = OldSchoolDbUnitTest.class.getClassLoader()
.getResourceAsStream("dbunit/items_exp_rename_no_produced.xml")) {
try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename_no_produced.xml")) { // given
ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS");
expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[] { "produced" }); expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[] { "produced" });
// when
connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1");
final IDataSet databaseDataSet = tester.getConnection().createDataSet(); // then
IDataSet databaseDataSet = tester.getConnection().createDataSet();
ITable actualTable = databaseDataSet.getTable("ITEMS"); ITable actualTable = databaseDataSet.getTable("ITEMS");
actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" });
assertEquals(expectedTable, actualTable); assertEquals(expectedTable, actualTable);

View File

@ -5,3 +5,4 @@ This module contains articles about Apache Maven. Please refer to its submodules
### Relevant Articles ### Relevant Articles
- [Apache Maven Tutorial](https://www.baeldung.com/maven) - [Apache Maven Tutorial](https://www.baeldung.com/maven)
- [Find Unused Maven Dependencies](https://www.baeldung.com/maven-unused-dependencies)

View File

@ -1,5 +1,5 @@
### Relevant Articles: ### Relevant Articles:
- [A Solid Guide to Solid Principles](https://www.baeldung.com/solid-principles) - [A Solid Guide to Solid Principles](https://www.baeldung.com/solid-principles)
- [Single Responsibility Principle in Java](https://www.baeldung.com/java-single-responsibility-principle)

View File

@ -12,4 +12,5 @@ This module contains articles about the Java Persistence API (JPA) in Java.
- [Combining JPA And/Or Criteria Predicates](https://www.baeldung.com/jpa-and-or-criteria-predicates) - [Combining JPA And/Or Criteria Predicates](https://www.baeldung.com/jpa-and-or-criteria-predicates)
- [JPA Annotation for the PostgreSQL TEXT Type](https://www.baeldung.com/jpa-annotation-postgresql-text-type) - [JPA Annotation for the PostgreSQL TEXT Type](https://www.baeldung.com/jpa-annotation-postgresql-text-type)
- [Mapping a Single Entity to Multiple Tables in JPA](https://www.baeldung.com/jpa-mapping-single-entity-to-multiple-tables) - [Mapping a Single Entity to Multiple Tables in JPA](https://www.baeldung.com/jpa-mapping-single-entity-to-multiple-tables)
- [Constructing a JPA Query Between Unrelated Entities](https://www.baeldung.com/jpa-query-unrelated-entities)
- More articles: [[<-- prev]](/java-jpa) - More articles: [[<-- prev]](/java-jpa)

View File

@ -3,3 +3,4 @@
- [A Guide to Redis with Redisson](http://www.baeldung.com/redis-redisson) - [A Guide to Redis with Redisson](http://www.baeldung.com/redis-redisson)
- [Introduction to Lettuce the Java Redis Client](https://www.baeldung.com/java-redis-lettuce) - [Introduction to Lettuce the Java Redis Client](https://www.baeldung.com/java-redis-lettuce)
- [List All Available Redis Keys](https://www.baeldung.com/redis-list-available-keys) - [List All Available Redis Keys](https://www.baeldung.com/redis-list-available-keys)
- [Spring Data Rediss Property-Based Configuration](https://www.baeldung.com/spring-data-redis-properties)

View File

@ -1,6 +1,7 @@
### Relevant Articles: ### Relevant Articles:
- [Spring JPA @Embedded and @EmbeddedId](TBD) - [Spring JPA @Embedded and @EmbeddedId](https://www.baeldung.com/spring-jpa-embedded-method-parameters)
- [Generate Database Schema with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-generate-db-schema)
### Eclipse Config ### Eclipse Config
After importing the project into Eclipse, you may see the following error: After importing the project into Eclipse, you may see the following error:

View File

@ -1,3 +1,4 @@
### Relevant Articles: ### Relevant Articles:
- [Spring JdbcTemplate Unit Testing](https://www.baeldung.com/spring-jdbctemplate-testing) - [Spring JdbcTemplate Unit Testing](https://www.baeldung.com/spring-jdbctemplate-testing)
- [Using a List of Values in a JdbcTemplate IN Clause](https://www.baeldung.com/spring-jdbctemplate-in-list)

View File

@ -9,3 +9,5 @@ This module contains articles about Spring Security 5
- [New Password Storage In Spring Security 5](https://www.baeldung.com/spring-security-5-password-storage) - [New Password Storage In Spring Security 5](https://www.baeldung.com/spring-security-5-password-storage)
- [Default Password Encoder in Spring Security 5](https://www.baeldung.com/spring-security-5-default-password-encoder) - [Default Password Encoder in Spring Security 5](https://www.baeldung.com/spring-security-5-default-password-encoder)
- [Guide to the AuthenticationManagerResolver in Spring Security](https://www.baeldung.com/spring-security-authenticationmanagerresolver) - [Guide to the AuthenticationManagerResolver in Spring Security](https://www.baeldung.com/spring-security-authenticationmanagerresolver)
- [Disable Security for a Profile in Spring Boot](https://www.baeldung.com/spring-security-disable-profile)
- [Manual Logout With Spring Security](https://www.baeldung.com/spring-security-manual-logout)

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Building a Simple Web Application with Spring Boot and Groovy](https://www.baeldung.com/spring-boot-groovy-web-app)

View File

@ -5,4 +5,4 @@ This module contains articles about logging in Spring Boot projects with Log4j 2
### Relevant Articles: ### Relevant Articles:
- [Logging in Spring Boot](https://www.baeldung.com/spring-boot-logging) - [Logging in Spring Boot](https://www.baeldung.com/spring-boot-logging)
- [Logging to Graylog with Spring Boot](https://www.baeldung.com/graylog-with-spring-boot) - [Logging to Graylog with Spring Boot](https://www.baeldung.com/graylog-with-spring-boot)
- [Log Groups in Spring Boot 2.1](https://www.baeldung.com/spring-boot-log-groups)

View File

@ -3,3 +3,4 @@
- [A Guide To Caching in Spring](http://www.baeldung.com/spring-cache-tutorial) - [A Guide To Caching in Spring](http://www.baeldung.com/spring-cache-tutorial)
- [Spring Cache Creating a Custom KeyGenerator](http://www.baeldung.com/spring-cache-custom-keygenerator) - [Spring Cache Creating a Custom KeyGenerator](http://www.baeldung.com/spring-cache-custom-keygenerator)
- [Cache Eviction in Spring Boot](https://www.baeldung.com/spring-boot-evict-cache) - [Cache Eviction in Spring Boot](https://www.baeldung.com/spring-boot-evict-cache)
- [Using Multiple Cache Managers in Spring](https://www.baeldung.com/spring-multiple-cache-managers)

View File

@ -6,3 +6,4 @@ This module contains articles about Spring Cloud Gateway
- [Exploring the new Spring Cloud Gateway](http://www.baeldung.com/spring-cloud-gateway) - [Exploring the new Spring Cloud Gateway](http://www.baeldung.com/spring-cloud-gateway)
- [Writing Custom Spring Cloud Gateway Filters](https://www.baeldung.com/spring-cloud-custom-gateway-filters) - [Writing Custom Spring Cloud Gateway Filters](https://www.baeldung.com/spring-cloud-custom-gateway-filters)
- [Spring Cloud Gateway Routing Predicate Factories](https://www.baeldung.com/spring-cloud-gateway-routing-predicate-factories) - [Spring Cloud Gateway Routing Predicate Factories](https://www.baeldung.com/spring-cloud-gateway-routing-predicate-factories)
- [Spring Cloud Gateway WebFilter Factories](https://www.baeldung.com/spring-cloud-gateway-webfilter-factories)

View File

@ -4,4 +4,6 @@ This module contains articles about core Spring functionality
## Relevant Articles: ## Relevant Articles:
- [Creating Spring Beans Through Factory Methods](https://www.baeldung.com/spring-beans-factory-methods)
- [How to dynamically Autowire a Bean in Spring](https://www.baeldung.com/spring-dynamic-autowire)
- More articles: [[<-- prev]](/spring-core-3) - More articles: [[<-- prev]](/spring-core-3)

View File

@ -10,9 +10,9 @@
<parent> <parent>
<groupId>com.baeldung</groupId> <groupId>com.baeldung</groupId>
<artifactId>parent-boot-1</artifactId> <artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-1</relativePath> <relativePath>../parent-boot-2</relativePath>
</parent> </parent>
<dependencies> <dependencies>
@ -23,11 +23,24 @@
<dependency> <dependency>
<groupId>org.springframework.mobile</groupId> <groupId>org.springframework.mobile</groupId>
<artifactId>spring-mobile-device</artifactId> <artifactId>spring-mobile-device</artifactId>
<version>${spring-mobile-device.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId> <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<spring-mobile-device.version>2.0.0.M3</spring-mobile-device.version>
</properties>
</project> </project>

View File

@ -0,0 +1,36 @@
package com.baeldung;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mobile.device.DeviceHandlerMethodArgumentResolver;
import org.springframework.mobile.device.DeviceResolverHandlerInterceptor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Bean
public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
return new DeviceResolverHandlerInterceptor();
}
@Bean
public DeviceHandlerMethodArgumentResolver deviceHandlerMethodArgumentResolver() {
return new DeviceHandlerMethodArgumentResolver();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(deviceResolverHandlerInterceptor());
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(deviceHandlerMethodArgumentResolver());
}
}

View File

@ -16,13 +16,16 @@ public class IndexController {
String deviceType = "browser"; String deviceType = "browser";
String platform = "browser"; String platform = "browser";
String viewName = "index";
if (device.isNormal()) { if (device.isNormal()) {
deviceType = "browser"; deviceType = "browser";
} else if (device.isMobile()) { } else if (device.isMobile()) {
deviceType = "mobile"; deviceType = "mobile";
viewName = "mobile/index";
} else if (device.isTablet()) { } else if (device.isTablet()) {
deviceType = "tablet"; deviceType = "tablet";
viewName = "tablet/index";
} }
platform = device.getDevicePlatform().name(); platform = device.getDevicePlatform().name();
@ -33,7 +36,7 @@ public class IndexController {
LOGGER.info("Client Device Type: " + deviceType + ", Platform: " + platform); LOGGER.info("Client Device Type: " + deviceType + ", Platform: " + platform);
return "index"; return viewName;
} }
} }

View File

@ -1 +1,3 @@
spring.mobile.devicedelegatingviewresolver.enabled: true spring.mobile.devicedelegatingviewresolver.enabled: true
spring.freemarker.template-loader-path: classpath:/templates
spring.freemarker.suffix: .ftl

View File

@ -9,9 +9,9 @@
<parent> <parent>
<groupId>com.baeldung</groupId> <groupId>com.baeldung</groupId>
<artifactId>parent-boot-1</artifactId> <artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-1</relativePath> <relativePath>../parent-boot-2</relativePath>
</parent> </parent>
<dependencies> <dependencies>
@ -19,25 +19,26 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa --> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${spring-boot.version}</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-rest-hal-browser --> <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-rest-hal-browser -->
<dependency> <dependency>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId> <artifactId>spring-data-rest-hal-browser</artifactId>
<version>${spring-data.version}</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 --> <!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
<version>${h2.version}</version> </dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-dep</artifactId>
<version>${bytebuddy.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
@ -55,9 +56,7 @@
</build> </build>
<properties> <properties>
<spring-boot.version>2.0.3.RELEASE</spring-boot.version> <bytebuddy.version>1.10.10</bytebuddy.version>
<spring-data.version>3.0.8.RELEASE</spring-data.version>
<h2.version>1.4.197</h2.version>
<source.version>1.8</source.version> <source.version>1.8</source.version>
<target.version>1.8</target.version> <target.version>1.8</target.version>
</properties> </properties>

View File

@ -10,4 +10,5 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com
- [Multiple Authentication Providers in Spring Security](https://www.baeldung.com/spring-security-multiple-auth-providers) - [Multiple Authentication Providers in Spring Security](https://www.baeldung.com/spring-security-multiple-auth-providers)
- [Two Login Pages with Spring Security](https://www.baeldung.com/spring-security-two-login-pages) - [Two Login Pages with Spring Security](https://www.baeldung.com/spring-security-two-login-pages)
- [HTTPS using Self-Signed Certificate in Spring Boot](https://www.baeldung.com/spring-boot-https-self-signed-certificate) - [HTTPS using Self-Signed Certificate in Spring Boot](https://www.baeldung.com/spring-boot-https-self-signed-certificate)
- [Spring Security: Exploring JDBC Authentication](https://www.baeldung.com/spring-security-jdbc-authentication) - [Spring Security: Exploring JDBC Authentication](https://www.baeldung.com/spring-security-jdbc-authentication)
- [Spring Security Custom Logout Handler](https://www.baeldung.com/spring-security-custom-logout-handler)

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Spring Security With Okta](https://www.baeldung.com/spring-security-okta)

View File

@ -5,3 +5,4 @@ This module contains articles about SOAP APIs with Spring
### Relevant articles: ### Relevant articles:
- [Creating a SOAP Web Service with Spring](https://www.baeldung.com/spring-boot-soap-web-service) - [Creating a SOAP Web Service with Spring](https://www.baeldung.com/spring-boot-soap-web-service)
- [Invoking a SOAP Web Service in Spring](https://www.baeldung.com/spring-soap-web-service)

View File

@ -0,0 +1,22 @@
package com.baeldung.thymeleaf.currencies;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class CurrenciesController {
@GetMapping(value = "/currency")
public String exchange(
@RequestParam(value = "amount", required = false) String amount,
@RequestParam(value = "amountList", required = false) List amountList,
Locale locale) {
return "currencies/currencies";
}
}

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Currency table</title>
</head>
<body>
<p>Currency format by Locale</p>
<p th:text="${#numbers.formatCurrency(param.amount)}"></p>
<p>Currency Arrays format by Locale</p>
<p th:text="${#numbers.listFormatCurrency(param.amountList)}"></p>
<p>Remove decimal values</p>
<p th:text="${#strings.replace(#numbers.formatCurrency(param.amount), '.00', '')}"></p>
<p>Replace decimal points</p>
<p th:text="${#numbers.formatDecimal(param.amount, 1, 2, 'COMMA')}"></p>
</body>
</html>

View File

@ -0,0 +1,68 @@
package com.baeldung.thymeleaf.currencies;
import static org.hamcrest.CoreMatchers.containsString;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc(printOnlyOnFailure = false)
public class CurrenciesControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void whenCallCurrencyWithSpanishLocale_ThenReturnProperCurrency() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/currency")
.header("Accept-Language", "es-ES")
.param("amount", "10032.5"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("10.032,50 ")));
}
@Test
public void whenCallCurrencyWithUSALocale_ThenReturnProperCurrency() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/currency")
.header("Accept-Language", "en-US")
.param("amount", "10032.5"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("$10,032.50")));
}
@Test
public void whenCallCurrencyWithRomanianLocaleWithArrays_ThenReturnLocaleCurrencies() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/currency")
.header("Accept-Language", "ro-RO")
.param("amountList", "10", "20", "30"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("10,00 RON, 20,00 RON, 30,00 RON")));
}
@Test
public void whenCallCurrencyWithUSALocaleWithoutDecimal_ThenReturnCurrencyWithoutTrailingZeros() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/currency")
.header("Accept-Language", "en-US")
.param("amount", "10032"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("$10,032")));
}
@Test
public void whenCallCurrencyWithUSALocale_ThenReturnReplacedDecimalPoint() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/currency")
.header("Accept-Language", "en-US")
.param("amount", "1.5"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("1,5")));
}
}

View File

@ -1,3 +1,4 @@
### Relevant Articles: ### Relevant Articles:
- [Introduction to Terraform](https://www.baeldung.com/ops/terraform-intro) - [Introduction to Terraform](https://www.baeldung.com/ops/terraform-intro)
- [Best Practices When Using Terraform](https://www.baeldung.com/ops/terraform-best-practices)

View File

@ -10,4 +10,4 @@
- [Custom Assertions with AssertJ](http://www.baeldung.com/assertj-custom-assertion) - [Custom Assertions with AssertJ](http://www.baeldung.com/assertj-custom-assertion)
- [Using Conditions with AssertJ Assertions](http://www.baeldung.com/assertj-conditions) - [Using Conditions with AssertJ Assertions](http://www.baeldung.com/assertj-conditions)
- [AssertJ Exception Assertions](http://www.baeldung.com/assertj-exception-assertion) - [AssertJ Exception Assertions](http://www.baeldung.com/assertj-exception-assertion)
- [Asserting Log Messages With JUnit](https://www.baeldung.com/junit-asserting-logs)