From b7ea20cf99e620a8085777a204fed81487792639 Mon Sep 17 00:00:00 2001 From: patkorek Date: Thu, 26 Mar 2020 12:02:03 +0100 Subject: [PATCH 001/194] Postman Collection to test GraphQL endpoints --- ...GraphQL collection.postman_collection.json | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json diff --git a/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json b/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json new file mode 100644 index 0000000000..7fcaa2c76d --- /dev/null +++ b/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json @@ -0,0 +1,169 @@ +{ + "info": { + "_postman_id": "910d9690-f629-4491-bbbd-adb30982a386", + "name": "GraphQL collection", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "mutations", + "item": [ + { + "name": "writePost", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "graphql", + "graphql": { + "query": "mutation writePost ($title: String!, $text: String!, $category: String) {\n writePost (title: $title, text: $text, category: $category) {\n id\n title\n text\n category\n }\n}", + "variables": "{\n \"title\": \"\",\n \"text\": \"\",\n \"category\": \"\"\n}" + }, + "options": { + "graphql": {} + } + }, + "url": { + "raw": "http://localhost:9090/springbootapp/graphql", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "9090", + "path": [ + "springbootapp", + "graphql" + ] + } + }, + "response": [] + } + ], + "protocolProfileBehavior": {} + }, + { + "name": "queries", + "item": [ + { + "name": "get recent posts", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "graphql", + "graphql": { + "query": "{\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n text\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}", + "variables": "" + } + }, + "url": { + "raw": "http://localhost:9090/springbootapp/graphql", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "9090", + "path": [ + "springbootapp", + "graphql" + ] + } + }, + "response": [] + }, + { + "name": "recentPosts - variables", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "graphql", + "graphql": { + "query": "query recentPosts ($count: Int, $offset: Int) {\n recentPosts (count: $count, offset: $offset) {\n id\n title\n text\n category\n }\n}", + "variables": "{\n \"count\": 1,\n \"offset\": 0\n}" + }, + "options": { + "graphql": {} + } + }, + "url": { + "raw": "http://localhost:9090/springbootapp/graphql", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "9090", + "path": [ + "springbootapp", + "graphql" + ] + } + }, + "response": [] + }, + { + "name": "get recent posts - raw", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/graphql", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "query {\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}" + }, + "url": { + "raw": "http://localhost:9090/springbootapp/graphql", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "9090", + "path": [ + "springbootapp", + "graphql" + ] + } + }, + "response": [] + } + ], + "protocolProfileBehavior": {} + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "b54f267b-c450-4f2d-8105-2f23bab4c922", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "00b575be-03d4-4b29-b137-733ead139638", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "id": "20a274e5-6d51-40d6-81cb-af9eb115b21b", + "key": "url", + "value": "", + "type": "string" + } + ], + "protocolProfileBehavior": {} +} \ No newline at end of file From 23153cf01c005f2033518054cb08cb7cddb78007 Mon Sep 17 00:00:00 2001 From: mthomas Date: Sat, 28 Mar 2020 04:58:57 -0500 Subject: [PATCH 002/194] BAEL-3860 - Add model class and test for AtomicStampedReference --- .../concurrent/atomic/SafeAccount.java | 34 +++++++++++++++++++ .../atomic/ThreadSafeAccountTest.java | 21 ++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeAccount.java create mode 100644 core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeAccount.java b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeAccount.java new file mode 100644 index 0000000000..febfd481c3 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeAccount.java @@ -0,0 +1,34 @@ +package com.baeldung.concurrent.atomic; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicStampedReference; + +public class SafeAccount { + + AtomicInteger stamp = new AtomicInteger(0); + AtomicStampedReference balance = new AtomicStampedReference<>(0, 0); + + public int getBalance() { + return this.balance.get(new int[1]); + } + + public int getStamp() { + int[] stamps = new int[1]; + this.balance.get(stamps); + return stamps[0]; + } + + public boolean deposit(int funds) { + int[] stamps = new int[1]; + int current = this.balance.get(stamps); + int newStamp = this.stamp.incrementAndGet(); + return this.balance.compareAndSet(current, current + funds, stamps[0], newStamp); + } + + public boolean withdrawal(int funds) { + int[] stamps = new int[1]; + int current = this.balance.get(stamps); + int newStamp = this.stamp.incrementAndGet(); + return this.balance.compareAndSet(current, current - funds, stamps[0], newStamp); + } +} diff --git a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java new file mode 100644 index 0000000000..b9a5fe7773 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java @@ -0,0 +1,21 @@ +package com.baeldung.concurrent.atomic; + +import org.junit.Assert; +import org.junit.Test; + +public class ThreadSafeAccountTest { + + @Test + public void givenMultiThread_whenSafeAccountSetBalance() throws InterruptedException { + SafeAccount account = new SafeAccount(); + Thread t = new Thread(() -> { + while (!account.withdrawal(100)) + Thread.yield(); + }); + t.start(); + Assert.assertTrue(account.deposit(100)); + t.join(1_000); + Assert.assertFalse(t.isAlive()); + Assert.assertSame(0, account.getBalance()); + } +} From e189686b4a55267a1a0b369ef0f170576b2a0eb7 Mon Sep 17 00:00:00 2001 From: naXa! Date: Sun, 17 Mar 2019 22:24:10 +0300 Subject: [PATCH 003/194] [BAEL-2749] create new module `dbunit`; add DbUnit tests: `OldSchoolDbUnitTest` + `PrepAndExpectedDbUnitTest` + relevant data --- dbunit/README.md | 6 + dbunit/docs/db_schema.png | Bin 0 -> 17099 bytes dbunit/pom.xml | 35 ++++++ .../main/java/com/baeldung/dbunit/.gitkeep | 0 dbunit/src/main/resources/logback.xml | 13 ++ .../baeldung/dbunit/OldSchoolDbUnitTest.java | 111 ++++++++++++++++++ .../dbunit/PrepAndExpectedDbUnitTest.java | 103 ++++++++++++++++ dbunit/src/test/resources/data.xml | 11 ++ dbunit/src/test/resources/items.xml | 9 ++ .../src/test/resources/items_exp_delete.xml | 8 ++ .../src/test/resources/items_exp_rename.xml | 9 ++ dbunit/src/test/resources/schema.sql | 28 +++++ dbunit/src/test/resources/users.xml | 7 ++ .../src/test/resources/users_exp_delete.xml | 6 + .../src/test/resources/users_exp_rename.xml | 7 ++ 15 files changed, 353 insertions(+) create mode 100644 dbunit/README.md create mode 100644 dbunit/docs/db_schema.png create mode 100644 dbunit/pom.xml create mode 100644 dbunit/src/main/java/com/baeldung/dbunit/.gitkeep create mode 100644 dbunit/src/main/resources/logback.xml create mode 100644 dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java create mode 100644 dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java create mode 100644 dbunit/src/test/resources/data.xml create mode 100644 dbunit/src/test/resources/items.xml create mode 100644 dbunit/src/test/resources/items_exp_delete.xml create mode 100644 dbunit/src/test/resources/items_exp_rename.xml create mode 100644 dbunit/src/test/resources/schema.sql create mode 100644 dbunit/src/test/resources/users.xml create mode 100644 dbunit/src/test/resources/users_exp_delete.xml create mode 100644 dbunit/src/test/resources/users_exp_rename.xml diff --git a/dbunit/README.md b/dbunit/README.md new file mode 100644 index 0000000000..383bd6fb7e --- /dev/null +++ b/dbunit/README.md @@ -0,0 +1,6 @@ +### Database schema + +![db schema](docs/db_schema.png) + +### Relevant Articles: +- [Introduction To DBUnit](https://www.baeldung.com/dbunit) diff --git a/dbunit/docs/db_schema.png b/dbunit/docs/db_schema.png new file mode 100644 index 0000000000000000000000000000000000000000..d9185bacd2c624c8e05aea87bf542cfdfd7f1604 GIT binary patch literal 17099 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 + 4.0.0 + dbunit + 1.0 + dbunit + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.dbunit + dbunit + ${dbunit.version} + test + + + + com.h2database + h2 + 1.4.197 + test + + + + + + 2.6.0 + + + diff --git a/dbunit/src/main/java/com/baeldung/dbunit/.gitkeep b/dbunit/src/main/java/com/baeldung/dbunit/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/dbunit/src/main/resources/logback.xml b/dbunit/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/dbunit/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java new file mode 100644 index 0000000000..a703863614 --- /dev/null +++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java @@ -0,0 +1,111 @@ +package com.baeldung.dbunit; + +import org.dbunit.Assertion; +import org.dbunit.IDatabaseTester; +import org.dbunit.JdbcDatabaseTester; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.xml.FlatXmlDataSet; +import org.dbunit.operation.DatabaseOperation; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.InputStream; +import java.sql.Connection; +import java.sql.ResultSet; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class OldSchoolDbUnitTest { + private static final String JDBC_DRIVER = org.h2.Driver.class.getName(); + private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"; + private static final String USER = "sa"; + private static final String PASSWORD = ""; + + private static IDatabaseTester tester = null; + + @BeforeClass + public static void setUp() throws Exception { + tester = initDatabaseTester(); + } + + private static IDatabaseTester initDatabaseTester() throws Exception { + final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); + tester.setDataSet(initDataSet()); + tester.setSetUpOperation(DatabaseOperation.REFRESH); + tester.setTearDownOperation(DatabaseOperation.NONE); + return tester; + } + + private static IDataSet initDataSet() throws Exception { + final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml"); + return new FlatXmlDataSet(is); + } + + @Before + public void setup() throws Exception { + tester.onSetup(); + } + + @After + public void tearDown() throws Exception { + tester.onTearDown(); + } + + @Test + public void testSelect() throws Exception { + // Arrange + final Connection connection = tester.getConnection().getConnection(); + + // Act + final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); + + // Assert + assertTrue(rs.next()); + assertEquals("Grey T-Shirt", rs.getString("title")); + } + + @Test + public void testDelete() throws Exception { + // Arrange + final Connection connection = tester.getConnection().getConnection(); + + final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml"); + ITable expectedTable = (new FlatXmlDataSet(is)).getTable("items"); + //expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"}); + + // Act + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + // Assert + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + //actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); + + Assertion.assertEquals(expectedTable, actualTable); + } + + @Test + public void testUpdate() throws Exception { + // Arrange + final Connection connection = tester.getConnection().getConnection(); + + final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml"); + ITable expectedTable = (new FlatXmlDataSet(is)).getTable("items"); + //expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"}); + + // Act + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + // Assert + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + //actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); + + Assertion.assertEquals(expectedTable, actualTable); + } + +} diff --git a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java new file mode 100644 index 0000000000..c3882d5eab --- /dev/null +++ b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java @@ -0,0 +1,103 @@ +package com.baeldung.dbunit; + +import org.dbunit.*; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.dbunit.operation.DatabaseOperation; +import org.dbunit.util.fileloader.DataFileLoader; +import org.dbunit.util.fileloader.FlatXmlDataFileLoader; +import org.junit.Test; + +import java.io.InputStream; +import java.sql.Connection; +import java.sql.ResultSet; + +public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { + private static final String JDBC_DRIVER = org.h2.Driver.class.getName(); + private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"; + private static final String USER = "sa"; + private static final String PASSWORD = ""; + + @Override + public void setUp() throws Exception { + setDatabaseTester(initDatabaseTester()); + setDataFileLoader(initDataFileLoader()); + super.setUp(); + } + + private IDatabaseTester initDatabaseTester() throws Exception { + final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); + tester.setDataSet(initDataSet()); + tester.setSetUpOperation(DatabaseOperation.REFRESH); + return tester; + } + + private IDataSet initDataSet() throws Exception { + final InputStream is = getClass().getClassLoader().getResourceAsStream("data.xml"); + return new FlatXmlDataSetBuilder().build(is); + } + + private DataFileLoader initDataFileLoader() { + return new FlatXmlDataFileLoader(); + } + + @Test + public void testSelect() throws Exception { + // Arrange + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; + final String[] prepDataFiles = {"/users.xml"}; + final String[] expectedDataFiles = {"/users.xml"}; + final PrepAndExpectedTestCaseSteps testSteps = () -> { + // invoke the method being tested here; for the sake of simplicity we use JDBC API directly in this example + final ResultSet rs = connection.createStatement().executeQuery("select * from USERS where id = 1"); + + // either place assertions here + //assertTrue(rs.next()); + //assertEquals("Xavier", rs.getString("last_name")); + + return rs; + }; + + // Act + final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + + // or place assertions at the end + assertTrue(rs.next()); + assertEquals("Xavier", rs.getString("last_name")); + } + + @Test + public void testUpdate() throws Exception { + // Arrange + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; // define tables to verify + final String[] prepDataFiles = {"/users.xml"}; // define prep files + final String[] expectedDataFiles = {"/users_exp_rename.xml"}; // define expected files + final PrepAndExpectedTestCaseSteps testSteps = () -> { + // invoke the method being tested here; for the sake of simplicity we use JDBC API directly in this example + return connection.createStatement().executeUpdate("update USERS set first_name = 'new name' where id = 1"); + // after this method exits, dbUnit will: + // * verify configured tables + // * cleanup tables as configured + }; + + // Act + super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + } + + @Test + public void testDelete() throws Exception { + // Arrange + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; + final String[] prepDataFiles = {"/users.xml"}; + final String[] expectedDataFiles = {"/users_exp_delete.xml"}; + final PrepAndExpectedTestCaseSteps testSteps = + () -> connection.createStatement().executeUpdate("delete from USERS where id = 2"); + + // Act + super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + } + +} diff --git a/dbunit/src/test/resources/data.xml b/dbunit/src/test/resources/data.xml new file mode 100644 index 0000000000..e4498513e0 --- /dev/null +++ b/dbunit/src/test/resources/data.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/dbunit/src/test/resources/items.xml b/dbunit/src/test/resources/items.xml new file mode 100644 index 0000000000..04a975d7ee --- /dev/null +++ b/dbunit/src/test/resources/items.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/dbunit/src/test/resources/items_exp_delete.xml b/dbunit/src/test/resources/items_exp_delete.xml new file mode 100644 index 0000000000..1aaeff59ca --- /dev/null +++ b/dbunit/src/test/resources/items_exp_delete.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/dbunit/src/test/resources/items_exp_rename.xml b/dbunit/src/test/resources/items_exp_rename.xml new file mode 100644 index 0000000000..237280e758 --- /dev/null +++ b/dbunit/src/test/resources/items_exp_rename.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/dbunit/src/test/resources/schema.sql b/dbunit/src/test/resources/schema.sql new file mode 100644 index 0000000000..9b5018985a --- /dev/null +++ b/dbunit/src/test/resources/schema.sql @@ -0,0 +1,28 @@ +CREATE TABLE IF NOT EXISTS USERS +( + `id` int AUTO_INCREMENT NOT NULL, + `first_name` varchar(100) NOT NULL, + `last_name` varchar(100) NOT NULL, + PRIMARY KEY (`id`) +); + +CREATE TABLE IF NOT EXISTS ITEMS +( + `id` int AUTO_INCREMENT NOT NULL, + `title` varchar(100) NOT NULL, + `produced` date, + `price` float, + PRIMARY KEY (`id`) +); + +CREATE TABLE IF NOT EXISTS PURCHASES +( + `id` int NOT NULL AUTO_INCREMENT, + `id_user` int NOT NULL, + `id_item` int NOT NULL, + `total_price` float NOT NULL, + `quantity` int(11) NOT NULL, + PRIMARY KEY (`id`), + FOREIGN KEY (`id_user`) REFERENCES USERS (`id`) ON DELETE CASCADE, + FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE +); diff --git a/dbunit/src/test/resources/users.xml b/dbunit/src/test/resources/users.xml new file mode 100644 index 0000000000..cebadf2e67 --- /dev/null +++ b/dbunit/src/test/resources/users.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dbunit/src/test/resources/users_exp_delete.xml b/dbunit/src/test/resources/users_exp_delete.xml new file mode 100644 index 0000000000..8b72ceef89 --- /dev/null +++ b/dbunit/src/test/resources/users_exp_delete.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/dbunit/src/test/resources/users_exp_rename.xml b/dbunit/src/test/resources/users_exp_rename.xml new file mode 100644 index 0000000000..9bc1254967 --- /dev/null +++ b/dbunit/src/test/resources/users_exp_rename.xml @@ -0,0 +1,7 @@ + + + + + + + From 6194165f0d1c57ef5d6b5f1111d96107beee735c Mon Sep 17 00:00:00 2001 From: naXa! Date: Mon, 25 Mar 2019 01:37:05 +0300 Subject: [PATCH 004/194] [BAEL-2749] add `SampleDbUnitTest` (extending `DBTestCase`) --- .../com/baeldung/dbunit/SampleDbUnitTest.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java diff --git a/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java new file mode 100644 index 0000000000..cfe4fd4e11 --- /dev/null +++ b/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java @@ -0,0 +1,96 @@ +package com.baeldung.dbunit; + +import org.dbunit.Assertion; +import org.dbunit.DBTestCase; +import org.dbunit.PropertiesBasedJdbcDatabaseTester; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.dbunit.operation.DatabaseOperation; +import org.junit.Test; + +import java.io.InputStream; +import java.sql.Connection; +import java.sql.ResultSet; + +public class SampleDbUnitTest extends DBTestCase { + private static final String JDBC_DRIVER = org.h2.Driver.class.getName(); + private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"; + private static final String USER = "sa"; + private static final String PASSWORD = ""; + + public SampleDbUnitTest(String name) { + super(name); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD); + // System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_SCHEMA, ""); + } + + @Override + protected IDataSet getDataSet() throws Exception { + final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml"); + return new FlatXmlDataSetBuilder().build(is); + } + + @Override + protected DatabaseOperation getSetUpOperation() { + return DatabaseOperation.REFRESH; + } + + @Override + protected DatabaseOperation getTearDownOperation() { + return DatabaseOperation.NONE; + } + + @Test + public void testSelect() throws Exception { + // Arrange + final Connection connection = getConnection().getConnection(); + + // Act + final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); + + // Assert + assertTrue(rs.next()); + assertEquals("Grey T-Shirt", rs.getString("title")); + } + + @Test + public void testDelete() throws Exception { + // Arrange + final Connection connection = getConnection().getConnection(); + + final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml"); + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); + + // Act + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + // Assert + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + + Assertion.assertEquals(expectedTable, actualTable); + } + + @Test + public void testUpdate() throws Exception { + // Arrange + final Connection connection = getConnection().getConnection(); + + final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml"); + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); + + // Act + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + // Assert + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + + Assertion.assertEquals(expectedTable, actualTable); + } + +} From 71fecd658963941c694f0528e981b2f88441999d Mon Sep 17 00:00:00 2001 From: Philippe Date: Sun, 29 Mar 2020 11:49:46 -0300 Subject: [PATCH 005/194] [BAEL-3793][BAEL-3935] Code snippets --- terraform/best-practices/README.md | 10 +++ .../best-practices/ec2-simple/.gitignore | 4 ++ terraform/best-practices/ec2-simple/SETUP.md | 23 +++++++ terraform/best-practices/ec2-simple/main.tf | 33 +++++++++ .../best-practices/ec2-simple/providers.tf | 6 ++ .../best-practices/ec2-simple/variables.tf | 15 ++++ terraform/best-practices/k8s-basic/.gitignore | 4 ++ terraform/best-practices/k8s-basic/SETUP.md | 15 ++++ terraform/best-practices/k8s-basic/main.tf | 12 ++++ .../best-practices/k8s-basic/providers.tf | 6 ++ .../best-practices/k8s-basic/variables.tf | 9 +++ .../best-practices/k8s-modules/.gitignore | 4 ++ terraform/best-practices/k8s-modules/SETUP.md | 21 ++++++ terraform/best-practices/k8s-modules/main.tf | 27 ++++++++ .../k8s-modules/modules/SvcCustomer/main.tf | 68 ++++++++++++++++++ .../modules/SvcCustomer/outputs.tf | 3 + .../modules/SvcCustomer/variables.tf | 5 ++ .../k8s-modules/modules/SvcFeedback/main.tf | 69 +++++++++++++++++++ .../modules/SvcFeedback/outputs.tf | 3 + .../modules/SvcFeedback/variables.tf | 5 ++ .../ingress/www.petshop.com.br/main.tf | 41 +++++++++++ .../ingress/www.petshop.com.br/outputs.tf | 5 ++ .../ingress/www.petshop.com.br/variables.tf | 20 ++++++ .../best-practices/k8s-modules/provider.tf | 13 ++++ terraform/hello-terraform/.gitignore | 6 ++ terraform/hello-terraform/main.tf | 7 ++ 26 files changed, 434 insertions(+) create mode 100644 terraform/best-practices/README.md create mode 100644 terraform/best-practices/ec2-simple/.gitignore create mode 100644 terraform/best-practices/ec2-simple/SETUP.md create mode 100644 terraform/best-practices/ec2-simple/main.tf create mode 100644 terraform/best-practices/ec2-simple/providers.tf create mode 100644 terraform/best-practices/ec2-simple/variables.tf create mode 100644 terraform/best-practices/k8s-basic/.gitignore create mode 100644 terraform/best-practices/k8s-basic/SETUP.md create mode 100644 terraform/best-practices/k8s-basic/main.tf create mode 100644 terraform/best-practices/k8s-basic/providers.tf create mode 100644 terraform/best-practices/k8s-basic/variables.tf create mode 100644 terraform/best-practices/k8s-modules/.gitignore create mode 100644 terraform/best-practices/k8s-modules/SETUP.md create mode 100644 terraform/best-practices/k8s-modules/main.tf create mode 100644 terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf create mode 100644 terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf create mode 100644 terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf create mode 100644 terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf create mode 100644 terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf create mode 100644 terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf create mode 100644 terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf create mode 100644 terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf create mode 100644 terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf create mode 100644 terraform/best-practices/k8s-modules/provider.tf create mode 100644 terraform/hello-terraform/.gitignore create mode 100644 terraform/hello-terraform/main.tf diff --git a/terraform/best-practices/README.md b/terraform/best-practices/README.md new file mode 100644 index 0000000000..fd488b1afb --- /dev/null +++ b/terraform/best-practices/README.md @@ -0,0 +1,10 @@ +# Terraform Sample Code + +This folder contains Terraform project samples that illustrates topics covered in the +"Best practices when using Terraform" article. Setup instructions are available in each sample's folder. + +List of available samples: + + * k8s-basic: "Hello world" project that just connects to a Kubernetes cluster and create a new namespace. + * ec2-basic: "Hello world" project that creates a single EC2 instance + * k8s-modules: A more elaborate sample that creates a simple set of services in a Kubernetes cluster diff --git a/terraform/best-practices/ec2-simple/.gitignore b/terraform/best-practices/ec2-simple/.gitignore new file mode 100644 index 0000000000..a70da3ca16 --- /dev/null +++ b/terraform/best-practices/ec2-simple/.gitignore @@ -0,0 +1,4 @@ +*.tfvars +*.tfstate +*.tfstate.backup +.terraform diff --git a/terraform/best-practices/ec2-simple/SETUP.md b/terraform/best-practices/ec2-simple/SETUP.md new file mode 100644 index 0000000000..3f906b6933 --- /dev/null +++ b/terraform/best-practices/ec2-simple/SETUP.md @@ -0,0 +1,23 @@ +# EC2 Basic Sample + +This Terraform sample project creates a single EC2 instance in the configured region. + +IMPORTANT NOTICE: In order to run this sample you must have an active AWS Account. As you probably know, creating resources on AWS +may result in additional charges in your bill. We recommend creating a test account to run this test as you can then use AWS's free tier +to play around. When finished, ALWAYS REMEMBER TO DESTROY YOUR RESOURCES !!! + +# Setup instructions + +1. Make sure you have a working AWS environment. Use a simple command such as _aws ec2 describe-instances_ and check its output. + If you get a list of existing EC2 instances, you're good to go. Otherwise, please refer to AWS documentation in order to setup your CLI. +2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere + in the OS's PATH. +3. Open a command prompt and _cd_ into this folder +4. Run the following commands: +''' + $ terraform init + $ terraform apply -auto-approve +''' +5. Wait until Terraform create all resources and run _aws ec2 describe-instances_. The output should list the newly creates EC2 instance +6. Run _terraform destroy_ to remove the previously creates namespace. + diff --git a/terraform/best-practices/ec2-simple/main.tf b/terraform/best-practices/ec2-simple/main.tf new file mode 100644 index 0000000000..57fb9d1757 --- /dev/null +++ b/terraform/best-practices/ec2-simple/main.tf @@ -0,0 +1,33 @@ +# +# Resource definitions +# + +data "aws_ami" "apache" { + filter { + name = "name" + values = [var.ami_name] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } + + owners = [var.ami_owner] + + most_recent = true +} + +resource "aws_instance" "web" { + ami = data.aws_ami.apache.id + instance_type = "t2.micro" + subnet_id = aws_subnet.frontend.id +} +resource "aws_subnet" "frontend" { + vpc_id = aws_vpc.apps.id + cidr_block = "10.0.1.0/24" +} + +resource "aws_vpc" "apps" { + cidr_block = "10.0.0.0/16" +} diff --git a/terraform/best-practices/ec2-simple/providers.tf b/terraform/best-practices/ec2-simple/providers.tf new file mode 100644 index 0000000000..fa5826b067 --- /dev/null +++ b/terraform/best-practices/ec2-simple/providers.tf @@ -0,0 +1,6 @@ +# +# Providers definitions +# +provider "aws" { + version = "~> 2.53" +} \ No newline at end of file diff --git a/terraform/best-practices/ec2-simple/variables.tf b/terraform/best-practices/ec2-simple/variables.tf new file mode 100644 index 0000000000..2a7fddcd33 --- /dev/null +++ b/terraform/best-practices/ec2-simple/variables.tf @@ -0,0 +1,15 @@ +# +# Variables +# + +variable "ami_name" { + type = string + description = "AMI name to use for our EC2 instance. Defaults to Ubuntu 18.04 (Bionic)" + default = "ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-*" +} + +variable "ami_owner" { + type = string + description = "AMI Owner ID to use for our EC2 instance. Defaults to 099720109477 (Canonical)" + default = "099720109477" +} \ No newline at end of file diff --git a/terraform/best-practices/k8s-basic/.gitignore b/terraform/best-practices/k8s-basic/.gitignore new file mode 100644 index 0000000000..a70da3ca16 --- /dev/null +++ b/terraform/best-practices/k8s-basic/.gitignore @@ -0,0 +1,4 @@ +*.tfvars +*.tfstate +*.tfstate.backup +.terraform diff --git a/terraform/best-practices/k8s-basic/SETUP.md b/terraform/best-practices/k8s-basic/SETUP.md new file mode 100644 index 0000000000..479bb75274 --- /dev/null +++ b/terraform/best-practices/k8s-basic/SETUP.md @@ -0,0 +1,15 @@ +# Setup instructions + +1. Mak sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output. + If you get a list of nodes that contains at least one _ready_ module, you're good to go +2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere + in the OS's PATH. +3. Open a command prompt and _cd_ into this folder +4. Run the following commands: +''' + $ terraform init + $ terraform apply -auto-approve +''' +5. Wait until Terraform create all resources and run _kubectl get namespaces_. The output should now have a new "hello-terraform" namespace. +6. Run _terraform destroy_ to remove the previously creates namespace. + diff --git a/terraform/best-practices/k8s-basic/main.tf b/terraform/best-practices/k8s-basic/main.tf new file mode 100644 index 0000000000..5eb3749930 --- /dev/null +++ b/terraform/best-practices/k8s-basic/main.tf @@ -0,0 +1,12 @@ +# +# Resource definitions +# + +resource "kubernetes_namespace" "hello" { + metadata { + labels = { + terraform = "true" + } + name = var.namespace_name + } +} \ No newline at end of file diff --git a/terraform/best-practices/k8s-basic/providers.tf b/terraform/best-practices/k8s-basic/providers.tf new file mode 100644 index 0000000000..385f857a11 --- /dev/null +++ b/terraform/best-practices/k8s-basic/providers.tf @@ -0,0 +1,6 @@ +# +# Providers definitions +# +provider "kubernetes" { + version = "~> 1.11" +} \ No newline at end of file diff --git a/terraform/best-practices/k8s-basic/variables.tf b/terraform/best-practices/k8s-basic/variables.tf new file mode 100644 index 0000000000..b9217079bf --- /dev/null +++ b/terraform/best-practices/k8s-basic/variables.tf @@ -0,0 +1,9 @@ +# +# Variables +# + +variable "namespace_name" { + type = string + description = "Name to use for the created namespace" + default = "hello-terraform" +} \ No newline at end of file diff --git a/terraform/best-practices/k8s-modules/.gitignore b/terraform/best-practices/k8s-modules/.gitignore new file mode 100644 index 0000000000..a70da3ca16 --- /dev/null +++ b/terraform/best-practices/k8s-modules/.gitignore @@ -0,0 +1,4 @@ +*.tfvars +*.tfstate +*.tfstate.backup +.terraform diff --git a/terraform/best-practices/k8s-modules/SETUP.md b/terraform/best-practices/k8s-modules/SETUP.md new file mode 100644 index 0000000000..b7e4c2764d --- /dev/null +++ b/terraform/best-practices/k8s-modules/SETUP.md @@ -0,0 +1,21 @@ +# Kubernetes multimodule sample + +This sample deploys two services behind a Kubernetes ingress. + +# Setup instructions + +1. Mak sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output. + If you get a list of nodes that contains at least one _ready_ module, you're good to go +2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere + in the OS's PATH. +3. Open a command prompt and _cd_ into this folder +4. Run the following commands: +''' + $ terraform init + $ terraform apply -auto-approve +''' +5. Wait until Terraform create all resources and run _kubectl get services_. The output should now have a few services. +6. Run _terraform destroy_ to remove the previously creates namespace. + + + diff --git a/terraform/best-practices/k8s-modules/main.tf b/terraform/best-practices/k8s-modules/main.tf new file mode 100644 index 0000000000..86426b33db --- /dev/null +++ b/terraform/best-practices/k8s-modules/main.tf @@ -0,0 +1,27 @@ +/* + * Top-level definitions + */ + +//================================================================== Ingress + +module "ingress_www_petshop_com_br" { + source = "./modules/ingress/www.petshop.com.br" + ingress_host = "www.petshop.com.br" +} + +//================================================================== Deployments + +module "SvcCustomer" { + source = "./modules/SvcCustomer" +} + +module "SvcFeedback" { + source = "./modules/SvcFeedback" +} + + + + + + + diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf new file mode 100644 index 0000000000..1ca0c91545 --- /dev/null +++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/main.tf @@ -0,0 +1,68 @@ +/* + * SvcCustomer deployment resources + */ + +resource "kubernetes_deployment" "SvcCustomer" { + + metadata { + name = "svccustomer" + labels = { + app = "SvcCustomer" + } + } + + spec { + replicas = 1 + + selector { + match_labels = { + app = "SvcCustomer" + } + } + + template { + metadata { + labels = { + app = "SvcCustomer" + } + } + + spec { + image_pull_secrets { + name = "docker-config" + } + + + container { + image = "inanimate/echo-server" + name = "svccustomer-httpd" + env { + name = "PORT" + value = "80" + } + } + } + } + } +} + +resource "kubernetes_service" "SvcCustomer" { + metadata { + name = "svccustomer" + } + + spec { + + selector = { + app = "SvcCustomer" + } + + session_affinity = "ClientIP" + port { + port = 80 + } + + //type = "LoadBalancer" + } + } + \ No newline at end of file diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf new file mode 100644 index 0000000000..8a37fdf375 --- /dev/null +++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/outputs.tf @@ -0,0 +1,3 @@ +/* + * SvcCustomer output values + */ diff --git a/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf b/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf new file mode 100644 index 0000000000..3dfcfcd264 --- /dev/null +++ b/terraform/best-practices/k8s-modules/modules/SvcCustomer/variables.tf @@ -0,0 +1,5 @@ +/* + * SvcCustomer deployment variables + */ + + \ No newline at end of file diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf new file mode 100644 index 0000000000..0f84c9163e --- /dev/null +++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/main.tf @@ -0,0 +1,69 @@ +/* + * SvcFeedback deployment resources + */ + +resource "kubernetes_deployment" "SvcFeedback" { + + metadata { + name = "svcfeedback" + labels = { + app = "SvcFeedback" + } + } + + spec { + replicas = 1 + + selector { + match_labels = { + app = "SvcFeedback" + } + } + + template { + metadata { + labels = { + app = "SvcFeedback" + } + } + + spec { + image_pull_secrets { + name = "docker-config" + } + + + container { + image = "inanimate/echo-server" + name = "svcfeedback-httpd" + env { + name = "PORT" + value = "80" + } + } + + } + } + } +} + +resource "kubernetes_service" "SvcFeedback" { + metadata { + name = "svcfeedback" + } + + spec { + + selector = { + app = "SvcFeedback" + } + + session_affinity = "ClientIP" + port { + port = 80 + } + + //type = "LoadBalancer" + } + } + \ No newline at end of file diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf new file mode 100644 index 0000000000..e08c17d4b4 --- /dev/null +++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/outputs.tf @@ -0,0 +1,3 @@ +/* + * SvcFeedback output values + */ diff --git a/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf b/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf new file mode 100644 index 0000000000..d8076d41a4 --- /dev/null +++ b/terraform/best-practices/k8s-modules/modules/SvcFeedback/variables.tf @@ -0,0 +1,5 @@ +/* + * SvcFeedback deployment variables + */ + + \ No newline at end of file diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf new file mode 100644 index 0000000000..0dbda48981 --- /dev/null +++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/main.tf @@ -0,0 +1,41 @@ +/* + * Kubernetes Ingress module + */ +locals { + iname = var.ingress_name == "" ? join("-",["ingress",sha1(uuid())]) : var.ingress_name +} + +resource "kubernetes_ingress" "ingress" { + metadata { + name = local.iname + annotations = map( + "nginx.ingress.kubernetes.io/rewrite-target","/" + ) + } + spec { + rule { + http { + path { + backend { + service_name = "svccustomer" + service_port = 80 + } + path = "/customers" + } + path { + backend { + service_name = "svcfeedback" + service_port = 80 + } + path = "/feedback" + } + } + } +/* + tls { + secret_name = "tls-secret" + } +*/ + } +} + diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf new file mode 100644 index 0000000000..e604417b05 --- /dev/null +++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/outputs.tf @@ -0,0 +1,5 @@ +/* + * Output variables + */ + + diff --git a/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf new file mode 100644 index 0000000000..9b06128ec5 --- /dev/null +++ b/terraform/best-practices/k8s-modules/modules/ingress/www.petshop.com.br/variables.tf @@ -0,0 +1,20 @@ +/* + * Kubernetes Ingress module + */ + + +variable "ingress_name" { + type = string + description = "Ingress name. Defaults to a random name." + default = "" +} + +variable "ingress_host" { + type = string + description = "Ingress hostname" + default = "www.petshop.com.br" +} + + + + diff --git a/terraform/best-practices/k8s-modules/provider.tf b/terraform/best-practices/k8s-modules/provider.tf new file mode 100644 index 0000000000..bb90d66ecf --- /dev/null +++ b/terraform/best-practices/k8s-modules/provider.tf @@ -0,0 +1,13 @@ +# +# Provider configurations +# This file will *NOT* be overwriten upon regeneration, so it's safe +# to add your own customizations +# + +provider "kubernetes" { + version = "~> 1.10" +} + +provider "random" { + version = "~> 2.2" +} \ No newline at end of file diff --git a/terraform/hello-terraform/.gitignore b/terraform/hello-terraform/.gitignore new file mode 100644 index 0000000000..452502c50f --- /dev/null +++ b/terraform/hello-terraform/.gitignore @@ -0,0 +1,6 @@ +*.tfvars +*.tfstate +*.tfstate.backup +.terraform +hello.txt + diff --git a/terraform/hello-terraform/main.tf b/terraform/hello-terraform/main.tf new file mode 100644 index 0000000000..d6a726fa36 --- /dev/null +++ b/terraform/hello-terraform/main.tf @@ -0,0 +1,7 @@ +provider "local" { + version = "~> 1.4" +} +resource "local_file" "hello" { + content = "Hello, Terraform" + filename = "hello.txt" +} From 405831d3da839c12ca73562112653842ee83ef44 Mon Sep 17 00:00:00 2001 From: patkorek Date: Tue, 31 Mar 2020 07:36:44 +0200 Subject: [PATCH 006/194] changed tabs to spaces --- ...GraphQL collection.postman_collection.json | 334 +++++++++--------- 1 file changed, 167 insertions(+), 167 deletions(-) diff --git a/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json b/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json index 7fcaa2c76d..f19bc1febb 100644 --- a/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json +++ b/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json @@ -1,169 +1,169 @@ { - "info": { - "_postman_id": "910d9690-f629-4491-bbbd-adb30982a386", - "name": "GraphQL collection", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "mutations", - "item": [ - { - "name": "writePost", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "mutation writePost ($title: String!, $text: String!, $category: String) {\n writePost (title: $title, text: $text, category: $category) {\n id\n title\n text\n category\n }\n}", - "variables": "{\n \"title\": \"\",\n \"text\": \"\",\n \"category\": \"\"\n}" - }, - "options": { - "graphql": {} - } - }, - "url": { - "raw": "http://localhost:9090/springbootapp/graphql", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "9090", - "path": [ - "springbootapp", - "graphql" - ] - } - }, - "response": [] - } - ], - "protocolProfileBehavior": {} - }, - { - "name": "queries", - "item": [ - { - "name": "get recent posts", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "{\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n text\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}", - "variables": "" - } - }, - "url": { - "raw": "http://localhost:9090/springbootapp/graphql", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "9090", - "path": [ - "springbootapp", - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "recentPosts - variables", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "query recentPosts ($count: Int, $offset: Int) {\n recentPosts (count: $count, offset: $offset) {\n id\n title\n text\n category\n }\n}", - "variables": "{\n \"count\": 1,\n \"offset\": 0\n}" - }, - "options": { - "graphql": {} - } - }, - "url": { - "raw": "http://localhost:9090/springbootapp/graphql", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "9090", - "path": [ - "springbootapp", - "graphql" - ] - } - }, - "response": [] - }, - { - "name": "get recent posts - raw", - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "application/graphql", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "query {\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}" - }, - "url": { - "raw": "http://localhost:9090/springbootapp/graphql", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "9090", - "path": [ - "springbootapp", - "graphql" - ] - } - }, - "response": [] - } - ], - "protocolProfileBehavior": {} - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "id": "b54f267b-c450-4f2d-8105-2f23bab4c922", - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "id": "00b575be-03d4-4b29-b137-733ead139638", - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ], - "variable": [ - { - "id": "20a274e5-6d51-40d6-81cb-af9eb115b21b", - "key": "url", - "value": "", - "type": "string" - } - ], - "protocolProfileBehavior": {} + "info": { + "_postman_id": "910d9690-f629-4491-bbbd-adb30982a386", + "name": "GraphQL collection", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "mutations", + "item": [ + { + "name": "writePost", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "graphql", + "graphql": { + "query": "mutation writePost ($title: String!, $text: String!, $category: String) {\n writePost (title: $title, text: $text, category: $category) {\n id\n title\n text\n category\n }\n}", + "variables": "{\n \"title\": \"\",\n \"text\": \"\",\n \"category\": \"\"\n}" + }, + "options": { + "graphql": {} + } + }, + "url": { + "raw": "http://localhost:9090/springbootapp/graphql", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "9090", + "path": [ + "springbootapp", + "graphql" + ] + } + }, + "response": [] + } + ], + "protocolProfileBehavior": {} + }, + { + "name": "queries", + "item": [ + { + "name": "get recent posts", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "graphql", + "graphql": { + "query": "{\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n text\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}", + "variables": "" + } + }, + "url": { + "raw": "http://localhost:9090/springbootapp/graphql", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "9090", + "path": [ + "springbootapp", + "graphql" + ] + } + }, + "response": [] + }, + { + "name": "recentPosts - variables", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "graphql", + "graphql": { + "query": "query recentPosts ($count: Int, $offset: Int) {\n recentPosts (count: $count, offset: $offset) {\n id\n title\n text\n category\n }\n}", + "variables": "{\n \"count\": 1,\n \"offset\": 0\n}" + }, + "options": { + "graphql": {} + } + }, + "url": { + "raw": "http://localhost:9090/springbootapp/graphql", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "9090", + "path": [ + "springbootapp", + "graphql" + ] + } + }, + "response": [] + }, + { + "name": "get recent posts - raw", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/graphql", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "query {\r\n recentPosts(count: 10, offset: 0) {\r\n id\r\n title\r\n category\r\n author {\r\n id\r\n name\r\n thumbnail\r\n }\r\n }\r\n}" + }, + "url": { + "raw": "http://localhost:9090/springbootapp/graphql", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "9090", + "path": [ + "springbootapp", + "graphql" + ] + } + }, + "response": [] + } + ], + "protocolProfileBehavior": {} + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "b54f267b-c450-4f2d-8105-2f23bab4c922", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "00b575be-03d4-4b29-b137-733ead139638", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "id": "20a274e5-6d51-40d6-81cb-af9eb115b21b", + "key": "url", + "value": "", + "type": "string" + } + ], + "protocolProfileBehavior": {} } \ No newline at end of file From 6534bddb6c73cae5ba2614fbc509535ae46babae Mon Sep 17 00:00:00 2001 From: mthomas Date: Tue, 31 Mar 2020 04:43:06 -0500 Subject: [PATCH 007/194] Move code to core-java-modules/core-java-concurrency-advanced-3Add Add missing 'Unit' in test name --- .../com/baeldung/atomicstampedreference}/SafeAccount.java | 6 +++--- .../atomicstampedreference/ThreadSafeAccountUnitTest.java} | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) rename core-java-modules/{core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic => core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference}/SafeAccount.java (82%) rename core-java-modules/{core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java => core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java} (70%) diff --git a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeAccount.java b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/SafeAccount.java similarity index 82% rename from core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeAccount.java rename to core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/SafeAccount.java index febfd481c3..fe41429e22 100644 --- a/core-java-modules/core-java-concurrency-advanced/src/main/java/com/baeldung/concurrent/atomic/SafeAccount.java +++ b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/SafeAccount.java @@ -1,12 +1,12 @@ -package com.baeldung.concurrent.atomic; +package com.baeldung.atomicstampedreference; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicStampedReference; public class SafeAccount { - AtomicInteger stamp = new AtomicInteger(0); - AtomicStampedReference balance = new AtomicStampedReference<>(0, 0); + private AtomicInteger stamp = new AtomicInteger(0); + private AtomicStampedReference balance = new AtomicStampedReference<>(0, 0); public int getBalance() { return this.balance.get(new int[1]); diff --git a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java similarity index 70% rename from core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java rename to core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java index b9a5fe7773..bd33d5b4ec 100644 --- a/core-java-modules/core-java-concurrency-advanced/src/test/java/com/baeldung/concurrent/atomic/ThreadSafeAccountTest.java +++ b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java @@ -1,12 +1,12 @@ -package com.baeldung.concurrent.atomic; +package com.baeldung.atomicstampedreference; import org.junit.Assert; import org.junit.Test; -public class ThreadSafeAccountTest { +public class ThreadSafeAccountUnitTest { @Test - public void givenMultiThread_whenSafeAccountSetBalance() throws InterruptedException { + public void givenMultiThread_whenSafeAccount_thenSetBalance() throws InterruptedException { SafeAccount account = new SafeAccount(); Thread t = new Thread(() -> { while (!account.withdrawal(100)) From aaffd9614fc1675ab05f992eec62c90be5aef76f Mon Sep 17 00:00:00 2001 From: naXa! Date: Mon, 25 Mar 2019 02:00:03 +0300 Subject: [PATCH 008/194] [BAEL-2749] add dbunit module to parent pom --- pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pom.xml b/pom.xml index 04a2ce054c..734e2c8ab9 100644 --- a/pom.xml +++ b/pom.xml @@ -601,6 +601,8 @@ + dbunit + parent-boot-1 parent-boot-2 parent-spring-4 @@ -1288,6 +1290,8 @@ + dbunit + parent-boot-1 parent-boot-2 parent-spring-4 From a65c5bf202c3326514e7d6c1408bd9e445c06fd9 Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Sun, 29 Mar 2020 11:37:19 +0200 Subject: [PATCH 009/194] [BAEL-2749] Introduces Assertj and uses builder pattern --- dbunit/pom.xml | 36 ++++++++++++++++--- .../baeldung/dbunit/OldSchoolDbUnitTest.java | 8 +++-- .../dbunit/PrepAndExpectedDbUnitTest.java | 12 +++++-- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/dbunit/pom.xml b/dbunit/pom.xml index b77b15f2d4..ab0befcf4c 100644 --- a/dbunit/pom.xml +++ b/dbunit/pom.xml @@ -3,6 +3,16 @@ 4.0.0 dbunit 1.0 + + 1.4.200 + + 1.8 + 1.8 + 3.8.1 + + 3.14.0 + 2.6.0 + dbunit @@ -22,14 +32,30 @@ com.h2database h2 - 1.4.197 + ${h2.version} + test + + + + org.assertj + assertj-core + ${assertj-core.version} test - - - 2.6.0 - + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven-compiler-plugin.source} + ${maven-compiler-plugin.target} + + + + diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java index a703863614..2a2f25971b 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java @@ -6,6 +6,7 @@ import org.dbunit.JdbcDatabaseTester; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ITable; import org.dbunit.dataset.xml.FlatXmlDataSet; +import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; import org.dbunit.operation.DatabaseOperation; import org.junit.After; import org.junit.Before; @@ -16,6 +17,7 @@ import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -74,7 +76,7 @@ public class OldSchoolDbUnitTest { final Connection connection = tester.getConnection().getConnection(); final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml"); - ITable expectedTable = (new FlatXmlDataSet(is)).getTable("items"); + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); //expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"}); // Act @@ -94,7 +96,7 @@ public class OldSchoolDbUnitTest { final Connection connection = tester.getConnection().getConnection(); final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml"); - ITable expectedTable = (new FlatXmlDataSet(is)).getTable("items"); + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); //expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"}); // Act @@ -105,7 +107,7 @@ public class OldSchoolDbUnitTest { ITable actualTable = databaseDataSet.getTable("items"); //actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); - Assertion.assertEquals(expectedTable, actualTable); + assertThat(actualTable).isEqualTo(actualTable); } } diff --git a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java index c3882d5eab..c322cf0ae3 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java @@ -1,6 +1,10 @@ package com.baeldung.dbunit; -import org.dbunit.*; +import org.dbunit.DefaultPrepAndExpectedTestCase; +import org.dbunit.IDatabaseTester; +import org.dbunit.JdbcDatabaseTester; +import org.dbunit.PrepAndExpectedTestCaseSteps; +import org.dbunit.VerifyTableDefinition; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; import org.dbunit.operation.DatabaseOperation; @@ -12,6 +16,8 @@ import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; +import static org.assertj.core.api.Assertions.assertThat; + public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { private static final String JDBC_DRIVER = org.h2.Driver.class.getName(); private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"; @@ -63,8 +69,8 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); // or place assertions at the end - assertTrue(rs.next()); - assertEquals("Xavier", rs.getString("last_name")); + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("last_name")).isEqualTo("Xavier"); } @Test From 71ba591868ed0f200f16c17a3d116cf6c32a559b Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Sun, 29 Mar 2020 18:16:45 +0200 Subject: [PATCH 010/194] [BAEL-2749] Select and Delete for OldSchool --- dbunit/pom.xml | 1 + .../baeldung/dbunit/OldSchoolDbUnitTest.java | 39 +++++++++++-------- .../items_exp_delete_no_produced.xml | 8 ++++ 3 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 dbunit/src/test/resources/items_exp_delete_no_produced.xml diff --git a/dbunit/pom.xml b/dbunit/pom.xml index ab0befcf4c..7ca53cd3be 100644 --- a/dbunit/pom.xml +++ b/dbunit/pom.xml @@ -13,6 +13,7 @@ 3.14.0 2.6.0 + dbunit diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java index 2a2f25971b..e64b49263a 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java @@ -5,7 +5,7 @@ import org.dbunit.IDatabaseTester; import org.dbunit.JdbcDatabaseTester; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ITable; -import org.dbunit.dataset.xml.FlatXmlDataSet; +import org.dbunit.dataset.filter.DefaultColumnFilter; import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; import org.dbunit.operation.DatabaseOperation; import org.junit.After; @@ -18,8 +18,7 @@ import java.sql.Connection; import java.sql.ResultSet; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.dbunit.Assertion.assertEquals; public class OldSchoolDbUnitTest { private static final String JDBC_DRIVER = org.h2.Driver.class.getName(); @@ -44,7 +43,7 @@ public class OldSchoolDbUnitTest { private static IDataSet initDataSet() throws Exception { final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml"); - return new FlatXmlDataSet(is); + return new FlatXmlDataSetBuilder().build(is); } @Before @@ -59,35 +58,43 @@ public class OldSchoolDbUnitTest { @Test public void testSelect() throws Exception { - // Arrange final Connection connection = tester.getConnection().getConnection(); - // Act final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); - // Assert - assertTrue(rs.next()); - assertEquals("Grey T-Shirt", rs.getString("title")); + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); } @Test public void testDelete() throws Exception { - // Arrange final Connection connection = tester.getConnection().getConnection(); final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml"); ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - //expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"}); - // Act connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - // Assert final IDataSet databaseDataSet = tester.getConnection().createDataSet(); ITable actualTable = databaseDataSet.getTable("items"); - //actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); - Assertion.assertEquals(expectedTable, actualTable); + assertEquals(expectedTable, actualTable); + } + + @Test + public void testDeleteWithExcludedColumns() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete_no_produced.xml"); + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); + + assertEquals(expectedTable, actualTable); } @Test @@ -107,7 +114,7 @@ public class OldSchoolDbUnitTest { ITable actualTable = databaseDataSet.getTable("items"); //actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); - assertThat(actualTable).isEqualTo(actualTable); + assertEquals(expectedTable, actualTable); } } diff --git a/dbunit/src/test/resources/items_exp_delete_no_produced.xml b/dbunit/src/test/resources/items_exp_delete_no_produced.xml new file mode 100644 index 0000000000..c9b182a1b2 --- /dev/null +++ b/dbunit/src/test/resources/items_exp_delete_no_produced.xml @@ -0,0 +1,8 @@ + + + + + + + + From e4f4f7110b33f753a50b5f56443b8dff8ab014b5 Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Sun, 29 Mar 2020 21:47:00 +0200 Subject: [PATCH 011/194] [BAEL-2749] Code refactoring --- dbunit/src/main/resources/logback.xml | 2 +- .../baeldung/dbunit/ConnectionSettings.java | 8 ++++ .../baeldung/dbunit/OldSchoolDbUnitTest.java | 32 ++++++++----- .../dbunit/PrepAndExpectedDbUnitTest.java | 48 +++++++------------ .../com/baeldung/dbunit/SampleDbUnitTest.java | 23 ++++----- dbunit/src/test/resources/data.xml | 12 ++--- .../src/test/resources/items_exp_delete.xml | 8 ++-- .../items_exp_delete_no_produced.xml | 8 ++-- .../src/test/resources/items_exp_rename.xml | 10 ++-- .../items_exp_rename_no_produced.xml | 9 ++++ dbunit/src/test/resources/schema.sql | 34 ++++++------- dbunit/src/test/resources/users.xml | 6 +-- .../src/test/resources/users_exp_delete.xml | 4 +- .../src/test/resources/users_exp_rename.xml | 6 +-- 14 files changed, 108 insertions(+), 102 deletions(-) create mode 100644 dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java create mode 100644 dbunit/src/test/resources/items_exp_rename_no_produced.xml diff --git a/dbunit/src/main/resources/logback.xml b/dbunit/src/main/resources/logback.xml index 7d900d8ea8..26beb6d5b4 100644 --- a/dbunit/src/main/resources/logback.xml +++ b/dbunit/src/main/resources/logback.xml @@ -8,6 +8,6 @@ - + \ No newline at end of file diff --git a/dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java b/dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java new file mode 100644 index 0000000000..e842022292 --- /dev/null +++ b/dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java @@ -0,0 +1,8 @@ +package com.baeldung.dbunit; + +public class ConnectionSettings { + public static final String JDBC_DRIVER = org.h2.Driver.class.getName(); + public static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"; + public static final String USER = "sa"; + public static final String PASSWORD = ""; +} diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java index e64b49263a..0b63184951 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java @@ -1,6 +1,5 @@ package com.baeldung.dbunit; -import org.dbunit.Assertion; import org.dbunit.IDatabaseTester; import org.dbunit.JdbcDatabaseTester; import org.dbunit.dataset.IDataSet; @@ -17,14 +16,14 @@ import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; +import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; +import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; +import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; +import static com.baeldung.dbunit.ConnectionSettings.USER; import static org.assertj.core.api.Assertions.assertThat; import static org.dbunit.Assertion.assertEquals; public class OldSchoolDbUnitTest { - private static final String JDBC_DRIVER = org.h2.Driver.class.getName(); - private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"; - private static final String USER = "sa"; - private static final String PASSWORD = ""; private static IDatabaseTester tester = null; @@ -99,20 +98,31 @@ public class OldSchoolDbUnitTest { @Test public void testUpdate() throws Exception { - // Arrange final Connection connection = tester.getConnection().getConnection(); final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml"); - ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - //expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"produced"}); + final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - // Act connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - // Assert final IDataSet databaseDataSet = tester.getConnection().createDataSet(); ITable actualTable = databaseDataSet.getTable("items"); - //actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); + + assertEquals(expectedTable, actualTable); + } + + @Test + public void testUpdateWithExcludedColumns() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename_no_produced.xml"); + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); assertEquals(expectedTable, actualTable); } diff --git a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java index c322cf0ae3..bb70136de2 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java @@ -16,13 +16,13 @@ import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; +import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; +import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; +import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; +import static com.baeldung.dbunit.ConnectionSettings.USER; import static org.assertj.core.api.Assertions.assertThat; public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { - private static final String JDBC_DRIVER = org.h2.Driver.class.getName(); - private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"; - private static final String USER = "sa"; - private static final String PASSWORD = ""; @Override public void setUp() throws Exception { @@ -49,60 +49,46 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { @Test public void testSelect() throws Exception { - // Arrange final Connection connection = getConnection().getConnection(); final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; final String[] prepDataFiles = {"/users.xml"}; final String[] expectedDataFiles = {"/users.xml"}; - final PrepAndExpectedTestCaseSteps testSteps = () -> { - // invoke the method being tested here; for the sake of simplicity we use JDBC API directly in this example - final ResultSet rs = connection.createStatement().executeQuery("select * from USERS where id = 1"); + final PrepAndExpectedTestCaseSteps testSteps = + () -> connection + .createStatement() + .executeQuery("select * from USERS where id = 1"); - // either place assertions here - //assertTrue(rs.next()); - //assertEquals("Xavier", rs.getString("last_name")); - - return rs; - }; - - // Act final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - // or place assertions at the end assertThat(rs.next()).isTrue(); assertThat(rs.getString("last_name")).isEqualTo("Xavier"); } @Test public void testUpdate() throws Exception { - // Arrange final Connection connection = getConnection().getConnection(); final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; // define tables to verify - final String[] prepDataFiles = {"/users.xml"}; // define prep files - final String[] expectedDataFiles = {"/users_exp_rename.xml"}; // define expected files - final PrepAndExpectedTestCaseSteps testSteps = () -> { - // invoke the method being tested here; for the sake of simplicity we use JDBC API directly in this example - return connection.createStatement().executeUpdate("update USERS set first_name = 'new name' where id = 1"); - // after this method exits, dbUnit will: - // * verify configured tables - // * cleanup tables as configured - }; + final String[] prepDataFiles = {"/users.xml"}; + final String[] expectedDataFiles = {"/users_exp_rename.xml"}; + final PrepAndExpectedTestCaseSteps testSteps = + () -> connection + .createStatement() + .executeUpdate("update USERS set first_name = 'new name' where id = 1"); - // Act super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); } @Test public void testDelete() throws Exception { - // Arrange final Connection connection = getConnection().getConnection(); final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; final String[] prepDataFiles = {"/users.xml"}; final String[] expectedDataFiles = {"/users_exp_delete.xml"}; final PrepAndExpectedTestCaseSteps testSteps = - () -> connection.createStatement().executeUpdate("delete from USERS where id = 2"); + () -> connection + .createStatement() + .executeUpdate("delete from USERS where id = 2"); - // Act super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); } diff --git a/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java index cfe4fd4e11..f7970754e7 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java @@ -13,11 +13,13 @@ import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; +import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; +import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; +import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; +import static com.baeldung.dbunit.ConnectionSettings.USER; +import static org.assertj.core.api.Assertions.assertThat; + public class SampleDbUnitTest extends DBTestCase { - private static final String JDBC_DRIVER = org.h2.Driver.class.getName(); - private static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"; - private static final String USER = "sa"; - private static final String PASSWORD = ""; public SampleDbUnitTest(String name) { super(name); @@ -46,29 +48,23 @@ public class SampleDbUnitTest extends DBTestCase { @Test public void testSelect() throws Exception { - // Arrange final Connection connection = getConnection().getConnection(); - // Act final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); - // Assert - assertTrue(rs.next()); - assertEquals("Grey T-Shirt", rs.getString("title")); + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); } @Test public void testDelete() throws Exception { - // Arrange final Connection connection = getConnection().getConnection(); final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml"); ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); - // Act connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - // Assert final IDataSet databaseDataSet = getConnection().createDataSet(); ITable actualTable = databaseDataSet.getTable("items"); @@ -77,16 +73,13 @@ public class SampleDbUnitTest extends DBTestCase { @Test public void testUpdate() throws Exception { - // Arrange final Connection connection = getConnection().getConnection(); final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml"); ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); - // Act connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - // Assert final IDataSet databaseDataSet = getConnection().createDataSet(); ITable actualTable = databaseDataSet.getTable("items"); diff --git a/dbunit/src/test/resources/data.xml b/dbunit/src/test/resources/data.xml index e4498513e0..ac413cfd23 100644 --- a/dbunit/src/test/resources/data.xml +++ b/dbunit/src/test/resources/data.xml @@ -1,11 +1,11 @@ - + - - - - - + + + + + diff --git a/dbunit/src/test/resources/items_exp_delete.xml b/dbunit/src/test/resources/items_exp_delete.xml index 1aaeff59ca..09b78da493 100644 --- a/dbunit/src/test/resources/items_exp_delete.xml +++ b/dbunit/src/test/resources/items_exp_delete.xml @@ -1,8 +1,8 @@ - - - - + + + + diff --git a/dbunit/src/test/resources/items_exp_delete_no_produced.xml b/dbunit/src/test/resources/items_exp_delete_no_produced.xml index c9b182a1b2..dd76e8c6ce 100644 --- a/dbunit/src/test/resources/items_exp_delete_no_produced.xml +++ b/dbunit/src/test/resources/items_exp_delete_no_produced.xml @@ -1,8 +1,8 @@ - - - - + + + + diff --git a/dbunit/src/test/resources/items_exp_rename.xml b/dbunit/src/test/resources/items_exp_rename.xml index 237280e758..830d83499f 100644 --- a/dbunit/src/test/resources/items_exp_rename.xml +++ b/dbunit/src/test/resources/items_exp_rename.xml @@ -1,9 +1,9 @@ - - - - - + + + + + diff --git a/dbunit/src/test/resources/items_exp_rename_no_produced.xml b/dbunit/src/test/resources/items_exp_rename_no_produced.xml new file mode 100644 index 0000000000..991c4726a0 --- /dev/null +++ b/dbunit/src/test/resources/items_exp_rename_no_produced.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/dbunit/src/test/resources/schema.sql b/dbunit/src/test/resources/schema.sql index 9b5018985a..dc4738ca76 100644 --- a/dbunit/src/test/resources/schema.sql +++ b/dbunit/src/test/resources/schema.sql @@ -1,28 +1,28 @@ CREATE TABLE IF NOT EXISTS USERS ( - `id` int AUTO_INCREMENT NOT NULL, - `first_name` varchar(100) NOT NULL, - `last_name` varchar(100) NOT NULL, - PRIMARY KEY (`id`) + `id` int AUTO_INCREMENT NOT NULL, + `first_name` varchar(100) NOT NULL, + `last_name` varchar(100) NOT NULL, + PRIMARY KEY (`id`) ); CREATE TABLE IF NOT EXISTS ITEMS ( - `id` int AUTO_INCREMENT NOT NULL, - `title` varchar(100) NOT NULL, - `produced` date, - `price` float, - PRIMARY KEY (`id`) + `id` int AUTO_INCREMENT NOT NULL, + `title` varchar(100) NOT NULL, + `produced` date, + `price` float, + PRIMARY KEY (`id`) ); CREATE TABLE IF NOT EXISTS PURCHASES ( - `id` int NOT NULL AUTO_INCREMENT, - `id_user` int NOT NULL, - `id_item` int NOT NULL, - `total_price` float NOT NULL, - `quantity` int(11) NOT NULL, - PRIMARY KEY (`id`), - FOREIGN KEY (`id_user`) REFERENCES USERS (`id`) ON DELETE CASCADE, - FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE + `id` int NOT NULL AUTO_INCREMENT, + `id_user` int NOT NULL, + `id_item` int NOT NULL, + `total_price` float NOT NULL, + `quantity` int(11) NOT NULL, + PRIMARY KEY (`id`), + FOREIGN KEY (`id_user`) REFERENCES USERS (`id`) ON DELETE CASCADE, + FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE ); diff --git a/dbunit/src/test/resources/users.xml b/dbunit/src/test/resources/users.xml index cebadf2e67..d8ff78024e 100644 --- a/dbunit/src/test/resources/users.xml +++ b/dbunit/src/test/resources/users.xml @@ -1,7 +1,7 @@ - - - + + + diff --git a/dbunit/src/test/resources/users_exp_delete.xml b/dbunit/src/test/resources/users_exp_delete.xml index 8b72ceef89..c4ea6e64e5 100644 --- a/dbunit/src/test/resources/users_exp_delete.xml +++ b/dbunit/src/test/resources/users_exp_delete.xml @@ -1,6 +1,6 @@ - - + + diff --git a/dbunit/src/test/resources/users_exp_rename.xml b/dbunit/src/test/resources/users_exp_rename.xml index 9bc1254967..c187e1ebe5 100644 --- a/dbunit/src/test/resources/users_exp_rename.xml +++ b/dbunit/src/test/resources/users_exp_rename.xml @@ -1,7 +1,7 @@ - - - + + + From d5d1cc7d580b1749b9f29df644ea34cbddeee8ac Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Tue, 31 Mar 2020 12:02:24 +0200 Subject: [PATCH 012/194] [BAEL-2749] Adds DataSourceBaseDBTestCase --- .../baeldung/dbunit/DataSourceDBUnitTest.java | 46 +++++++++++++++++++ ...{SampleDbUnitTest.java => DbUnitTest.java} | 12 ++--- 2 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java rename dbunit/src/test/java/com/baeldung/dbunit/{SampleDbUnitTest.java => DbUnitTest.java} (85%) diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java new file mode 100644 index 0000000000..154d93e0af --- /dev/null +++ b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.dbunit; + +import org.dbunit.DataSourceBasedDBTestCase; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.h2.jdbcx.JdbcDataSource; +import org.junit.Test; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { + @Override + protected DataSource getDataSource() { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setURL( + "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"); + dataSource.setUser("sa"); + dataSource.setPassword("sa"); + return dataSource; + } + + @Override + protected IDataSet getDataSet() throws Exception { + return new FlatXmlDataSetBuilder().build(getClass() + .getClassLoader() + .getResourceAsStream("data.xml")); + } + + @Test + public void testSimpleDataSet() throws SQLException { + final Connection connection = getDataSource() + .getConnection(); + + final ResultSet rs = connection + .createStatement() + .executeQuery("select * from iTEMS where id = 1"); + + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + } +} diff --git a/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java similarity index 85% rename from dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java rename to dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java index f7970754e7..8d6a94279a 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/SampleDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java @@ -19,9 +19,9 @@ import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; import static com.baeldung.dbunit.ConnectionSettings.USER; import static org.assertj.core.api.Assertions.assertThat; -public class SampleDbUnitTest extends DBTestCase { +public class DbUnitTest extends DBTestCase { - public SampleDbUnitTest(String name) { + public DbUnitTest(String name) { super(name); System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER); System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL); @@ -32,7 +32,7 @@ public class SampleDbUnitTest extends DBTestCase { @Override protected IDataSet getDataSet() throws Exception { - final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml"); + final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("data.xml"); return new FlatXmlDataSetBuilder().build(is); } @@ -53,14 +53,14 @@ public class SampleDbUnitTest extends DBTestCase { final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + assertThat(rs.getString( "title")).isEqualTo("Grey T-Shirt"); } @Test public void testDelete() throws Exception { final Connection connection = getConnection().getConnection(); - final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml"); + final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml"); ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); @@ -75,7 +75,7 @@ public class SampleDbUnitTest extends DBTestCase { public void testUpdate() throws Exception { final Connection connection = getConnection().getConnection(); - final InputStream is = SampleDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml"); + final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml"); ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); From ef19d83db5f48290978f5c4e9e3c738a53e6087c Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Tue, 31 Mar 2020 12:38:39 +0200 Subject: [PATCH 013/194] [BAEL-2749] USERS table name changed to CLIENTS --- .../baeldung/dbunit/DataSourceDBUnitTest.java | 18 +++++++++++++++--- .../java/com/baeldung/dbunit/DbUnitTest.java | 1 - .../dbunit/PrepAndExpectedDbUnitTest.java | 12 ++++++------ dbunit/src/test/resources/data.xml | 2 +- dbunit/src/test/resources/schema.sql | 4 ++-- dbunit/src/test/resources/users.xml | 6 +++--- dbunit/src/test/resources/users_exp_delete.xml | 4 ++-- dbunit/src/test/resources/users_exp_rename.xml | 6 +++--- 8 files changed, 32 insertions(+), 21 deletions(-) diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java index 154d93e0af..c8045394c4 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java @@ -1,7 +1,9 @@ package com.baeldung.dbunit; +import org.dbunit.Assertion; import org.dbunit.DataSourceBasedDBTestCase; import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; import org.h2.jdbcx.JdbcDataSource; import org.junit.Test; @@ -11,16 +13,17 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; +import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; import static org.assertj.core.api.Assertions.assertThat; public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { + @Override protected DataSource getDataSource() { JdbcDataSource dataSource = new JdbcDataSource(); - dataSource.setURL( - "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"); + dataSource.setURL(JDBC_URL); dataSource.setUser("sa"); - dataSource.setPassword("sa"); + dataSource.setPassword(""); return dataSource; } @@ -43,4 +46,13 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { assertThat(rs.next()).isTrue(); assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); } + + @Test + public void testEmptySchema() throws Exception { + IDataSet expectedDataSet = getDataSet(); + ITable expectedTable = expectedDataSet.getTable("CLIENTS"); + IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("CLIENTS"); + Assertion.assertEquals(expectedTable, actualTable); + } } diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java index 8d6a94279a..479ea3dd51 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java @@ -27,7 +27,6 @@ public class DbUnitTest extends DBTestCase { System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL); System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER); System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD); - // System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_SCHEMA, ""); } @Override diff --git a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java index bb70136de2..2c7e5de508 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java @@ -50,13 +50,13 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { @Test public void testSelect() throws Exception { final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; + final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; final String[] prepDataFiles = {"/users.xml"}; final String[] expectedDataFiles = {"/users.xml"}; final PrepAndExpectedTestCaseSteps testSteps = () -> connection .createStatement() - .executeQuery("select * from USERS where id = 1"); + .executeQuery("select * from CLIENTS where id = 1"); final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); @@ -67,13 +67,13 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { @Test public void testUpdate() throws Exception { final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; // define tables to verify + final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; // define tables to verify final String[] prepDataFiles = {"/users.xml"}; final String[] expectedDataFiles = {"/users_exp_rename.xml"}; final PrepAndExpectedTestCaseSteps testSteps = () -> connection .createStatement() - .executeUpdate("update USERS set first_name = 'new name' where id = 1"); + .executeUpdate("update CLIENTS set first_name = 'new name' where id = 1"); super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); } @@ -81,13 +81,13 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { @Test public void testDelete() throws Exception { final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("USERS", new String[]{})}; + final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; final String[] prepDataFiles = {"/users.xml"}; final String[] expectedDataFiles = {"/users_exp_delete.xml"}; final PrepAndExpectedTestCaseSteps testSteps = () -> connection .createStatement() - .executeUpdate("delete from USERS where id = 2"); + .executeUpdate("delete from CLIENTS where id = 2"); super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); } diff --git a/dbunit/src/test/resources/data.xml b/dbunit/src/test/resources/data.xml index ac413cfd23..4230073fc6 100644 --- a/dbunit/src/test/resources/data.xml +++ b/dbunit/src/test/resources/data.xml @@ -1,7 +1,7 @@ - + diff --git a/dbunit/src/test/resources/schema.sql b/dbunit/src/test/resources/schema.sql index dc4738ca76..c2a8d2d630 100644 --- a/dbunit/src/test/resources/schema.sql +++ b/dbunit/src/test/resources/schema.sql @@ -1,4 +1,4 @@ -CREATE TABLE IF NOT EXISTS USERS +CREATE TABLE IF NOT EXISTS CLIENTS ( `id` int AUTO_INCREMENT NOT NULL, `first_name` varchar(100) NOT NULL, @@ -23,6 +23,6 @@ CREATE TABLE IF NOT EXISTS PURCHASES `total_price` float NOT NULL, `quantity` int(11) NOT NULL, PRIMARY KEY (`id`), - FOREIGN KEY (`id_user`) REFERENCES USERS (`id`) ON DELETE CASCADE, + FOREIGN KEY (`id_user`) REFERENCES CLIENTS (`id`) ON DELETE CASCADE, FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE ); diff --git a/dbunit/src/test/resources/users.xml b/dbunit/src/test/resources/users.xml index d8ff78024e..9c14435362 100644 --- a/dbunit/src/test/resources/users.xml +++ b/dbunit/src/test/resources/users.xml @@ -1,7 +1,7 @@ - - - + + + diff --git a/dbunit/src/test/resources/users_exp_delete.xml b/dbunit/src/test/resources/users_exp_delete.xml index c4ea6e64e5..3780c00c4c 100644 --- a/dbunit/src/test/resources/users_exp_delete.xml +++ b/dbunit/src/test/resources/users_exp_delete.xml @@ -1,6 +1,6 @@ - - + + diff --git a/dbunit/src/test/resources/users_exp_rename.xml b/dbunit/src/test/resources/users_exp_rename.xml index c187e1ebe5..a576cc9e80 100644 --- a/dbunit/src/test/resources/users_exp_rename.xml +++ b/dbunit/src/test/resources/users_exp_rename.xml @@ -1,7 +1,7 @@ - - - + + + From 07947ce4d62daae7bc147fe7b4ac106b070b4d0e Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Tue, 31 Mar 2020 13:31:11 +0200 Subject: [PATCH 014/194] [BAEL-2749] Insertion test with ignore cols --- .../baeldung/dbunit/DataSourceDBUnitTest.java | 18 ++++++++++++++++++ dbunit/src/test/resources/expected-user.xml | 5 +++++ 2 files changed, 23 insertions(+) create mode 100644 dbunit/src/test/resources/expected-user.xml diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java index c8045394c4..d30305ecf2 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java @@ -55,4 +55,22 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { ITable actualTable = databaseDataSet.getTable("CLIENTS"); Assertion.assertEquals(expectedTable, actualTable); } + + + @Test + public void testAssertByQuery() throws Exception { + IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(getClass() + .getClassLoader() + .getResourceAsStream("expected-user.xml")); + ITable expectedTable = expectedDataSet.getTable("CLIENTS"); + Connection conn = getDataSource().getConnection(); + conn.createStatement() + .executeUpdate( + "INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); + ITable actualData = getConnection() + .createQueryTable( + "result_name", + "SELECT * FROM CLIENTS WHERE id='2'"); + Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[]{"id"}); + } } diff --git a/dbunit/src/test/resources/expected-user.xml b/dbunit/src/test/resources/expected-user.xml new file mode 100644 index 0000000000..379db13601 --- /dev/null +++ b/dbunit/src/test/resources/expected-user.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file From 906d72859f67d1d9d9016d6b689805286d4c2675 Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Tue, 31 Mar 2020 17:51:04 +0200 Subject: [PATCH 015/194] [BAEL-2749] Test Code Completion --- .../baeldung/dbunit/DataSourceDBUnitTest.java | 49 ++++++++++++++++++- .../java/com/baeldung/dbunit/DbUnitTest.java | 2 +- .../baeldung/dbunit/OldSchoolDbUnitTest.java | 19 ++++++- dbunit/src/test/resources/data.xml | 2 - .../expected-ignoring-registered_at.xml | 9 ++++ .../resources/expected-multiple-failures.xml | 9 ++++ dbunit/src/test/resources/expected-user.xml | 3 +- dbunit/src/test/resources/items.xml | 1 - .../src/test/resources/items_exp_delete.xml | 1 - .../items_exp_delete_no_produced.xml | 1 - .../src/test/resources/items_exp_rename.xml | 1 - .../items_exp_rename_no_produced.xml | 1 - dbunit/src/test/resources/users.xml | 1 - .../src/test/resources/users_exp_delete.xml | 1 - .../src/test/resources/users_exp_rename.xml | 1 - 15 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 dbunit/src/test/resources/expected-ignoring-registered_at.xml create mode 100644 dbunit/src/test/resources/expected-multiple-failures.xml diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java index d30305ecf2..7482f38535 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java @@ -2,10 +2,15 @@ package com.baeldung.dbunit; import org.dbunit.Assertion; import org.dbunit.DataSourceBasedDBTestCase; +import org.dbunit.assertion.DiffCollectingFailureHandler; +import org.dbunit.assertion.Difference; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ITable; import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.dbunit.operation.DatabaseOperation; import org.h2.jdbcx.JdbcDataSource; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import javax.sql.DataSource; @@ -14,6 +19,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; +import static java.util.stream.Collectors.joining; import static org.assertj.core.api.Assertions.assertThat; public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { @@ -34,6 +40,27 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { .getResourceAsStream("data.xml")); } + @Override + protected DatabaseOperation getSetUpOperation() { + return DatabaseOperation.REFRESH; + } + + @Override + protected DatabaseOperation getTearDownOperation() { + return DatabaseOperation.DELETE_ALL; + } + + @Before + public void setUp() throws Exception { + super.setUp(); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + + @Test public void testSimpleDataSet() throws SQLException { final Connection connection = getDataSource() @@ -56,7 +83,6 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { Assertion.assertEquals(expectedTable, actualTable); } - @Test public void testAssertByQuery() throws Exception { IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(getClass() @@ -70,7 +96,26 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { ITable actualData = getConnection() .createQueryTable( "result_name", - "SELECT * FROM CLIENTS WHERE id='2'"); + "SELECT * FROM CLIENTS WHERE last_name='Jansen'"); Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[]{"id"}); } + + @Test(expected = AssertionError.class) + public void testMultipleFailures() throws Exception { + IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(getClass().getClassLoader().getResourceAsStream("expected-multiple-failures.xml")); + ITable expectedTable = expectedDataSet.getTable("ITEMS"); + Connection conn = getDataSource().getConnection(); + conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); + ITable actualData = getConnection().createDataSet().getTable("ITEMS"); + DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler(); + Assertion.assertEquals(expectedTable, actualData, collectingHandler); + if (!collectingHandler.getDiffList().isEmpty()) { + String message = (String) collectingHandler.getDiffList().stream().map(d -> formatDifference((Difference) d)).collect(joining("\n")); +// throw new AssertionError(message); + } + } + + 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(); + } } diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java index 479ea3dd51..1dee5afb28 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java @@ -42,7 +42,7 @@ public class DbUnitTest extends DBTestCase { @Override protected DatabaseOperation getTearDownOperation() { - return DatabaseOperation.NONE; + return DatabaseOperation.DELETE_ALL; } @Test diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java index 0b63184951..3b46feb304 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java @@ -1,5 +1,6 @@ package com.baeldung.dbunit; +import org.dbunit.Assertion; import org.dbunit.IDatabaseTester; import org.dbunit.JdbcDatabaseTester; import org.dbunit.dataset.IDataSet; @@ -36,7 +37,7 @@ public class OldSchoolDbUnitTest { final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); tester.setDataSet(initDataSet()); tester.setSetUpOperation(DatabaseOperation.REFRESH); - tester.setTearDownOperation(DatabaseOperation.NONE); + tester.setTearDownOperation(DatabaseOperation.DELETE_ALL); return tester; } @@ -65,6 +66,22 @@ public class OldSchoolDbUnitTest { assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); } + @Test + public void testIgnoringProduced() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + final String[] excludedColumns = {"id", "produced"}; + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(getClass().getClassLoader() + .getResourceAsStream("expected-ignoring-registered_at.xml")); + final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns); + + 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); + + Assertion.assertEquals(expectedTable, actualTable); + } + @Test public void testDelete() throws Exception { final Connection connection = tester.getConnection().getConnection(); diff --git a/dbunit/src/test/resources/data.xml b/dbunit/src/test/resources/data.xml index 4230073fc6..290cc36890 100644 --- a/dbunit/src/test/resources/data.xml +++ b/dbunit/src/test/resources/data.xml @@ -1,8 +1,6 @@ - - diff --git a/dbunit/src/test/resources/expected-ignoring-registered_at.xml b/dbunit/src/test/resources/expected-ignoring-registered_at.xml new file mode 100644 index 0000000000..ea57b6a961 --- /dev/null +++ b/dbunit/src/test/resources/expected-ignoring-registered_at.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dbunit/src/test/resources/expected-multiple-failures.xml b/dbunit/src/test/resources/expected-multiple-failures.xml new file mode 100644 index 0000000000..ea57b6a961 --- /dev/null +++ b/dbunit/src/test/resources/expected-multiple-failures.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dbunit/src/test/resources/expected-user.xml b/dbunit/src/test/resources/expected-user.xml index 379db13601..631dd84210 100644 --- a/dbunit/src/test/resources/expected-user.xml +++ b/dbunit/src/test/resources/expected-user.xml @@ -1,5 +1,4 @@ - - + \ No newline at end of file diff --git a/dbunit/src/test/resources/items.xml b/dbunit/src/test/resources/items.xml index 04a975d7ee..d13e93bbe0 100644 --- a/dbunit/src/test/resources/items.xml +++ b/dbunit/src/test/resources/items.xml @@ -1,5 +1,4 @@ - diff --git a/dbunit/src/test/resources/items_exp_delete.xml b/dbunit/src/test/resources/items_exp_delete.xml index 09b78da493..a6fa2b33e8 100644 --- a/dbunit/src/test/resources/items_exp_delete.xml +++ b/dbunit/src/test/resources/items_exp_delete.xml @@ -1,5 +1,4 @@ - diff --git a/dbunit/src/test/resources/items_exp_delete_no_produced.xml b/dbunit/src/test/resources/items_exp_delete_no_produced.xml index dd76e8c6ce..3e7f854f5f 100644 --- a/dbunit/src/test/resources/items_exp_delete_no_produced.xml +++ b/dbunit/src/test/resources/items_exp_delete_no_produced.xml @@ -1,5 +1,4 @@ - diff --git a/dbunit/src/test/resources/items_exp_rename.xml b/dbunit/src/test/resources/items_exp_rename.xml index 830d83499f..32f1d57cf6 100644 --- a/dbunit/src/test/resources/items_exp_rename.xml +++ b/dbunit/src/test/resources/items_exp_rename.xml @@ -1,5 +1,4 @@ - diff --git a/dbunit/src/test/resources/items_exp_rename_no_produced.xml b/dbunit/src/test/resources/items_exp_rename_no_produced.xml index 991c4726a0..b42d3804fa 100644 --- a/dbunit/src/test/resources/items_exp_rename_no_produced.xml +++ b/dbunit/src/test/resources/items_exp_rename_no_produced.xml @@ -1,5 +1,4 @@ - diff --git a/dbunit/src/test/resources/users.xml b/dbunit/src/test/resources/users.xml index 9c14435362..9ac3909bc5 100644 --- a/dbunit/src/test/resources/users.xml +++ b/dbunit/src/test/resources/users.xml @@ -1,5 +1,4 @@ - diff --git a/dbunit/src/test/resources/users_exp_delete.xml b/dbunit/src/test/resources/users_exp_delete.xml index 3780c00c4c..2fe97ae6f6 100644 --- a/dbunit/src/test/resources/users_exp_delete.xml +++ b/dbunit/src/test/resources/users_exp_delete.xml @@ -1,5 +1,4 @@ - diff --git a/dbunit/src/test/resources/users_exp_rename.xml b/dbunit/src/test/resources/users_exp_rename.xml index a576cc9e80..95682118bb 100644 --- a/dbunit/src/test/resources/users_exp_rename.xml +++ b/dbunit/src/test/resources/users_exp_rename.xml @@ -1,5 +1,4 @@ - From 0b1c5e01a5108350a493a06e07d2779a0b9e3f60 Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Tue, 31 Mar 2020 20:18:11 +0200 Subject: [PATCH 016/194] [BAEL-2749] Improves code and makes a copy in libraries-testing --- dbunit/README.md | 2 - dbunit/docs/db_schema.png | Bin 17099 -> 0 bytes .../baeldung/dbunit/DataSourceDBUnitTest.java | 75 ++++---- .../java/com/baeldung/dbunit/DbUnitTest.java | 33 ++-- .../baeldung/dbunit/OldSchoolDbUnitTest.java | 85 +++++---- .../dbunit/PrepAndExpectedDbUnitTest.java | 23 +-- libraries-testing/pom.xml | 37 ++++ .../baeldung/dbunit/ConnectionSettings.java | 8 + .../baeldung/dbunit/DataSourceDBUnitTest.java | 136 +++++++++++++++ .../java/com/baeldung/dbunit/DbUnitTest.java | 90 ++++++++++ .../baeldung/dbunit/OldSchoolDbUnitTest.java | 161 ++++++++++++++++++ .../dbunit/PrepAndExpectedDbUnitTest.java | 89 ++++++++++ .../src/test/resources/dbunit/data.xml | 9 + .../expected-ignoring-registered_at.xml | 9 + .../dbunit/expected-multiple-failures.xml | 9 + .../test/resources/dbunit/expected-user.xml | 4 + .../src/test/resources/dbunit/items.xml | 8 + .../resources/dbunit/items_exp_delete.xml | 7 + .../dbunit/items_exp_delete_no_produced.xml | 7 + .../resources/dbunit/items_exp_rename.xml | 8 + .../dbunit/items_exp_rename_no_produced.xml | 8 + .../src/test/resources/dbunit/schema.sql | 28 +++ .../src/test/resources/dbunit/users.xml | 6 + .../resources/dbunit/users_exp_delete.xml | 5 + .../resources/dbunit/users_exp_rename.xml | 6 + 25 files changed, 758 insertions(+), 95 deletions(-) delete mode 100644 dbunit/docs/db_schema.png create mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java create mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java create mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java create mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java create mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java create mode 100644 libraries-testing/src/test/resources/dbunit/data.xml create mode 100644 libraries-testing/src/test/resources/dbunit/expected-ignoring-registered_at.xml create mode 100644 libraries-testing/src/test/resources/dbunit/expected-multiple-failures.xml create mode 100644 libraries-testing/src/test/resources/dbunit/expected-user.xml create mode 100644 libraries-testing/src/test/resources/dbunit/items.xml create mode 100644 libraries-testing/src/test/resources/dbunit/items_exp_delete.xml create mode 100644 libraries-testing/src/test/resources/dbunit/items_exp_delete_no_produced.xml create mode 100644 libraries-testing/src/test/resources/dbunit/items_exp_rename.xml create mode 100644 libraries-testing/src/test/resources/dbunit/items_exp_rename_no_produced.xml create mode 100644 libraries-testing/src/test/resources/dbunit/schema.sql create mode 100644 libraries-testing/src/test/resources/dbunit/users.xml create mode 100644 libraries-testing/src/test/resources/dbunit/users_exp_delete.xml create mode 100644 libraries-testing/src/test/resources/dbunit/users_exp_rename.xml diff --git a/dbunit/README.md b/dbunit/README.md index 383bd6fb7e..333cac9439 100644 --- a/dbunit/README.md +++ b/dbunit/README.md @@ -1,6 +1,4 @@ ### Database schema -![db schema](docs/db_schema.png) - ### Relevant Articles: - [Introduction To DBUnit](https://www.baeldung.com/dbunit) diff --git a/dbunit/docs/db_schema.png b/dbunit/docs/db_schema.png deleted file mode 100644 index d9185bacd2c624c8e05aea87bf542cfdfd7f1604..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17099 zcmch91VJ!}GI}RUv>+r(2*N1QqxWuf5_R<6d+(z6 z-!1Yy&%5`2fBT$$UFV!XTv)U2wZ3buZ~d&#JpnIY$Y5iTVIUzPVav%%svsfVi2;60 z(eDB+822AMMnVz~my;BG<)XV4zoAOL7CX9s?c%i38RO6$T#=SwZAPC=hhk8vhx^8Q z*#LRjxRBks5RbaoFYa^Wn-AE&AA=r-3LTBMOb=R@GsRgBsavVYrG>wGOr>)A<@u7s z^fs|#&Wtt9po;d?v-)=(LkBv$2R%Cz>lKM!Z?Tb(M9(jn_pok+y9+`_62*OwKtk$8 zo&_Tz9UxT#?LtWZr<(&I!)U8__hyKYxIU@CNRd7xgOCsIRBmSfPkxJaK+5s27#r~* zG6v{|b|Wo_IW3hMBw6xVuqc&L6v7t0DSG9~u4~{8J^CJ)nh02y2NI}y{pRx+^Gg$FS!w(9&E1EFBz$I6)Zflx43pyBK@pRkNHk|*mL@sdv$r;pt=FadpwQ?=zHNdLYUp` zF=E$=R4ZeDuOJz%!k(2ue$8WNeoEsp^^NH#@Xo(m(OzoI=t5# zzXlZrt-6`k>}PDay%Fq$Rk^rGDj)f3K@vy3E-Dw&-~b*&gh!uFTJcZhM}TWc%fgs1HHhc(^S$SoaX%_2&&^E=uy9?xVmmd3L1=gH@|d3U@_L+}J9#zeZdmZmu-5Pbw4##7NQ+(l99IQMFD~j3~ zbQ^50WpOG3nZE_(Y=$Hm&sz7~mjU`Kjq51&gG^89YIt!*& zd#WI1JErze&qk;QrQdye`bWJ35d(&*au%Wk z>GREqQy__f+kVP0D=Mr)x7kKs63{&`nqOAtAk=@y6kYLS6UuX-|2dD+_DCTp)kbk! zMu%93iQ*MAHv>%bql2bqFd`-Bje>Pc>Tdyr2pL{7ok#oU#wAzC6C4uvtM?uoUD_tD z8Il$6iIs&L+Q$gJ0Yyw+TznB_0F(ic`Q{Of2`GA%yW{d{^;Tj?t#3p`_2ebkcQHxJ zT_Inr9}12`CjHd(3I(Qf_%d2F>n*8mq;hoNY;n#b41%YA9tyL8f6xA<7mAdG;+GX| z08>2E_~5-fd;LV_+Jx9rDmq(0T~~N)%ABq2lanb+jo{gC^ZNGlT0eZ&Ds!A}P z&Z!7d-FXe~awcmkQp;}64$Cxl?*^!7_RHu%(mAkUpCtP)vz0}zRS=PmeGAhJla^!Y zbdm?`!7H(iL7$3>Z&7{EFOmYQYsHjg!btT9pP+}A58-s5x01!rOF;mIu_gV&M3|oP z4zv%-hpCP95y!Qgv*qNISW89c?Bv#rPhvWM)!zc^z;g?&%=Oa?XzLK@Ogqb~ov*bM z3NNKzcKbiLzNjTDv1N!Kc{Z20%|cif-mI_1co}$QUZhS=c zbdFS;ch3BKv~_sr2=ol5$Vs&-#au{%{V438AtYIS=~UMhJcfBwXi`UOD@(~OD|Uts0`5LR5F z@WI`q+3^4-Dv%@4YLZbk@vep@8L_xbaFiaFR9~->;+6fkB*3~x8o4x!udD-b~nU(LH{#@0~J3n-cgI|GUA1He^offg31 z)MK1Tcfbd9^-t4vqIl;;qz4LWJtB!qy6h~Lia--kA2Z{yGHdpS6xltr(NfWf%x~#? zz3zH`t3eNZ@CD_qg~j;Eq$RGrnJy+2{O*5PK|+zV2P|O7VNBdvfr{X=jSau5bF{MN z!6~7z%d6H7d8K2-JUp0bEf!m`==eMhvTW{w7rVs>@71*5SB4$6*goZZ?K^X&5iRP1 zBPvQy0tng+Dp^?!D;=Bbu-T!)KjJWf@v>+->6)1OeDA3Uw;h|4PThJA-<;IzJW$A< zfPPPXG!Dg!q5K^UN}wyjE|6rusxaB!X7JeVx(5=@z}tpVDXUF=$Z|6R1_& z9zt58+uSl_-=svJLwzU%fqfInJ4Q$fet0hnB1|`6(&2el+aRLopRT-tB{GGnBmFWY z5Uq8tEwb{MZ42D5zI62Qnb2dWh{kzG0jrVEUwuy>mB6ka?OT2{Flq04QcNb}lc~vY z)kRMD1g{c{R_!)s%(gg8Lru>F2^^L_Jvtzn1~2du3Pp(Z=Ku13Jad$jw=l5VH*si! zhUpzfJD_GqT2fq6ZsI;nrG<5B(mEk8%Qf)Uf{D*TX4jpxI&xGqeE)uU@nG8iDcCX* z4^QsH?|>q?1-^h_gF(KP?C2euBKXnH8bMVt0VrZiJW8m`XZ=T$UYj_3J6ZV=*qvuJs0Gm~W*xe~S=_I~)B`5j7q|nasUe$W}_1JvL!uet1bvSkAW~|#l zg7x0(CVE=9ceQ=k_MO_j9oXDQ&YSJ!B8&kx(LsmUq>zJT{z|kmuT^U@+b-=R4Dl)T?gZIpq{-GsHt7r}(WGoljovf_K51o8tX4=|s^|4`7@46$FBH)}pl!-^t#OJCm-#^nTeZa-5Vg{^Cn8;_h@&^8KDt)A!a*ZZB+S zL1LUr?C*96rD|h59Jp4UN5=C@lz8U%V;Y~Dk@p7u<$eaX!8Oi|eXTXJY9#p$n;%Le zgD($W?Y``PvDjtVGv?<(>{vEI^{#i>AXGj!u*xKi9+EpAtjQn3666im4jh-hXxxjU zkk+1T({|1qQXuctBxWvAv!3|wrGMe%8WObW*G|VC@&4 z?8!RND4HxeKGOaJ^O~$Psrm3 z3%5pc`J|CWzAf{fgn-YTD%hxl53*!nwK1`>$iYRgDYNl=?XXVw<=1Ou|Ln`*0@(1! zy!2+oyu!eyX)2?<5y7_d^2CckaMVGPu%-+R@62N6rma#}Cz?3T^@aEwj-TbBwhIq2 z1cYexl(JSe#rlvx0+Zd};qUXV&P8m`b{pt0a3pRKW|;j4Rok6TgHSm==pEk!5j=Yqznef{1(Q0DHgUe6)f5sf%)paqr&)!1Fwc*4Ck#kKnoFyL zLtVDOs^=$niu=#+Ip0&%W(C0l0&DdcYQ^_=AH}+ok>!-6gnZwq+gUZ_!;e|bEuyoC z-qO6s`^({R-NVNUP@R$>2j5GHtJxF9&IrVDabqu4RJ#bWR;?g1r--~h z>{QMr9j5@Hi2K-+%{!N&D3{x00dCim?nhFu%xd%)#%XS&Amb+4 z?OX)CMiPciUY!i5^9x~?Nmfb4(C12>?-%1ERIh6dY95P!aoo1*neXopzxHIELGG#+ zBKn0}L8z%<+B2NZnITJtb_n*pDw-gI8^`i!eH$Aa-q<{j4hL0tCag)KZi92UIeK(U z2`6Gq*tUy$bfZU2z~7fSyF+xw=?to6E61?(O2hqhPol)kus%hmN zaa%h(j@87(!{8bHsQDIs_4LhVR%FA?4)1$Aw(>N`3jW^_pt2Pdv~BQ{-sOZ}_aqwq z)<#XBd#7fU|EQ*=RN&^8L5xlDqbj?sZl3wP;+isi33caX#K2p7|s~O(G7? z-vnH-W{Z?Pvhxz{6!N=03fXQT39_G>m=LIzDkR`vt>!275(RxQlC3z7z_7vwLJAZ@ z&ugmz>K95P>G7u5k=8i0il=qR>vrN}Q4h*#Fvtqexnd>>UvMhW`rZMJCI2UQH0ZQ^ z?A0@X#c0VKiEK+whj2eO2R)-tl&CQeV}hAko3aDt3{X`xIZ$iDIP?zDA7M?_tl_zb zDUwV*)QoYnFSa|Oale>2J9_THW0gfp>P0ceCom=KQg&vPmp4k!Kdk8ZZbjxhvzEz^ z#@+U_Am@p&WAdJ(bX4uF%`+4;R&oqBVYjZDp`+cyj`8O*Z+Z5)aZ1{q*e~oCW+nK3 zS#Pz!yPhgaj`Tg0aKw3X1#hG!uXlJz#=;?zC*gZrj^HIAS0Vtrl%(RULm0sPk6}5* zf=`b9Ha^;{JjdN^7AanQ5ECysog6gMhTin*Xx2o(Xm0oFM-@weq5+QxzsI6kie`O7 z@0+#LHTS`r>hO2meh*k3<^*&lboOWWT&s&hDPM4uWi>(y_AZJpQxHC*ZO$2862Amh z53G7c6*05o5;SGXXpMatxJcy5XPOZW!jIRET_}wxZGW|R#2!DRA@O!4gJb%elyL>N z-x#_3Kt*oUx9m0a5?7aW^f3Z|RIiY~A~<@Fw_}w;;ovY&`LW%~qT$KvVaLK}{bQ>P zetuZdxlDY)_AXC&pDHdGM{EqU`l3XeO&R8NKD$M%DtTEEU@X7M5H)^UF&7a^&Y8Db zOdqFF@ul#HBu9Y|3;T-YKkplaY9AjYp_tyEue;-aJvPBUAbO5x3nR@HI;qrwa2LtXPc6oTB&S;9U_mp7mDFL;gVNc2I~a%uf;*W$&HE7e>4UOC}|ii zfpLf;KbO7u*d@DC0bZC8wm!2aUz-4io>N{7dFrTnM~eSEk(08;ME)%(u1|}%(BmB= ztg-ja#dJN!zlgdH04SW-?90n%=YDqvY3%0~ocv_M1XD6~q^DjEg6J|W0j=Oq9HY1T zmxq4q#V=t79ichsqdq=tnQ5D6*L#g^R@-}b+wH2uAGAVImY%Nb9Qf(kNWI)&|1o^k z-ar0M2F@r3;}HCq+^DiYAi%}f43YYSVk#F$OzQeWKoqbQYSP ze!dnYrU|4}&(Nq39su^0YXMU`Ri{gI3K=HvPkkud??L@l?eju^g?!|#F{S#jPsQLr zvuim%A^ym;d(MrQ(mQ-(_!zWPXwQEFHJP)6qjB)%I;9@j6G8?+#Yu@~!H<*kk{fR- zMR6~01c)dAu3#HPqW!1CZ8p@24twC}x&h%6=-fJ)ddK(7seoSqj6?ouWY#EuD|~u( z5=g!cjUP@eUY4(V=n)QQ8!Nd$uXRpVyE+CU@;IB(6H_FubXFQb`)TLnpCT^16OuMh zDTR9?U~#P(6KEo6#_x*Zr*_gq?G&;n@UJLhf{2M7kzEd4?rwz;g-%v`Pz0q)Yo(=K z4AhL#k%y;Q_vhq8V_kLj6}VS*Q$XB{o1FOXz=pM>Gw-3Wy^$QPE4t`7G-1r|wjm-S zQd18xD~<}To7Hn{&bu(p|KYEm4#B?CXwrA=><@xSe;ICSoKn2%(tJXd$l~~uN{wVi z^hEDz0JW^Vas@A+$Ry;OVoWhbv*PwxCIYKiV*Muo$8fEbiR|`NZu}~djYuuDa-`uK z3-&0;xXG;F-_}CoIxR9aPMQZf*2d9sjq^<8Se$w`R6B2pc4vGrQRn%0ihQT0&roe% zcR7&=j#@pj@6|Q{FMd9WnPd2;xU{3)D&DL!TfT#EZVceb7&7W)YI{5OknSg`+7mD8 zJ~n#zY=Sq1O^7fu<49{TrOHQmrwZpRF4m9~+I(`0O@Y!gr=BFfe}s~Tvz#5^>BF0^ zPNp3Y{vxl9ERCoZ`CsRlP$|=_zB}F@h>yVK)Zv$Q+LS$+Ri@k^oU_X111(7R%=M_X zklt)flMp>sk)i4bPz06A6DLy6*EV(m8*dX1g-A@Qn&~!w>(}4O^zRI3e-fI$Oq2ea z!d^2f7lA{?E2%SVyIqW`&he4_b8e&o#CXeC=g7X0*n#v(dI{yP2PUtk#u)I?@V9AB zXIrpfa+M06vXq?W^es@?PeGU-OZXBdA8yN)f42JWR&m9^lvF7ra|P$P)h2V0YrjC1 zXX(bVlV@SbnxRwv9y2+_SJ=3(xH{Ze9@ua;nb$t<+{sJP0rk_>UT7%8N!~nn(9|t*bjofw!YhkPcE4xi49HjQf@-cnHWR(CozXoGwU<~= zVf(ViSQLjvoH1ZlZOuhAxrc(Rs>AI{Okl-6R)XCAt}5FgH7}A*tZmDgtq^dp{bifIn4=x&-vONm|JDZCe&`ouMvOI> zEO_|(9KQJ1lnlGM4vk@|kF!*)nkVC2-&o2x8 zuPPcygj%8F(0(E&Y-lVSFbcyXMw@AK_ZE2vR2vn6g?m%*g#_l7i+ zHj=a59LHDU;^GgdZHiU91uC4gRWGnLvH>g|@X*Pj!1HF#F-4}d55~g6b$WR>8SAqL#OjlsX&} z0EQocs$Y3@oi|NUfTFLVG5ICt}pLtVkxwwhXVWKf9c088HY zDX2R=AY!Jlap%o6#!hW;%cwlwZeV+kImSp>+i=SWM!E>^RkGySeg=b*%%ar6ZBP!Y zOuj>odk*1Gtr(wKqxye9$huw1va?S|S?JR*RdF{@p0jnOo5qzK_t;WOAYHZ88S8i?*4#~cLNp^V#Kbn8l?3?IKDo~qhSB$;^T*9Wq?nz30v zdYE{KCei5HV{4)aI)0Tm`BKpM$?GYFxd)BVHHp!uzUi7(az%)6Ovr1zY(PxK+24Z` z-Jn&rnz0S!&|WTi<{J=hw%Cz+_H1d#;1JiUizWzLdVW zZQ&1uq`O_2GD^`TU?Ra#+U1{N%5u*ZyBOit{b_=v-<<_(z6{#T6+}|x6n!uYCPIR> z`)C<`LnN7@K1KQcx!H*{DOVTL(tE@!BnSic3@|-u5`}FH#(M-k9(Tt-9q&uthGJ$?g}2?<0%H}-VlZmhAW{qIqTCBFR@5jh;`W{Tp6^IRR3@6$=Y zp!}9V2g!&giK2}b5a$2DpQ7JbEO#iYhB%)loS(Lp?kmRxpPi&c1Vl)QX5UNz^FvI? z%uHOdXc1n|&+)pRY@*Dl)5v`bO=!yuO>ArbEwR%byJGgnpeK}|2>QnTK4#Lxy+-Id zGN>9!xjGoEX$(sgcHJ{}w|0GF$p3alKEk`1+@|5(Zp~eDa*Ia4_q!S?8BupK zAJiLh8P)B%2=nQG?&$gx?m~YaZHmh&ukDQ5Qg`)(sy?+V`3W23-s6!`d1y!d(bi!- z4I^ijmJj*4u{^Psi9n?{h{jsmv1p1sk!bruWhM1V_{m8)NJ0?UC6jP)ve2tx9{zod zg$wUq_a;$$x5~|#yT4Bq6R)b%yvMWV7_&pmx^HyT{#%etKa?TJYN46j6W1%tW{v7l z*N`nzWaXlviy{Vx+j(*+-6GCWsa^ONH&rk9||uKd+x+SQBs+Jv!x`L&5nk?}N7CG_E1wjbQD0EBMSIm|Z09ND z0Zb?2^d$UsF@<-ln`zhF+HCC}e>YUm^R&7=-z}4-rEBGinB>YkUuW6oP9|!l!pGHV z=)5Kp5@_J@S>5>I<=Xr2cVLWuz;1|OBhb9!PD_$@a)hoj5Dg+|NjS4$O8jf{5rMNS zN74TG2**!#1x_Ab0@P*=Pyxvqjp{lP$}e0%r<9!>otZ=&Su)!goWA3s{2e7UdhDCY z&do=TGmyhkA?Xqa9%UQn19#+*K?5}ZOudHZp||z_YWOT`-DmPLtG809B8StTBVnuP z>9JjD-;KejRKWg%=vC84;_~Y=MS+>2+s2T+N0g#hDrmn)3<6$MssTC%jZnDs7b zfOrj481k1WpsSpHoz6T7_0M!D#I%@;eoZ5cu`AG&qdw`~qG`;S-K4{ai zCSeV7{NPh9ch(abcWk&WAPOeXklx0 z_FSRtd|EJ(&2R2lGShiBd2iJwVid7ai<3-@wpO}+R9I}tTRkSWPN%7cvpE*po#SS{Q@V6}MtC6LwIH&P% zYW+)fGaa3r#LmK3+y}Gj`OQX*wL2bHHJmd~;SBXXooKgP`o5Y4VE$;X6oTA@rcDjf zvB#{K>$~1U3HRlDwwPEW^QL|-xJ=f3^u zwaF^!4<6~R)rvJOB<!r620E>`aI|rJnF_Dg+o)>a&wL`4KnO3roch+^~yMuT+fh zrKZ+Rl@t~3(N#+Ny%T8x?=a1n zSKW#|E7>-RS1*f)hVcdEjF-wnxJcw@tT~B;(Y)O4t9uQ;m&l(b=2B87UsAjA1fSas z5o#$$eH%_2sug|QKFPMB^&crcD(@7pxWH6@jAR?!Zq^sN2O$5+_56s{#5ostk#`d z1^R*t3phmi4kTB<&35~Sl?07P2C1UmwuqUxM)@KJ|LUy;yR!~h=l_PW|BDTGL!s}} zPv$;SH9*O397dnhm^0T0|E3d4Y|sGSt=|BMVt+Xkz$^dpFwKAL3~&$+|M&yj7-Hl< z-ej#&vM0akg?<1SKv&K5>SJSXok1Fz=e5 zCNkPY6`@!>E2L@VcmG&&FSI2k;LYMdce`1y4pY_L&uVpQrK_g3V!i+d>NA{m&&GzI zH7yd;mudS5Rftl`*j@P>wd}aMAm0v^g<~KIDd6S+!BAmuW1Q`3bE`tiM-|lFG~agm ze}JELcjR={+RBg)g9geG7!&El#%E0P)xk->tV6nk%a-m>=%FlGKHTe>$>G2>>38iS zxLWHLSC&`gN=$-usWy&H+hYiV{uqN8Y)`+dxaV!mm1oR-F0mK`p0AjSfES?7oEIzs zsC9-A<2EY^fpsRH`|1wrM@neoLA0>Bn|uCYT(paArkoQP>g@qm<|5p6(!IvG_Psq9 zNgkw^7m-jo)7FRZ6kak~sFggaDZU1|9~dvKwMQ8P^acK|2pT;b(se$9?|GT0`EEw@ zjin0nOOk&(d8*Bd7A1K}3ysEHb@uKNLq zPR-h@Z9vt4mz3p2#(>k5EPwP4hui56M~~A}r>IGH+8jIjPqEN>J?=kN?5t_Kz`q0L zx{MEif04vJ!?cOnBM(eyr#96%Z3wqH9~#~>J6YX2EAjPfkPVZo0B93V!$-kAXA(g) z*PAYG_XCWptQGH>Y@;Wz8CC!kB70#ml_&w1It75CJBZ{Qlc~c{6Sa7AZ5C9Ynfjh$DFScKj_Qm3Ns9zMPg+hVgkcb`+cj7p zdENnpg$zSqZfJm#hS{jmfOErlB&Ax;wX|oK6uOonG;K0H(=E+2G98EB_dlr(hKT0r z0Sm!_y(Q&;`2EEd<_&=@tVyf>L*9tPf!P!LXD{`|g;-V^tWOqIU95h}DX+@NceR}? zw6*lD9W~|*J+ZLLr9>CVIM@znyI5Y^tNv{3QkgL+B?)no zbaW-RdP7B%)z6!80Wt5hq;}Dr*QW9K@=s{$8cT7;BXcTbWh{g(i^q0%thtmDpAt?V z5%(*@Xv!4-Tssn7t7}{|=%AK)dduHhaWI8e;F=*0>s}E3x}k3Runh(5L3w#mZK&WA zsvj~18jozSs%-?jz82}*(Uo@-OdL#@cFgNI4Ns^M??G^ZV@9zjKem~SRH{YBO zn~4O!DQMAd*CqmnlG2GY=P=tbsQD%Su=OyM4b6fB7FL>7nln;8=XJ!>$<-^2G6^Mg zLoY&vRA^C*#tT9pi~vVXQu*+=iV_TgXwE&F(jc}Vg05GuH(>1C*c_h=2GRl;Fs+>6 z$KB`A!+{+wS{Xl#zwc|qru~&}t_CCE#~v~Oy}3=&{P_oYH~@Uf4W3C|W?}U7q!eKC!ALEZsahr%yz1HC3s{E$6a<S&O8BP!;-*|co0la~~R{eWIAW3M@VX%fZ z>qcl}`YnRyj_ zYeAw=nAmsv|8b`AzcN?Aef*WagoA#}G`EHJ68hOP`yFyDSmv(*crSoWVXLfye>YsY zBCi|Xy+N!Rp*m4@XVFbv_vIye`lo;G*VY9_S1h?l0Z+Ua|D)tDGlbK3r>;->JF)hv zJ1cJoqXcafa}Bo=)aUJ7 zjH^_E`{KgESBhtE4nH*7nL`|)3;(+DDPk}?%Fct~)|xhG0Lf3n=I-`2IwjSMM+V;- zW|%P#Id07Y1-QW@+b}c$5dgU3(@*?=uG^Ku>eVxBG+Fu81|FoNK6gofdX#n^0B|;d z%LNF=t&=j#4RsAe;In*^`w}(onyx<3qQIRWWzjoL!lQIxqPQCg!0)edne` zTr2KTrBZEzhPg$qfanOAKLxyVQkxzLMl6rZhJ$%nI81&SFbaWu&!QWee=FVCN=_)_ zZdjJb#VnnwV7HFgfO-%Dn)1|_IoT&VvFGM8;|ox3qgEn*zKwpB6G~d*s*9;Qz+2^d zVq4qjZxj|UE7sYwd?Rw(t->Vc2&bDm_-;5|&o?gk4%jYMv}(&^!#4%)6aKvTt&za_ z{2Pq~*8E!|fuUl?|D3ulER8!q36Uhsa5HwK4r*BVf0xt#4>axH#w6J)%l>*=EC~bd zrG7FLowpO$mV0A+muCoU)Ifr)yf(RBxY|_efbh)ZX6~_PM7;elyjC^78TM{cr16hj zrY+Ev3e)ejDzC#LsLf=4-%511*WvsAb1i`dcsOwk9jCFBD43QAB`8R>cfVNd%TZNW z(u_`5{eVvrAzYz&oPp{#XZHoP=QkThuJ*gg3yArpVeQ4{lsaqnXrCqYx($+B<5%F1~bhYAeEAnh|6ego`bb*t& z(vIj_7})YnMCKG4>zj}3m*O`JLDZy%v4y}teK-EJWr+Vu-E&|{xj^J0MyKm`g~kfI zjrm2$+Bf5&sr}A#iJ%~WrzCs)d6f+Kl$T60O}yaHs|uBVUSkcA@+1(>=vjzbLqumQpHbtxUhLfFFcL^ zg`ixVf|PZS@c7Zt%lK0j&;kaOj3vLgk$vB1bD=i>EKBNwZ@Dx!So0nnM85Fg^tYfpz*WtA5w5XVa;wy^sN$>BUSI9*(Id)OJ)wu_IKwKl zV2_(1>sZ}6+E! zv0jl&8?;tjVx77~e7@k;!%ALgMhAbxe~*I@7|Zvq80Kmdf3FOD%nPeQ+U;b?feUH3xIqf=6% zlwp*@)}N|!?>K07o;k)}hh@G~U94z#fYp*()C40Gx+L7bA&Nn^nx#o52hUDFsea{L zt|Wn5YPCT9C(GNDyi!V<^tnk_b7LD#u?1?z)7k$98zgtmcWzSh&m*7+7IV_A)Y^Ee zT*I^Icnb(sNkQj_0;PzrCD*P%`gJm<5|1!09mcjyOn~RQMi=#)ndWwrP1FYop}kPD z$*2x8RaLh(DV0Y&0wo}@@{>>LjDPrr#mO>D2QgPXO=SH}uYDsI7!f`;g?ho<{fazvFHe;p~84amD zu3z3MSN*zpHi!-I{?%M84u!Nx%hrgu19OVv6OnT=qPvuYg*8bX6Q<5#4y0mG4JDZm z&AdP6VrT_)mAglKLg2xrBcUkB3s!JqX_b6!)y~@Me#^jeev6%Vck8^#1os(#Su6Qn z{9u(LCJ=}!ThHZT*R_f`Pk9gEYqy95SlOdUGq-&t< zW7m{NkEscc-X4i|ViJW^ZBX6rMjpC3w#VqWh^ChI&Qp_dF(WaU+mh|&?9itR))G!3 zkJp$~d7RFZFD~}!(k#8$>ky;+ojJ3Z?;h3Zy7H+t2|c3ueXjVRRE1_M--J{66;rsG z$rxrFT8qhL<4aqBFRdAY5K@!>vizU9j9H(AZG$u>o(WR?UH#A=a&Yq4>aT(SRt5a5 z&{J2s7y1I?C(-xHldST3t{LT;@!mEwo-yN`=TF`7$LIZm`s78j&TRVb{sMkfQ^ zF+`4GC2Wvjf~I2@{QruHNY9)EYLwCkf31bmE^aUjyJhkIZ$Kfp*Xi>5;DUL6Et|rh z&YCqo(Hzx*H4<8HKKNv<8^Dym<~am~jp!ydbw14+K1R*jDyksbX$+ukfo>i&UB;cl z;USarBJRF!Hmt({S-_!rOt4^#%1m45`i)zRpYik(o2i#v&%cL9Ztmf=(ie4X zYlieW`gkvJ=@Rj6H7|UkZCbQ9rRD7`RyB+xKKd#oBV~c;x50K)1Fkkv{I#E|$0eg< zQJs~XX$x9oEjg&fm~3HtJ53C^Z+#nQUwRPJsNKWKo8)>FyOYzPo5^~E7Wmk61^Zth ztECA2DTh^7i%Wjlk$<+_k~NI9;eG&n{1T7ADtw4?S~~98Az{B<6;{mBGVQu?LVoa& z3K1vs>MJjZaduU+r_-~4^O}(UbB^Zimzy_0%caXL(8B$w@fK+e2g&CPGmMosMICy) zYK>wDu!|{+i$owAwTciRrcb1AW778TFBET)dLs-lES|$zobHuI49j$q`g^d_iEvPM z#tfh6DN6GOuM|6Y%@MJx_JZgr4|_oa!oQ1^C`S(k!#S7tjMAs$6B=ebV-ywYkM=>F z+#KA_N-tmxu`H!yOVbOGD9Qrr^cqBAQ*8QZxLr7N5+^;2;&Ec?W&PBfsDw(3yrz9v z&<7ocd{f3MJ%-WbQQ*C&InNm3n@g5$@V!G0Os%MC^qqOm&n(^0?|DrG4!()-$35i; zBTR!9yO>w{UD1bW>TkNgaKTZJ;Rf+@tm)NE&%EHWgV5Jfhz;qEM)%M$gjc9*xkOP3 z@UofaXF9P#7T+C?vfG-FF+0?(U}JYn_+m}sWOrm}E3pEgU3Egu@=T8`*{)AO6t4B~ zYsC6+zDZ_t$0S<>=o4uxw9|XHDc0xkvBswaeW%2aW?yUf4+F>r?Zc7~(UE(BQ9vYU zj1lx%L5$}8><<5?^yO=QE-zR_`tgb5)~1#;3&}S zP@p5hf1Dw5Dff(5XtL67VZx@KsOPi%83Z+~4oISdf^^h%bf%j6dwXBLe7RdabNQmi zKQMCvd`0JAyF5=6^$l@$^N#rd-hFtd5jZ)Zp#G{VJDZ7(P3flJGI*O#KKujl^0_Q8 z%$Bstx!#_QTcPVRn%mX(#2zCI1Fj)ul@7w=3` zKtbIZMwjGg!Nt3AT`jCqI2|1w;vYr#mxjf{#nG%REhW!ouqF6m$qo`veAOk&FLUb8 zn7IhH;F+19^w7F`y1ImBq&@G+!REHW?ImydC{~Sn6|T6DkY0Mr-`ura?*70vCDTOa z4!b%lxE?p!>O3-|n`ZAJVq{v?S zDcy_Sy@3wO2WAhR~VEP8^(Kghuf#}(c^Wb z6kYOl?c~F-sY(QS*BsB>VDIE)r{dShNS&bCp2u(;6)ba;y;kupYJS+B6(||nD-7=n zQ&E2MRWDJ-{@w+h-VX?aYq=@ocwtQq1@~BQ!94&gNFr;mRLIw9DQoIItG~Y7QMSOm zA5wqSR}U#r{m=^y-*{>XOOB8Xk`0$^5i@yP*GL-9JWF*-whSECl9)$lN(ybe>OCZC zO8SLji%lUG$7K6sg!ObyyUt>!>e%4mD{bwd^!kfm@{588bQQuXsOH&=%ga|G&6Ygc zdBYY(pa^ZWt=>6Xh)X@zp*j2|if55bF?^O;*3&2qLEi&_Y24di2>QlS zrkTy90&fqbA1bT8I=|8>HNYi8#qU@Bz+cpZcQAOK#N%*CBa>jf!6(*!lF}KVjSh=3 zQw!;w2r;Y=Bu9wlBxC!<3p!@Ey>H|888U3p_;S&9QtNeL*=N_cmV88Z) formatDifference((Difference) d)).collect(joining("\n")); -// throw new AssertionError(message); + try (final InputStream is = getClass() + .getClassLoader() + .getResourceAsStream("expected-multiple-failures.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = expectedDataSet.getTable("ITEMS"); + final Connection conn = getDataSource().getConnection(); + final DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler(); + + conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); + final ITable actualData = getConnection().createDataSet().getTable("ITEMS"); + + Assertion.assertEquals(expectedTable, actualData, collectingHandler); + if (!collectingHandler.getDiffList().isEmpty()) { + String message = (String) collectingHandler.getDiffList().stream().map(d -> formatDifference((Difference) d)).collect(joining("\n")); + logger.error(() -> message); + } } } diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java index 1dee5afb28..d24410bedf 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java @@ -31,8 +31,9 @@ public class DbUnitTest extends DBTestCase { @Override protected IDataSet getDataSet() throws Exception { - final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("data.xml"); - return new FlatXmlDataSetBuilder().build(is); + try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("data.xml")) { + return new FlatXmlDataSetBuilder().build(is); + } } @Override @@ -52,37 +53,39 @@ public class DbUnitTest extends DBTestCase { final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); assertThat(rs.next()).isTrue(); - assertThat(rs.getString( "title")).isEqualTo("Grey T-Shirt"); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); } @Test public void testDelete() throws Exception { final Connection connection = getConnection().getConnection(); - final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml"); - ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); + try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml")) { + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - final IDataSet databaseDataSet = getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); - Assertion.assertEquals(expectedTable, actualTable); + Assertion.assertEquals(expectedTable, actualTable); + } } @Test public void testUpdate() throws Exception { final Connection connection = getConnection().getConnection(); - final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml"); - ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); + try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml")) { + 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(); - ITable actualTable = databaseDataSet.getTable("items"); + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); - Assertion.assertEquals(expectedTable, actualTable); + Assertion.assertEquals(expectedTable, actualTable); + } } } diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java index 3b46feb304..41d7ffd8d4 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java @@ -42,8 +42,9 @@ public class OldSchoolDbUnitTest { } private static IDataSet initDataSet() throws Exception { - final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml"); - return new FlatXmlDataSetBuilder().build(is); + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml")) { + return new FlatXmlDataSetBuilder().build(is); + } } @Before @@ -70,78 +71,92 @@ public class OldSchoolDbUnitTest { public void testIgnoringProduced() throws Exception { final Connection connection = tester.getConnection().getConnection(); final String[] excludedColumns = {"id", "produced"}; - final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(getClass().getClassLoader() - .getResourceAsStream("expected-ignoring-registered_at.xml")); - final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns); + try (final InputStream is = getClass().getClassLoader() + .getResourceAsStream("expected-ignoring-registered_at.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns); - connection.createStatement().executeUpdate("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); + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + final ITable actualTable = DefaultColumnFilter.excludedColumnsTable(databaseDataSet.getTable("ITEMS"), excludedColumns); - Assertion.assertEquals(expectedTable, actualTable); + Assertion.assertEquals(expectedTable, actualTable); + } } @Test public void testDelete() throws Exception { final Connection connection = tester.getConnection().getConnection(); - final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml"); - ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + try (final InputStream is = + OldSchoolDbUnitTest.class.getClassLoader() + .getResourceAsStream("items_exp_delete.xml");) { + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); - assertEquals(expectedTable, actualTable); + assertEquals(expectedTable, actualTable); + } } @Test public void testDeleteWithExcludedColumns() throws Exception { final Connection connection = tester.getConnection().getConnection(); - final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete_no_produced.xml"); - ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + try (final InputStream is = + OldSchoolDbUnitTest.class.getClassLoader() + .getResourceAsStream("items_exp_delete_no_produced.xml")) { + final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); - assertEquals(expectedTable, actualTable); + assertEquals(expectedTable, actualTable); + } } @Test public void testUpdate() throws Exception { final Connection connection = tester.getConnection().getConnection(); - final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml"); - final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + try (final InputStream is = + OldSchoolDbUnitTest.class.getClassLoader() + .getResourceAsStream("items_exp_rename.xml")) { + final 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 = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); - assertEquals(expectedTable, actualTable); + assertEquals(expectedTable, actualTable); + } } @Test public void testUpdateWithExcludedColumns() throws Exception { final Connection connection = tester.getConnection().getConnection(); - final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename_no_produced.xml"); - ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + try (final InputStream is = + OldSchoolDbUnitTest.class.getClassLoader() + .getResourceAsStream("items_exp_rename_no_produced.xml")) { + 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 = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); - assertEquals(expectedTable, actualTable); + assertEquals(expectedTable, actualTable); + } } } diff --git a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java index 2c7e5de508..b4e23f56ff 100644 --- a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java +++ b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java @@ -39,8 +39,9 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { } private IDataSet initDataSet() throws Exception { - final InputStream is = getClass().getClassLoader().getResourceAsStream("data.xml"); - return new FlatXmlDataSetBuilder().build(is); + try (final InputStream is = getClass().getClassLoader().getResourceAsStream("data.xml")) { + return new FlatXmlDataSetBuilder().build(is); + } } private DataFileLoader initDataFileLoader() { @@ -53,10 +54,8 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; final String[] prepDataFiles = {"/users.xml"}; final String[] expectedDataFiles = {"/users.xml"}; - final PrepAndExpectedTestCaseSteps testSteps = - () -> connection - .createStatement() - .executeQuery("select * from CLIENTS where id = 1"); + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() + .executeQuery("select * from CLIENTS where id = 1"); final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); @@ -70,10 +69,8 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; // define tables to verify final String[] prepDataFiles = {"/users.xml"}; final String[] expectedDataFiles = {"/users_exp_rename.xml"}; - final PrepAndExpectedTestCaseSteps testSteps = - () -> connection - .createStatement() - .executeUpdate("update CLIENTS set first_name = 'new name' where id = 1"); + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() + .executeUpdate("update CLIENTS set first_name = 'new name' where id = 1"); super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); } @@ -84,10 +81,8 @@ public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; final String[] prepDataFiles = {"/users.xml"}; final String[] expectedDataFiles = {"/users_exp_delete.xml"}; - final PrepAndExpectedTestCaseSteps testSteps = - () -> connection - .createStatement() - .executeUpdate("delete from CLIENTS where id = 2"); + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() + .executeUpdate("delete from CLIENTS where id = 2"); super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); } diff --git a/libraries-testing/pom.xml b/libraries-testing/pom.xml index 3ffbb291a0..c4d2786441 100644 --- a/libraries-testing/pom.xml +++ b/libraries-testing/pom.xml @@ -130,6 +130,27 @@ ${asciidoctor.version} + + org.dbunit + dbunit + ${dbunit.version} + test + + + + com.h2database + h2 + ${h2.version} + test + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + @@ -150,6 +171,16 @@ + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven-compiler-plugin.source} + ${maven-compiler-plugin.target} + + + @@ -166,6 +197,12 @@ 4.1.1 3.6.2 2.0.0.0 + 1.4.200 + 2.6.0 + 3.14.0 + 1.8 + 1.8 + 3.8.1 diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java b/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java new file mode 100644 index 0000000000..cc29d9c58a --- /dev/null +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java @@ -0,0 +1,8 @@ +package com.baeldung.dbunit; + +public class ConnectionSettings { + public static final String JDBC_DRIVER = org.h2.Driver.class.getName(); + public static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:dbunit/schema.sql'"; + public static final String USER = "sa"; + public static final String PASSWORD = ""; +} diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java new file mode 100644 index 0000000000..662ed44fb6 --- /dev/null +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java @@ -0,0 +1,136 @@ +package com.baeldung.dbunit; + +import org.dbunit.Assertion; +import org.dbunit.DataSourceBasedDBTestCase; +import org.dbunit.assertion.DiffCollectingFailureHandler; +import org.dbunit.assertion.Difference; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.dbunit.operation.DatabaseOperation; +import org.h2.jdbcx.JdbcDataSource; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.platform.commons.logging.Logger; +import org.junit.platform.commons.logging.LoggerFactory; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; + +import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; +import static java.util.stream.Collectors.joining; +import static org.assertj.core.api.Assertions.assertThat; + +public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { + + private static Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class); + + @Override + protected javax.sql.DataSource getDataSource() { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setURL(JDBC_URL); + dataSource.setUser("sa"); + dataSource.setPassword(""); + return dataSource; + } + + @Override + protected IDataSet getDataSet() throws Exception { + try (java.io.InputStream resourceAsStream = getClass() + .getClassLoader() + .getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(resourceAsStream); + } + } + + @Override + protected DatabaseOperation getSetUpOperation() { + return DatabaseOperation.REFRESH; + } + + @Override + protected DatabaseOperation getTearDownOperation() { + return DatabaseOperation.DELETE_ALL; + } + + @Before + public void setUp() throws Exception { + super.setUp(); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + + + @Test + public void testSimpleDataSet() throws SQLException { + final Connection connection = getDataSource() + .getConnection(); + + final ResultSet rs = connection + .createStatement() + .executeQuery("select * from iTEMS where id = 1"); + + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + } + + @Test + public void testEmptySchema() throws Exception { + final IDataSet expectedDataSet = getDataSet(); + final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); + final IDataSet databaseDataSet = getConnection().createDataSet(); + final ITable actualTable = databaseDataSet.getTable("CLIENTS"); + Assertion.assertEquals(expectedTable, actualTable); + } + + @Test + public void testAssertByQuery() throws Exception { + try (final java.io.InputStream is = getClass() + .getClassLoader() + .getResourceAsStream("dbunit/expected-user.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); + final Connection conn = getDataSource().getConnection(); + + conn.createStatement() + .executeUpdate( + "INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); + final ITable actualData = getConnection() + .createQueryTable( + "result_name", + "SELECT * FROM CLIENTS WHERE last_name='Jansen'"); + + Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[]{"id"}); + } + } + + @Test + public void testMultipleFailures() throws Exception { + try (final java.io.InputStream is = getClass() + .getClassLoader() + .getResourceAsStream("dbunit/expected-multiple-failures.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = expectedDataSet.getTable("ITEMS"); + final Connection conn = getDataSource().getConnection(); + final DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler(); + + conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); + final ITable actualData = getConnection().createDataSet().getTable("ITEMS"); + + Assertion.assertEquals(expectedTable, actualData, collectingHandler); + if (!collectingHandler.getDiffList().isEmpty()) { + String message = (String) collectingHandler.getDiffList().stream().map(d -> formatDifference((Difference) d)).collect(joining("\n")); + logger.error(() -> message); + } + } + } + + 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(); + } +} diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java new file mode 100644 index 0000000000..3ed77b2c25 --- /dev/null +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java @@ -0,0 +1,90 @@ +package com.baeldung.dbunit; + +import org.dbunit.Assertion; +import org.dbunit.DBTestCase; +import org.dbunit.PropertiesBasedJdbcDatabaseTester; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.dbunit.operation.DatabaseOperation; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; + +import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; +import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; +import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; +import static com.baeldung.dbunit.ConnectionSettings.USER; +import static org.assertj.core.api.Assertions.assertThat; + +public class DbUnitTest extends DBTestCase { + + public DbUnitTest(String name) { + super(name); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD); + } + + @Override + protected IDataSet getDataSet() throws Exception { + try (final java.io.InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(is); + } + } + + @Override + protected DatabaseOperation getSetUpOperation() { + return DatabaseOperation.REFRESH; + } + + @Override + protected DatabaseOperation getTearDownOperation() { + return DatabaseOperation.DELETE_ALL; + } + + @Test + public void testSelect() throws Exception { + final Connection connection = getConnection().getConnection(); + + final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); + + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + } + + @Test + public void testDelete() throws Exception { + final Connection connection = getConnection().getConnection(); + + try (final java.io.InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + + Assertion.assertEquals(expectedTable, actualTable); + } + } + + @Test + public void testUpdate() throws Exception { + final Connection connection = getConnection().getConnection(); + + try (final java.io.InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); + + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + + Assertion.assertEquals(expectedTable, actualTable); + } + } + +} diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java new file mode 100644 index 0000000000..aa6d9143bb --- /dev/null +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java @@ -0,0 +1,161 @@ +package com.baeldung.dbunit; + +import org.dbunit.Assertion; +import org.dbunit.IDatabaseTester; +import org.dbunit.JdbcDatabaseTester; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.filter.DefaultColumnFilter; +import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.dbunit.operation.DatabaseOperation; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; + +import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; +import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; +import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; +import static com.baeldung.dbunit.ConnectionSettings.USER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.dbunit.Assertion.assertEquals; + +public class OldSchoolDbUnitTest { + + private static IDatabaseTester tester = null; + + @BeforeClass + public static void setUp() throws Exception { + tester = initDatabaseTester(); + } + + private static IDatabaseTester initDatabaseTester() throws Exception { + final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); + tester.setDataSet(initDataSet()); + tester.setSetUpOperation(DatabaseOperation.REFRESH); + tester.setTearDownOperation(DatabaseOperation.DELETE_ALL); + return tester; + } + + private static IDataSet initDataSet() throws Exception { + try (final java.io.InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(is); + } + } + + @Before + public void setup() throws Exception { + tester.onSetup(); + } + + @After + public void tearDown() throws Exception { + tester.onTearDown(); + } + + @Test + public void testSelect() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); + + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + } + + @Test + public void testIgnoringProduced() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + final String[] excludedColumns = {"id", "produced"}; + try (final java.io.InputStream is = getClass().getClassLoader() + .getResourceAsStream("dbunit/expected-ignoring-registered_at.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns); + + 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); + + Assertion.assertEquals(expectedTable, actualTable); + } + } + + @Test + public void testDelete() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final java.io.InputStream is = + OldSchoolDbUnitTest.class.getClassLoader() + .getResourceAsStream("dbunit/items_exp_delete.xml");) { + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + + assertEquals(expectedTable, actualTable); + } + } + + @Test + public void testDeleteWithExcludedColumns() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final java.io.InputStream is = + OldSchoolDbUnitTest.class.getClassLoader() + .getResourceAsStream("dbunit/items_exp_delete_no_produced.xml")) { + final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); + + assertEquals(expectedTable, actualTable); + } + } + + @Test + public void testUpdate() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final java.io.InputStream is = + OldSchoolDbUnitTest.class.getClassLoader() + .getResourceAsStream("dbunit/items_exp_rename.xml")) { + final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + + assertEquals(expectedTable, actualTable); + } + } + + @Test + public void testUpdateWithExcludedColumns() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final java.io.InputStream is = + OldSchoolDbUnitTest.class.getClassLoader() + .getResourceAsStream("dbunit/items_exp_rename_no_produced.xml")) { + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("items"); + actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); + + assertEquals(expectedTable, actualTable); + } + } + +} diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java new file mode 100644 index 0000000000..7e77cd8fc3 --- /dev/null +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java @@ -0,0 +1,89 @@ +package com.baeldung.dbunit; + +import org.dbunit.DefaultPrepAndExpectedTestCase; +import org.dbunit.IDatabaseTester; +import org.dbunit.JdbcDatabaseTester; +import org.dbunit.PrepAndExpectedTestCaseSteps; +import org.dbunit.VerifyTableDefinition; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; +import org.dbunit.operation.DatabaseOperation; +import org.dbunit.util.fileloader.DataFileLoader; +import org.dbunit.util.fileloader.FlatXmlDataFileLoader; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.ResultSet; + +import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; +import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; +import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; +import static com.baeldung.dbunit.ConnectionSettings.USER; +import static org.assertj.core.api.Assertions.assertThat; + +public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { + + @Override + public void setUp() throws Exception { + setDatabaseTester(initDatabaseTester()); + setDataFileLoader(initDataFileLoader()); + super.setUp(); + } + + private IDatabaseTester initDatabaseTester() throws Exception { + final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); + tester.setDataSet(initDataSet()); + tester.setSetUpOperation(DatabaseOperation.REFRESH); + return tester; + } + + private IDataSet initDataSet() throws Exception { + try (final java.io.InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(is); + } + } + + private DataFileLoader initDataFileLoader() { + return new FlatXmlDataFileLoader(); + } + + @Test + public void testSelect() throws Exception { + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; + final String[] prepDataFiles = {"/dbunit/users.xml"}; + final String[] expectedDataFiles = {"/dbunit/users.xml"}; + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() + .executeQuery("select * from CLIENTS where id = 1"); + + final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("last_name")).isEqualTo("Xavier"); + } + + @Test + public void testUpdate() throws Exception { + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; // define tables to verify + final String[] prepDataFiles = {"/dbunit/users.xml"}; + final String[] expectedDataFiles = {"/dbunit/users_exp_rename.xml"}; + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() + .executeUpdate("update CLIENTS set first_name = 'new name' where id = 1"); + + super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + } + + @Test + public void testDelete() throws Exception { + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; + final String[] prepDataFiles = {"/dbunit/users.xml"}; + final String[] expectedDataFiles = {"/dbunit/users_exp_delete.xml"}; + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() + .executeUpdate("delete from CLIENTS where id = 2"); + + super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + } + +} diff --git a/libraries-testing/src/test/resources/dbunit/data.xml b/libraries-testing/src/test/resources/dbunit/data.xml new file mode 100644 index 0000000000..290cc36890 --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/data.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/libraries-testing/src/test/resources/dbunit/expected-ignoring-registered_at.xml b/libraries-testing/src/test/resources/dbunit/expected-ignoring-registered_at.xml new file mode 100644 index 0000000000..ea57b6a961 --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/expected-ignoring-registered_at.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/libraries-testing/src/test/resources/dbunit/expected-multiple-failures.xml b/libraries-testing/src/test/resources/dbunit/expected-multiple-failures.xml new file mode 100644 index 0000000000..ea57b6a961 --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/expected-multiple-failures.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/libraries-testing/src/test/resources/dbunit/expected-user.xml b/libraries-testing/src/test/resources/dbunit/expected-user.xml new file mode 100644 index 0000000000..631dd84210 --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/expected-user.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/libraries-testing/src/test/resources/dbunit/items.xml b/libraries-testing/src/test/resources/dbunit/items.xml new file mode 100644 index 0000000000..d13e93bbe0 --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/items.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/libraries-testing/src/test/resources/dbunit/items_exp_delete.xml b/libraries-testing/src/test/resources/dbunit/items_exp_delete.xml new file mode 100644 index 0000000000..a6fa2b33e8 --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/items_exp_delete.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/libraries-testing/src/test/resources/dbunit/items_exp_delete_no_produced.xml b/libraries-testing/src/test/resources/dbunit/items_exp_delete_no_produced.xml new file mode 100644 index 0000000000..3e7f854f5f --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/items_exp_delete_no_produced.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/libraries-testing/src/test/resources/dbunit/items_exp_rename.xml b/libraries-testing/src/test/resources/dbunit/items_exp_rename.xml new file mode 100644 index 0000000000..32f1d57cf6 --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/items_exp_rename.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/libraries-testing/src/test/resources/dbunit/items_exp_rename_no_produced.xml b/libraries-testing/src/test/resources/dbunit/items_exp_rename_no_produced.xml new file mode 100644 index 0000000000..b42d3804fa --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/items_exp_rename_no_produced.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/libraries-testing/src/test/resources/dbunit/schema.sql b/libraries-testing/src/test/resources/dbunit/schema.sql new file mode 100644 index 0000000000..c2a8d2d630 --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/schema.sql @@ -0,0 +1,28 @@ +CREATE TABLE IF NOT EXISTS CLIENTS +( + `id` int AUTO_INCREMENT NOT NULL, + `first_name` varchar(100) NOT NULL, + `last_name` varchar(100) NOT NULL, + PRIMARY KEY (`id`) +); + +CREATE TABLE IF NOT EXISTS ITEMS +( + `id` int AUTO_INCREMENT NOT NULL, + `title` varchar(100) NOT NULL, + `produced` date, + `price` float, + PRIMARY KEY (`id`) +); + +CREATE TABLE IF NOT EXISTS PURCHASES +( + `id` int NOT NULL AUTO_INCREMENT, + `id_user` int NOT NULL, + `id_item` int NOT NULL, + `total_price` float NOT NULL, + `quantity` int(11) NOT NULL, + PRIMARY KEY (`id`), + FOREIGN KEY (`id_user`) REFERENCES CLIENTS (`id`) ON DELETE CASCADE, + FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE +); diff --git a/libraries-testing/src/test/resources/dbunit/users.xml b/libraries-testing/src/test/resources/dbunit/users.xml new file mode 100644 index 0000000000..9ac3909bc5 --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/users.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/libraries-testing/src/test/resources/dbunit/users_exp_delete.xml b/libraries-testing/src/test/resources/dbunit/users_exp_delete.xml new file mode 100644 index 0000000000..2fe97ae6f6 --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/users_exp_delete.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/libraries-testing/src/test/resources/dbunit/users_exp_rename.xml b/libraries-testing/src/test/resources/dbunit/users_exp_rename.xml new file mode 100644 index 0000000000..95682118bb --- /dev/null +++ b/libraries-testing/src/test/resources/dbunit/users_exp_rename.xml @@ -0,0 +1,6 @@ + + + + + + From ee185d85b57e3b5036cec9aa3d5b13c08dc94ada Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Tue, 31 Mar 2020 20:19:11 +0200 Subject: [PATCH 017/194] [BAEL-2749] Removes dbunit module --- dbunit/README.md | 4 - dbunit/pom.xml | 62 ------- .../main/java/com/baeldung/dbunit/.gitkeep | 0 dbunit/src/main/resources/logback.xml | 13 -- .../baeldung/dbunit/ConnectionSettings.java | 8 - .../baeldung/dbunit/DataSourceDBUnitTest.java | 138 --------------- .../java/com/baeldung/dbunit/DbUnitTest.java | 91 ---------- .../baeldung/dbunit/OldSchoolDbUnitTest.java | 162 ------------------ .../dbunit/PrepAndExpectedDbUnitTest.java | 90 ---------- dbunit/src/test/resources/data.xml | 9 - .../expected-ignoring-registered_at.xml | 9 - .../resources/expected-multiple-failures.xml | 9 - dbunit/src/test/resources/expected-user.xml | 4 - dbunit/src/test/resources/items.xml | 8 - .../src/test/resources/items_exp_delete.xml | 7 - .../items_exp_delete_no_produced.xml | 7 - .../src/test/resources/items_exp_rename.xml | 8 - .../items_exp_rename_no_produced.xml | 8 - dbunit/src/test/resources/schema.sql | 28 --- dbunit/src/test/resources/users.xml | 6 - .../src/test/resources/users_exp_delete.xml | 5 - .../src/test/resources/users_exp_rename.xml | 6 - 22 files changed, 682 deletions(-) delete mode 100644 dbunit/README.md delete mode 100644 dbunit/pom.xml delete mode 100644 dbunit/src/main/java/com/baeldung/dbunit/.gitkeep delete mode 100644 dbunit/src/main/resources/logback.xml delete mode 100644 dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java delete mode 100644 dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java delete mode 100644 dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java delete mode 100644 dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java delete mode 100644 dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java delete mode 100644 dbunit/src/test/resources/data.xml delete mode 100644 dbunit/src/test/resources/expected-ignoring-registered_at.xml delete mode 100644 dbunit/src/test/resources/expected-multiple-failures.xml delete mode 100644 dbunit/src/test/resources/expected-user.xml delete mode 100644 dbunit/src/test/resources/items.xml delete mode 100644 dbunit/src/test/resources/items_exp_delete.xml delete mode 100644 dbunit/src/test/resources/items_exp_delete_no_produced.xml delete mode 100644 dbunit/src/test/resources/items_exp_rename.xml delete mode 100644 dbunit/src/test/resources/items_exp_rename_no_produced.xml delete mode 100644 dbunit/src/test/resources/schema.sql delete mode 100644 dbunit/src/test/resources/users.xml delete mode 100644 dbunit/src/test/resources/users_exp_delete.xml delete mode 100644 dbunit/src/test/resources/users_exp_rename.xml diff --git a/dbunit/README.md b/dbunit/README.md deleted file mode 100644 index 333cac9439..0000000000 --- a/dbunit/README.md +++ /dev/null @@ -1,4 +0,0 @@ -### Database schema - -### Relevant Articles: -- [Introduction To DBUnit](https://www.baeldung.com/dbunit) diff --git a/dbunit/pom.xml b/dbunit/pom.xml deleted file mode 100644 index 7ca53cd3be..0000000000 --- a/dbunit/pom.xml +++ /dev/null @@ -1,62 +0,0 @@ - - 4.0.0 - dbunit - 1.0 - - 1.4.200 - - 1.8 - 1.8 - 3.8.1 - - 3.14.0 - 2.6.0 - - - dbunit - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - org.dbunit - dbunit - ${dbunit.version} - test - - - - com.h2database - h2 - ${h2.version} - test - - - - org.assertj - assertj-core - ${assertj-core.version} - test - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${maven-compiler-plugin.source} - ${maven-compiler-plugin.target} - - - - - - diff --git a/dbunit/src/main/java/com/baeldung/dbunit/.gitkeep b/dbunit/src/main/java/com/baeldung/dbunit/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/dbunit/src/main/resources/logback.xml b/dbunit/src/main/resources/logback.xml deleted file mode 100644 index 26beb6d5b4..0000000000 --- a/dbunit/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java b/dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java deleted file mode 100644 index e842022292..0000000000 --- a/dbunit/src/test/java/com/baeldung/dbunit/ConnectionSettings.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.dbunit; - -public class ConnectionSettings { - public static final String JDBC_DRIVER = org.h2.Driver.class.getName(); - public static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:schema.sql'"; - public static final String USER = "sa"; - public static final String PASSWORD = ""; -} diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java deleted file mode 100644 index 606f1a90a3..0000000000 --- a/dbunit/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.baeldung.dbunit; - -import org.dbunit.Assertion; -import org.dbunit.DataSourceBasedDBTestCase; -import org.dbunit.assertion.DiffCollectingFailureHandler; -import org.dbunit.assertion.Difference; -import org.dbunit.dataset.IDataSet; -import org.dbunit.dataset.ITable; -import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; -import org.dbunit.operation.DatabaseOperation; -import org.h2.jdbcx.JdbcDataSource; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.platform.commons.logging.Logger; -import org.junit.platform.commons.logging.LoggerFactory; - -import javax.sql.DataSource; -import java.io.InputStream; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; - -import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; -import static java.util.stream.Collectors.joining; -import static org.assertj.core.api.Assertions.assertThat; - -public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { - - private static Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class); - - @Override - protected DataSource getDataSource() { - JdbcDataSource dataSource = new JdbcDataSource(); - dataSource.setURL(JDBC_URL); - dataSource.setUser("sa"); - dataSource.setPassword(""); - return dataSource; - } - - @Override - protected IDataSet getDataSet() throws Exception { - try (InputStream resourceAsStream = getClass() - .getClassLoader() - .getResourceAsStream("data.xml")) { - return new FlatXmlDataSetBuilder().build(resourceAsStream); - } - } - - @Override - protected DatabaseOperation getSetUpOperation() { - return DatabaseOperation.REFRESH; - } - - @Override - protected DatabaseOperation getTearDownOperation() { - return DatabaseOperation.DELETE_ALL; - } - - @Before - public void setUp() throws Exception { - super.setUp(); - } - - @After - public void tearDown() throws Exception { - super.tearDown(); - } - - - @Test - public void testSimpleDataSet() throws SQLException { - final Connection connection = getDataSource() - .getConnection(); - - final ResultSet rs = connection - .createStatement() - .executeQuery("select * from iTEMS where id = 1"); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); - } - - @Test - public void testEmptySchema() throws Exception { - final IDataSet expectedDataSet = getDataSet(); - final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); - final IDataSet databaseDataSet = getConnection().createDataSet(); - final ITable actualTable = databaseDataSet.getTable("CLIENTS"); - Assertion.assertEquals(expectedTable, actualTable); - } - - @Test - public void testAssertByQuery() throws Exception { - try (final InputStream is = getClass() - .getClassLoader() - .getResourceAsStream("expected-user.xml")) { - final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); - final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); - final Connection conn = getDataSource().getConnection(); - - conn.createStatement() - .executeUpdate( - "INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); - final ITable actualData = getConnection() - .createQueryTable( - "result_name", - "SELECT * FROM CLIENTS WHERE last_name='Jansen'"); - - Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[]{"id"}); - } - } - - @Test - public void testMultipleFailures() throws Exception { - try (final InputStream is = getClass() - .getClassLoader() - .getResourceAsStream("expected-multiple-failures.xml")) { - final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); - final ITable expectedTable = expectedDataSet.getTable("ITEMS"); - final Connection conn = getDataSource().getConnection(); - final DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler(); - - conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); - final ITable actualData = getConnection().createDataSet().getTable("ITEMS"); - - Assertion.assertEquals(expectedTable, actualData, collectingHandler); - if (!collectingHandler.getDiffList().isEmpty()) { - String message = (String) collectingHandler.getDiffList().stream().map(d -> formatDifference((Difference) d)).collect(joining("\n")); - logger.error(() -> message); - } - } - } - - 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(); - } -} diff --git a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java deleted file mode 100644 index d24410bedf..0000000000 --- a/dbunit/src/test/java/com/baeldung/dbunit/DbUnitTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.baeldung.dbunit; - -import org.dbunit.Assertion; -import org.dbunit.DBTestCase; -import org.dbunit.PropertiesBasedJdbcDatabaseTester; -import org.dbunit.dataset.IDataSet; -import org.dbunit.dataset.ITable; -import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; -import org.dbunit.operation.DatabaseOperation; -import org.junit.Test; - -import java.io.InputStream; -import java.sql.Connection; -import java.sql.ResultSet; - -import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; -import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; -import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; -import static com.baeldung.dbunit.ConnectionSettings.USER; -import static org.assertj.core.api.Assertions.assertThat; - -public class DbUnitTest extends DBTestCase { - - public DbUnitTest(String name) { - super(name); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD); - } - - @Override - protected IDataSet getDataSet() throws Exception { - try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("data.xml")) { - return new FlatXmlDataSetBuilder().build(is); - } - } - - @Override - protected DatabaseOperation getSetUpOperation() { - return DatabaseOperation.REFRESH; - } - - @Override - protected DatabaseOperation getTearDownOperation() { - return DatabaseOperation.DELETE_ALL; - } - - @Test - public void testSelect() throws Exception { - final Connection connection = getConnection().getConnection(); - - final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); - } - - @Test - public void testDelete() throws Exception { - final Connection connection = getConnection().getConnection(); - - try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_delete.xml")) { - ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); - - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - - final IDataSet databaseDataSet = getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - - Assertion.assertEquals(expectedTable, actualTable); - } - } - - @Test - public void testUpdate() throws Exception { - final Connection connection = getConnection().getConnection(); - - try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("items_exp_rename.xml")) { - ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); - - connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - - final IDataSet databaseDataSet = getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - - Assertion.assertEquals(expectedTable, actualTable); - } - } - -} diff --git a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java deleted file mode 100644 index 41d7ffd8d4..0000000000 --- a/dbunit/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.baeldung.dbunit; - -import org.dbunit.Assertion; -import org.dbunit.IDatabaseTester; -import org.dbunit.JdbcDatabaseTester; -import org.dbunit.dataset.IDataSet; -import org.dbunit.dataset.ITable; -import org.dbunit.dataset.filter.DefaultColumnFilter; -import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; -import org.dbunit.operation.DatabaseOperation; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.io.InputStream; -import java.sql.Connection; -import java.sql.ResultSet; - -import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; -import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; -import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; -import static com.baeldung.dbunit.ConnectionSettings.USER; -import static org.assertj.core.api.Assertions.assertThat; -import static org.dbunit.Assertion.assertEquals; - -public class OldSchoolDbUnitTest { - - private static IDatabaseTester tester = null; - - @BeforeClass - public static void setUp() throws Exception { - tester = initDatabaseTester(); - } - - private static IDatabaseTester initDatabaseTester() throws Exception { - final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); - tester.setDataSet(initDataSet()); - tester.setSetUpOperation(DatabaseOperation.REFRESH); - tester.setTearDownOperation(DatabaseOperation.DELETE_ALL); - return tester; - } - - private static IDataSet initDataSet() throws Exception { - try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("data.xml")) { - return new FlatXmlDataSetBuilder().build(is); - } - } - - @Before - public void setup() throws Exception { - tester.onSetup(); - } - - @After - public void tearDown() throws Exception { - tester.onTearDown(); - } - - @Test - public void testSelect() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); - } - - @Test - public void testIgnoringProduced() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - final String[] excludedColumns = {"id", "produced"}; - try (final InputStream is = getClass().getClassLoader() - .getResourceAsStream("expected-ignoring-registered_at.xml")) { - final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); - final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns); - - 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); - - Assertion.assertEquals(expectedTable, actualTable); - } - } - - @Test - public void testDelete() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final InputStream is = - OldSchoolDbUnitTest.class.getClassLoader() - .getResourceAsStream("items_exp_delete.xml");) { - ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - - assertEquals(expectedTable, actualTable); - } - } - - @Test - public void testDeleteWithExcludedColumns() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final InputStream is = - OldSchoolDbUnitTest.class.getClassLoader() - .getResourceAsStream("items_exp_delete_no_produced.xml")) { - final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); - - assertEquals(expectedTable, actualTable); - } - } - - @Test - public void testUpdate() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final InputStream is = - OldSchoolDbUnitTest.class.getClassLoader() - .getResourceAsStream("items_exp_rename.xml")) { - final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - - connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - - assertEquals(expectedTable, actualTable); - } - } - - @Test - public void testUpdateWithExcludedColumns() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final InputStream is = - OldSchoolDbUnitTest.class.getClassLoader() - .getResourceAsStream("items_exp_rename_no_produced.xml")) { - ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - - connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); - - assertEquals(expectedTable, actualTable); - } - } - -} diff --git a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java deleted file mode 100644 index b4e23f56ff..0000000000 --- a/dbunit/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.baeldung.dbunit; - -import org.dbunit.DefaultPrepAndExpectedTestCase; -import org.dbunit.IDatabaseTester; -import org.dbunit.JdbcDatabaseTester; -import org.dbunit.PrepAndExpectedTestCaseSteps; -import org.dbunit.VerifyTableDefinition; -import org.dbunit.dataset.IDataSet; -import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; -import org.dbunit.operation.DatabaseOperation; -import org.dbunit.util.fileloader.DataFileLoader; -import org.dbunit.util.fileloader.FlatXmlDataFileLoader; -import org.junit.Test; - -import java.io.InputStream; -import java.sql.Connection; -import java.sql.ResultSet; - -import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; -import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; -import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; -import static com.baeldung.dbunit.ConnectionSettings.USER; -import static org.assertj.core.api.Assertions.assertThat; - -public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { - - @Override - public void setUp() throws Exception { - setDatabaseTester(initDatabaseTester()); - setDataFileLoader(initDataFileLoader()); - super.setUp(); - } - - private IDatabaseTester initDatabaseTester() throws Exception { - final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); - tester.setDataSet(initDataSet()); - tester.setSetUpOperation(DatabaseOperation.REFRESH); - return tester; - } - - private IDataSet initDataSet() throws Exception { - try (final InputStream is = getClass().getClassLoader().getResourceAsStream("data.xml")) { - return new FlatXmlDataSetBuilder().build(is); - } - } - - private DataFileLoader initDataFileLoader() { - return new FlatXmlDataFileLoader(); - } - - @Test - public void testSelect() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; - final String[] prepDataFiles = {"/users.xml"}; - final String[] expectedDataFiles = {"/users.xml"}; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() - .executeQuery("select * from CLIENTS where id = 1"); - - final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("last_name")).isEqualTo("Xavier"); - } - - @Test - public void testUpdate() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; // define tables to verify - final String[] prepDataFiles = {"/users.xml"}; - final String[] expectedDataFiles = {"/users_exp_rename.xml"}; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() - .executeUpdate("update CLIENTS set first_name = 'new name' where id = 1"); - - super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - } - - @Test - public void testDelete() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; - final String[] prepDataFiles = {"/users.xml"}; - final String[] expectedDataFiles = {"/users_exp_delete.xml"}; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() - .executeUpdate("delete from CLIENTS where id = 2"); - - super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - } - -} diff --git a/dbunit/src/test/resources/data.xml b/dbunit/src/test/resources/data.xml deleted file mode 100644 index 290cc36890..0000000000 --- a/dbunit/src/test/resources/data.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/dbunit/src/test/resources/expected-ignoring-registered_at.xml b/dbunit/src/test/resources/expected-ignoring-registered_at.xml deleted file mode 100644 index ea57b6a961..0000000000 --- a/dbunit/src/test/resources/expected-ignoring-registered_at.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/dbunit/src/test/resources/expected-multiple-failures.xml b/dbunit/src/test/resources/expected-multiple-failures.xml deleted file mode 100644 index ea57b6a961..0000000000 --- a/dbunit/src/test/resources/expected-multiple-failures.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/dbunit/src/test/resources/expected-user.xml b/dbunit/src/test/resources/expected-user.xml deleted file mode 100644 index 631dd84210..0000000000 --- a/dbunit/src/test/resources/expected-user.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/dbunit/src/test/resources/items.xml b/dbunit/src/test/resources/items.xml deleted file mode 100644 index d13e93bbe0..0000000000 --- a/dbunit/src/test/resources/items.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/dbunit/src/test/resources/items_exp_delete.xml b/dbunit/src/test/resources/items_exp_delete.xml deleted file mode 100644 index a6fa2b33e8..0000000000 --- a/dbunit/src/test/resources/items_exp_delete.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/dbunit/src/test/resources/items_exp_delete_no_produced.xml b/dbunit/src/test/resources/items_exp_delete_no_produced.xml deleted file mode 100644 index 3e7f854f5f..0000000000 --- a/dbunit/src/test/resources/items_exp_delete_no_produced.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/dbunit/src/test/resources/items_exp_rename.xml b/dbunit/src/test/resources/items_exp_rename.xml deleted file mode 100644 index 32f1d57cf6..0000000000 --- a/dbunit/src/test/resources/items_exp_rename.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/dbunit/src/test/resources/items_exp_rename_no_produced.xml b/dbunit/src/test/resources/items_exp_rename_no_produced.xml deleted file mode 100644 index b42d3804fa..0000000000 --- a/dbunit/src/test/resources/items_exp_rename_no_produced.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/dbunit/src/test/resources/schema.sql b/dbunit/src/test/resources/schema.sql deleted file mode 100644 index c2a8d2d630..0000000000 --- a/dbunit/src/test/resources/schema.sql +++ /dev/null @@ -1,28 +0,0 @@ -CREATE TABLE IF NOT EXISTS CLIENTS -( - `id` int AUTO_INCREMENT NOT NULL, - `first_name` varchar(100) NOT NULL, - `last_name` varchar(100) NOT NULL, - PRIMARY KEY (`id`) -); - -CREATE TABLE IF NOT EXISTS ITEMS -( - `id` int AUTO_INCREMENT NOT NULL, - `title` varchar(100) NOT NULL, - `produced` date, - `price` float, - PRIMARY KEY (`id`) -); - -CREATE TABLE IF NOT EXISTS PURCHASES -( - `id` int NOT NULL AUTO_INCREMENT, - `id_user` int NOT NULL, - `id_item` int NOT NULL, - `total_price` float NOT NULL, - `quantity` int(11) NOT NULL, - PRIMARY KEY (`id`), - FOREIGN KEY (`id_user`) REFERENCES CLIENTS (`id`) ON DELETE CASCADE, - FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE -); diff --git a/dbunit/src/test/resources/users.xml b/dbunit/src/test/resources/users.xml deleted file mode 100644 index 9ac3909bc5..0000000000 --- a/dbunit/src/test/resources/users.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/dbunit/src/test/resources/users_exp_delete.xml b/dbunit/src/test/resources/users_exp_delete.xml deleted file mode 100644 index 2fe97ae6f6..0000000000 --- a/dbunit/src/test/resources/users_exp_delete.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/dbunit/src/test/resources/users_exp_rename.xml b/dbunit/src/test/resources/users_exp_rename.xml deleted file mode 100644 index 95682118bb..0000000000 --- a/dbunit/src/test/resources/users_exp_rename.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - From dc75e11440a687431620b26d3ed4f8d812e0a293 Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Wed, 1 Apr 2020 07:44:25 +0200 Subject: [PATCH 018/194] [BAEL-2749] DBUnit documentation --- libraries-testing/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries-testing/README.md b/libraries-testing/README.md index 332debfe18..7098c10d28 100644 --- a/libraries-testing/README.md +++ b/libraries-testing/README.md @@ -11,3 +11,4 @@ This module contains articles about test libraries. - [Introduction to Awaitlity](https://www.baeldung.com/awaitlity-testing) - [Introduction to Hoverfly in Java](https://www.baeldung.com/hoverfly) - [Testing with Hamcrest](https://www.baeldung.com/java-junit-hamcrest-guide) +- [Introduction To DBUnit](https://www.baeldung.com/dbunit) From c0abc0ed354f073d0f3958308acb4939f11c49fb Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Wed, 1 Apr 2020 19:44:48 +0200 Subject: [PATCH 019/194] [BAEL-2749] Uses static imports and uses code format --- .../baeldung/dbunit/ConnectionSettings.java | 8 +- .../baeldung/dbunit/DataSourceDBUnitTest.java | 178 ++++++-------- .../java/com/baeldung/dbunit/DbUnitTest.java | 117 +++++----- .../baeldung/dbunit/OldSchoolDbUnitTest.java | 219 ++++++++---------- .../dbunit/PrepAndExpectedDbUnitTest.java | 100 ++++---- pom.xml | 1 - 6 files changed, 285 insertions(+), 338 deletions(-) diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java b/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java index cc29d9c58a..b30d636a12 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java @@ -1,8 +1,8 @@ package com.baeldung.dbunit; public class ConnectionSettings { - public static final String JDBC_DRIVER = org.h2.Driver.class.getName(); - public static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:dbunit/schema.sql'"; - public static final String USER = "sa"; - public static final String PASSWORD = ""; + public static final String JDBC_DRIVER = org.h2.Driver.class.getName(); + public static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:dbunit/schema.sql'"; + public static final String USER = "sa"; + public static final String PASSWORD = ""; } diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java index 662ed44fb6..1cb7489688 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java @@ -15,6 +15,7 @@ import org.junit.Test; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; +import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -25,112 +26,87 @@ import static org.assertj.core.api.Assertions.assertThat; public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { - private static Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class); + private static final Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class); - @Override - protected javax.sql.DataSource getDataSource() { - JdbcDataSource dataSource = new JdbcDataSource(); - dataSource.setURL(JDBC_URL); - dataSource.setUser("sa"); - dataSource.setPassword(""); - return dataSource; - } - - @Override - protected IDataSet getDataSet() throws Exception { - try (java.io.InputStream resourceAsStream = getClass() - .getClassLoader() - .getResourceAsStream("dbunit/data.xml")) { - return new FlatXmlDataSetBuilder().build(resourceAsStream); + @Override protected javax.sql.DataSource getDataSource() { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setURL(JDBC_URL); + dataSource.setUser("sa"); + dataSource.setPassword(""); + return dataSource; } - } - @Override - protected DatabaseOperation getSetUpOperation() { - return DatabaseOperation.REFRESH; - } - - @Override - protected DatabaseOperation getTearDownOperation() { - return DatabaseOperation.DELETE_ALL; - } - - @Before - public void setUp() throws Exception { - super.setUp(); - } - - @After - public void tearDown() throws Exception { - super.tearDown(); - } - - - @Test - public void testSimpleDataSet() throws SQLException { - final Connection connection = getDataSource() - .getConnection(); - - final ResultSet rs = connection - .createStatement() - .executeQuery("select * from iTEMS where id = 1"); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); - } - - @Test - public void testEmptySchema() throws Exception { - final IDataSet expectedDataSet = getDataSet(); - final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); - final IDataSet databaseDataSet = getConnection().createDataSet(); - final ITable actualTable = databaseDataSet.getTable("CLIENTS"); - Assertion.assertEquals(expectedTable, actualTable); - } - - @Test - public void testAssertByQuery() throws Exception { - try (final java.io.InputStream is = getClass() - .getClassLoader() - .getResourceAsStream("dbunit/expected-user.xml")) { - final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); - final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); - final Connection conn = getDataSource().getConnection(); - - conn.createStatement() - .executeUpdate( - "INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); - final ITable actualData = getConnection() - .createQueryTable( - "result_name", - "SELECT * FROM CLIENTS WHERE last_name='Jansen'"); - - Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[]{"id"}); + @Override protected IDataSet getDataSet() throws Exception { + try (InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(resourceAsStream); + } } - } - @Test - public void testMultipleFailures() throws Exception { - try (final java.io.InputStream is = getClass() - .getClassLoader() - .getResourceAsStream("dbunit/expected-multiple-failures.xml")) { - final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); - final ITable expectedTable = expectedDataSet.getTable("ITEMS"); - final Connection conn = getDataSource().getConnection(); - final DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler(); - - conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); - final ITable actualData = getConnection().createDataSet().getTable("ITEMS"); - - Assertion.assertEquals(expectedTable, actualData, collectingHandler); - if (!collectingHandler.getDiffList().isEmpty()) { - String message = (String) collectingHandler.getDiffList().stream().map(d -> formatDifference((Difference) d)).collect(joining("\n")); - logger.error(() -> message); - } + @Override protected DatabaseOperation getSetUpOperation() { + return DatabaseOperation.REFRESH; } - } - 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(); - } + @Override protected DatabaseOperation getTearDownOperation() { + return DatabaseOperation.DELETE_ALL; + } + + @Before public void setUp() throws Exception { + super.setUp(); + } + + @After public void tearDown() throws Exception { + super.tearDown(); + } + + @Test public void testSimpleDataSet() throws SQLException { + final Connection connection = getDataSource().getConnection(); + + final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); + + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + } + + @Test public void testEmptySchema() throws Exception { + final IDataSet expectedDataSet = getDataSet(); + final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); + final IDataSet databaseDataSet = getConnection().createDataSet(); + final ITable actualTable = databaseDataSet.getTable("CLIENTS"); + Assertion.assertEquals(expectedTable, actualTable); + } + + @Test public void testAssertByQuery() throws Exception { + try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-user.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); + final Connection conn = getDataSource().getConnection(); + + conn.createStatement().executeUpdate("INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); + final ITable actualData = getConnection().createQueryTable("result_name", "SELECT * FROM CLIENTS WHERE last_name='Jansen'"); + + Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[] { "id" }); + } + } + + @Test public void testMultipleFailures() throws Exception { + try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-multiple-failures.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = expectedDataSet.getTable("ITEMS"); + final Connection conn = getDataSource().getConnection(); + final DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler(); + + conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); + final ITable actualData = getConnection().createDataSet().getTable("ITEMS"); + + Assertion.assertEquals(expectedTable, actualData, collectingHandler); + if (!collectingHandler.getDiffList().isEmpty()) { + String message = (String) collectingHandler.getDiffList().stream().map(d -> formatDifference((Difference) d)).collect(joining("\n")); + logger.error(() -> message); + } + } + } + + 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(); + } } diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java index 3ed77b2c25..a3a41b9b8d 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java @@ -9,6 +9,7 @@ import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; import org.dbunit.operation.DatabaseOperation; import org.junit.Test; +import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; @@ -20,71 +21,65 @@ import static org.assertj.core.api.Assertions.assertThat; public class DbUnitTest extends DBTestCase { - public DbUnitTest(String name) { - super(name); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD); - } - - @Override - protected IDataSet getDataSet() throws Exception { - try (final java.io.InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { - return new FlatXmlDataSetBuilder().build(is); + public DbUnitTest(String name) { + super(name); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD); } - } - @Override - protected DatabaseOperation getSetUpOperation() { - return DatabaseOperation.REFRESH; - } - - @Override - protected DatabaseOperation getTearDownOperation() { - return DatabaseOperation.DELETE_ALL; - } - - @Test - public void testSelect() throws Exception { - final Connection connection = getConnection().getConnection(); - - final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); - } - - @Test - public void testDelete() throws Exception { - final Connection connection = getConnection().getConnection(); - - try (final java.io.InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { - ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); - - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - - final IDataSet databaseDataSet = getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - - Assertion.assertEquals(expectedTable, actualTable); + @Override protected IDataSet getDataSet() throws Exception { + try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(is); + } } - } - @Test - public void testUpdate() throws Exception { - final Connection connection = getConnection().getConnection(); - - try (final java.io.InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { - ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("items"); - - connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - - final IDataSet databaseDataSet = getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - - Assertion.assertEquals(expectedTable, actualTable); + @Override protected DatabaseOperation getSetUpOperation() { + return DatabaseOperation.REFRESH; + } + + @Override protected DatabaseOperation getTearDownOperation() { + return DatabaseOperation.DELETE_ALL; + } + + @Test public void testSelect() throws Exception { + final Connection connection = getConnection().getConnection(); + + final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); + + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + } + + @Test public void testDelete() throws Exception { + final Connection connection = getConnection().getConnection(); + + try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + + Assertion.assertEquals(expectedTable, actualTable); + } + } + + @Test public void testUpdate() throws Exception { + final Connection connection = getConnection().getConnection(); + + try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); + + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + + Assertion.assertEquals(expectedTable, actualTable); + } } - } } diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java index aa6d9143bb..be6023d432 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java @@ -13,6 +13,7 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; @@ -25,137 +26,119 @@ import static org.dbunit.Assertion.assertEquals; public class OldSchoolDbUnitTest { - private static IDatabaseTester tester = null; + private static IDatabaseTester tester = null; - @BeforeClass - public static void setUp() throws Exception { - tester = initDatabaseTester(); - } - - private static IDatabaseTester initDatabaseTester() throws Exception { - final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); - tester.setDataSet(initDataSet()); - tester.setSetUpOperation(DatabaseOperation.REFRESH); - tester.setTearDownOperation(DatabaseOperation.DELETE_ALL); - return tester; - } - - private static IDataSet initDataSet() throws Exception { - try (final java.io.InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { - return new FlatXmlDataSetBuilder().build(is); + @BeforeClass public static void setUp() throws Exception { + tester = initDatabaseTester(); } - } - @Before - public void setup() throws Exception { - tester.onSetup(); - } - - @After - public void tearDown() throws Exception { - tester.onTearDown(); - } - - @Test - public void testSelect() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - final ResultSet rs = connection.createStatement().executeQuery("select * from iTEMS where id = 1"); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); - } - - @Test - public void testIgnoringProduced() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - final String[] excludedColumns = {"id", "produced"}; - try (final java.io.InputStream is = getClass().getClassLoader() - .getResourceAsStream("dbunit/expected-ignoring-registered_at.xml")) { - final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); - final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns); - - 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); - - Assertion.assertEquals(expectedTable, actualTable); + private static IDatabaseTester initDatabaseTester() throws Exception { + final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); + tester.setDataSet(initDataSet()); + tester.setSetUpOperation(DatabaseOperation.REFRESH); + tester.setTearDownOperation(DatabaseOperation.DELETE_ALL); + return tester; } - } - @Test - public void testDelete() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final java.io.InputStream is = - OldSchoolDbUnitTest.class.getClassLoader() - .getResourceAsStream("dbunit/items_exp_delete.xml");) { - ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - - assertEquals(expectedTable, actualTable); + private static IDataSet initDataSet() throws Exception { + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(is); + } } - } - @Test - public void testDeleteWithExcludedColumns() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final java.io.InputStream is = - OldSchoolDbUnitTest.class.getClassLoader() - .getResourceAsStream("dbunit/items_exp_delete_no_produced.xml")) { - final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); - - assertEquals(expectedTable, actualTable); + @Before public void setup() throws Exception { + tester.onSetup(); } - } - @Test - public void testUpdate() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final java.io.InputStream is = - OldSchoolDbUnitTest.class.getClassLoader() - .getResourceAsStream("dbunit/items_exp_rename.xml")) { - final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); - - connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - - assertEquals(expectedTable, actualTable); + @After public void tearDown() throws Exception { + tester.onTearDown(); } - } - @Test - public void testUpdateWithExcludedColumns() throws Exception { - final Connection connection = tester.getConnection().getConnection(); + @Test public void testSelect() throws Exception { + final Connection connection = tester.getConnection().getConnection(); - try (final java.io.InputStream is = - OldSchoolDbUnitTest.class.getClassLoader() - .getResourceAsStream("dbunit/items_exp_rename_no_produced.xml")) { - ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("items"); + final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); - connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("items"); - actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[]{"produced"}); - - assertEquals(expectedTable, actualTable); + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + } + + @Test public void testIgnoringProduced() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + final String[] excludedColumns = { "id", "produced" }; + try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-ignoring-registered_at.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns); + + 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); + + Assertion.assertEquals(expectedTable, actualTable); + } + } + + @Test public void testDelete() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + + assertEquals(expectedTable, actualTable); + } + } + + @Test public void testDeleteWithExcludedColumns() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete_no_produced.xml")) { + final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); + + assertEquals(expectedTable, actualTable); + } + } + + @Test public void testUpdate() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { + final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); + + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + + assertEquals(expectedTable, actualTable); + } + } + + @Test public void testUpdateWithExcludedColumns() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename_no_produced.xml")) { + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); + + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); + + assertEquals(expectedTable, actualTable); + } } - } } diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java index 7e77cd8fc3..f797f153a0 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java @@ -12,6 +12,7 @@ import org.dbunit.util.fileloader.DataFileLoader; import org.dbunit.util.fileloader.FlatXmlDataFileLoader; import org.junit.Test; +import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; @@ -23,67 +24,60 @@ import static org.assertj.core.api.Assertions.assertThat; public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { - @Override - public void setUp() throws Exception { - setDatabaseTester(initDatabaseTester()); - setDataFileLoader(initDataFileLoader()); - super.setUp(); - } - - private IDatabaseTester initDatabaseTester() throws Exception { - final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); - tester.setDataSet(initDataSet()); - tester.setSetUpOperation(DatabaseOperation.REFRESH); - return tester; - } - - private IDataSet initDataSet() throws Exception { - try (final java.io.InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/data.xml")) { - return new FlatXmlDataSetBuilder().build(is); + @Override public void setUp() throws Exception { + setDatabaseTester(initDatabaseTester()); + setDataFileLoader(initDataFileLoader()); + super.setUp(); } - } - private DataFileLoader initDataFileLoader() { - return new FlatXmlDataFileLoader(); - } + private IDatabaseTester initDatabaseTester() throws Exception { + final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); + tester.setDataSet(initDataSet()); + tester.setSetUpOperation(DatabaseOperation.REFRESH); + return tester; + } - @Test - public void testSelect() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; - final String[] prepDataFiles = {"/dbunit/users.xml"}; - final String[] expectedDataFiles = {"/dbunit/users.xml"}; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() - .executeQuery("select * from CLIENTS where id = 1"); + private IDataSet initDataSet() throws Exception { + try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(is); + } + } - final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + private DataFileLoader initDataFileLoader() { + return new FlatXmlDataFileLoader(); + } - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("last_name")).isEqualTo("Xavier"); - } + @Test public void testSelect() throws Exception { + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; + final String[] prepDataFiles = { "/dbunit/users.xml" }; + final String[] expectedDataFiles = { "/dbunit/users.xml" }; + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeQuery("select * from CLIENTS where id = 1"); - @Test - public void testUpdate() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; // define tables to verify - final String[] prepDataFiles = {"/dbunit/users.xml"}; - final String[] expectedDataFiles = {"/dbunit/users_exp_rename.xml"}; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() - .executeUpdate("update CLIENTS set first_name = 'new name' where id = 1"); + final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - } + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("last_name")).isEqualTo("Xavier"); + } - @Test - public void testDelete() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = {new VerifyTableDefinition("CLIENTS", new String[]{})}; - final String[] prepDataFiles = {"/dbunit/users.xml"}; - final String[] expectedDataFiles = {"/dbunit/users_exp_delete.xml"}; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement() - .executeUpdate("delete from CLIENTS where id = 2"); + @Test public void testUpdate() throws Exception { + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; // define tables to verify + final String[] prepDataFiles = { "/dbunit/users.xml" }; + final String[] expectedDataFiles = { "/dbunit/users_exp_rename.xml" }; + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeUpdate("update CLIENTS set first_name = 'new name' where id = 1"); - super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - } + super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + } + + @Test public void testDelete() throws Exception { + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; + final String[] prepDataFiles = { "/dbunit/users.xml" }; + final String[] expectedDataFiles = { "/dbunit/users_exp_delete.xml" }; + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeUpdate("delete from CLIENTS where id = 2"); + + super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + } } diff --git a/pom.xml b/pom.xml index 734e2c8ab9..8b09f69252 100644 --- a/pom.xml +++ b/pom.xml @@ -601,7 +601,6 @@ - dbunit parent-boot-1 parent-boot-2 From 064e16251be28928331af940acf6b39fe9258dda Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Wed, 1 Apr 2020 20:02:46 +0200 Subject: [PATCH 020/194] [BAEL-2749] Formats pom --- pom.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pom.xml b/pom.xml index 8b09f69252..04a2ce054c 100644 --- a/pom.xml +++ b/pom.xml @@ -601,7 +601,6 @@ - parent-boot-1 parent-boot-2 parent-spring-4 @@ -1289,8 +1288,6 @@ - dbunit - parent-boot-1 parent-boot-2 parent-spring-4 From f06af6499859b3dcd45d14d2060631a4fd1f0241 Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Thu, 2 Apr 2020 11:20:34 +0200 Subject: [PATCH 021/194] [BAEL-2749] Indentation and annotations format --- .../baeldung/dbunit/ConnectionSettings.java | 8 +- .../baeldung/dbunit/DataSourceDBUnitTest.java | 162 +++++++------- .../java/com/baeldung/dbunit/DbUnitTest.java | 116 +++++----- .../baeldung/dbunit/OldSchoolDbUnitTest.java | 209 +++++++++--------- .../dbunit/PrepAndExpectedDbUnitTest.java | 96 ++++---- 5 files changed, 310 insertions(+), 281 deletions(-) diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java b/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java index b30d636a12..cc29d9c58a 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/ConnectionSettings.java @@ -1,8 +1,8 @@ package com.baeldung.dbunit; public class ConnectionSettings { - public static final String JDBC_DRIVER = org.h2.Driver.class.getName(); - public static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:dbunit/schema.sql'"; - public static final String USER = "sa"; - public static final String PASSWORD = ""; + public static final String JDBC_DRIVER = org.h2.Driver.class.getName(); + public static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:dbunit/schema.sql'"; + public static final String USER = "sa"; + public static final String PASSWORD = ""; } diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java index 1cb7489688..93503277b4 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java @@ -26,87 +26,97 @@ import static org.assertj.core.api.Assertions.assertThat; public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { - private static final Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class); + private static final Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class); - @Override protected javax.sql.DataSource getDataSource() { - JdbcDataSource dataSource = new JdbcDataSource(); - dataSource.setURL(JDBC_URL); - dataSource.setUser("sa"); - dataSource.setPassword(""); - return dataSource; + @Override + protected javax.sql.DataSource getDataSource() { + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setURL(JDBC_URL); + dataSource.setUser("sa"); + dataSource.setPassword(""); + return dataSource; + } + + @Override + protected IDataSet getDataSet() throws Exception { + try (InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(resourceAsStream); } + } - @Override protected IDataSet getDataSet() throws Exception { - try (InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("dbunit/data.xml")) { - return new FlatXmlDataSetBuilder().build(resourceAsStream); - } + @Override + protected DatabaseOperation getSetUpOperation() { + return DatabaseOperation.REFRESH; + } + + @Override + protected DatabaseOperation getTearDownOperation() { + return DatabaseOperation.DELETE_ALL; + } + + @Before + public void setUp() throws Exception { + super.setUp(); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testSimpleDataSet() throws SQLException { + final Connection connection = getDataSource().getConnection(); + + final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); + + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + } + + @Test + public void testEmptySchema() throws Exception { + final IDataSet expectedDataSet = getDataSet(); + final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); + final IDataSet databaseDataSet = getConnection().createDataSet(); + final ITable actualTable = databaseDataSet.getTable("CLIENTS"); + Assertion.assertEquals(expectedTable, actualTable); + } + + @Test + public void testAssertByQuery() throws Exception { + try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-user.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); + final Connection conn = getDataSource().getConnection(); + + conn.createStatement().executeUpdate("INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); + final ITable actualData = getConnection().createQueryTable("result_name", "SELECT * FROM CLIENTS WHERE last_name='Jansen'"); + + Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[] { "id" }); } + } - @Override protected DatabaseOperation getSetUpOperation() { - return DatabaseOperation.REFRESH; + @Test + public void testMultipleFailures() throws Exception { + try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-multiple-failures.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = expectedDataSet.getTable("ITEMS"); + final Connection conn = getDataSource().getConnection(); + final DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler(); + + conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); + final ITable actualData = getConnection().createDataSet().getTable("ITEMS"); + + Assertion.assertEquals(expectedTable, actualData, collectingHandler); + if (!collectingHandler.getDiffList().isEmpty()) { + String message = (String) collectingHandler.getDiffList().stream().map(d -> formatDifference((Difference) d)).collect(joining("\n")); + logger.error(() -> message); + } } + } - @Override protected DatabaseOperation getTearDownOperation() { - return DatabaseOperation.DELETE_ALL; - } - - @Before public void setUp() throws Exception { - super.setUp(); - } - - @After public void tearDown() throws Exception { - super.tearDown(); - } - - @Test public void testSimpleDataSet() throws SQLException { - final Connection connection = getDataSource().getConnection(); - - final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); - } - - @Test public void testEmptySchema() throws Exception { - final IDataSet expectedDataSet = getDataSet(); - final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); - final IDataSet databaseDataSet = getConnection().createDataSet(); - final ITable actualTable = databaseDataSet.getTable("CLIENTS"); - Assertion.assertEquals(expectedTable, actualTable); - } - - @Test public void testAssertByQuery() throws Exception { - try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-user.xml")) { - final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); - final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); - final Connection conn = getDataSource().getConnection(); - - conn.createStatement().executeUpdate("INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); - final ITable actualData = getConnection().createQueryTable("result_name", "SELECT * FROM CLIENTS WHERE last_name='Jansen'"); - - Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[] { "id" }); - } - } - - @Test public void testMultipleFailures() throws Exception { - try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-multiple-failures.xml")) { - final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); - final ITable expectedTable = expectedDataSet.getTable("ITEMS"); - final Connection conn = getDataSource().getConnection(); - final DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler(); - - conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); - final ITable actualData = getConnection().createDataSet().getTable("ITEMS"); - - Assertion.assertEquals(expectedTable, actualData, collectingHandler); - if (!collectingHandler.getDiffList().isEmpty()) { - String message = (String) collectingHandler.getDiffList().stream().map(d -> formatDifference((Difference) d)).collect(joining("\n")); - logger.error(() -> message); - } - } - } - - 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(); - } + 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(); + } } diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java index a3a41b9b8d..da4ac54f12 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java @@ -21,65 +21,71 @@ import static org.assertj.core.api.Assertions.assertThat; public class DbUnitTest extends DBTestCase { - public DbUnitTest(String name) { - super(name); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD); + public DbUnitTest(String name) { + super(name); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER); + System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD); + } + + @Override + protected IDataSet getDataSet() throws Exception { + try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(is); } + } - @Override protected IDataSet getDataSet() throws Exception { - try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { - return new FlatXmlDataSetBuilder().build(is); - } + @Override + protected DatabaseOperation getSetUpOperation() { + return DatabaseOperation.REFRESH; + } + + @Override + protected DatabaseOperation getTearDownOperation() { + return DatabaseOperation.DELETE_ALL; + } + + @Test + public void testSelect() throws Exception { + final Connection connection = getConnection().getConnection(); + + final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); + + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + } + + @Test + public void testDelete() throws Exception { + final Connection connection = getConnection().getConnection(); + + try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + + Assertion.assertEquals(expectedTable, actualTable); } + } - @Override protected DatabaseOperation getSetUpOperation() { - return DatabaseOperation.REFRESH; - } - - @Override protected DatabaseOperation getTearDownOperation() { - return DatabaseOperation.DELETE_ALL; - } - - @Test public void testSelect() throws Exception { - final Connection connection = getConnection().getConnection(); - - final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); - } - - @Test public void testDelete() throws Exception { - final Connection connection = getConnection().getConnection(); - - try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { - ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); - - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - - final IDataSet databaseDataSet = getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("ITEMS"); - - Assertion.assertEquals(expectedTable, actualTable); - } - } - - @Test public void testUpdate() throws Exception { - final Connection connection = getConnection().getConnection(); - - try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { - ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); - - connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - - final IDataSet databaseDataSet = getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("ITEMS"); - - Assertion.assertEquals(expectedTable, actualTable); - } + @Test + public void testUpdate() throws Exception { + final Connection connection = getConnection().getConnection(); + + try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); + + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + + Assertion.assertEquals(expectedTable, actualTable); } + } } diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java index be6023d432..a7821102dc 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java @@ -26,119 +26,128 @@ import static org.dbunit.Assertion.assertEquals; public class OldSchoolDbUnitTest { - private static IDatabaseTester tester = null; + private static IDatabaseTester tester = null; - @BeforeClass public static void setUp() throws Exception { - tester = initDatabaseTester(); + @BeforeClass + public static void setUp() throws Exception { + tester = initDatabaseTester(); + } + + private static IDatabaseTester initDatabaseTester() throws Exception { + final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); + tester.setDataSet(initDataSet()); + tester.setSetUpOperation(DatabaseOperation.REFRESH); + tester.setTearDownOperation(DatabaseOperation.DELETE_ALL); + return tester; + } + + private static IDataSet initDataSet() throws Exception { + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(is); } + } - private static IDatabaseTester initDatabaseTester() throws Exception { - final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); - tester.setDataSet(initDataSet()); - tester.setSetUpOperation(DatabaseOperation.REFRESH); - tester.setTearDownOperation(DatabaseOperation.DELETE_ALL); - return tester; + @Before + public void setup() throws Exception { + tester.onSetup(); + } + + @After + public void tearDown() throws Exception { + tester.onTearDown(); + } + + @Test + public void testSelect() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); + + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); + } + + @Test + public void testIgnoringProduced() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + final String[] excludedColumns = { "id", "produced" }; + try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-ignoring-registered_at.xml")) { + final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); + final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns); + + 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); + + Assertion.assertEquals(expectedTable, actualTable); } + } - private static IDataSet initDataSet() throws Exception { - try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { - return new FlatXmlDataSetBuilder().build(is); - } + @Test + public void testDelete() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + + assertEquals(expectedTable, actualTable); } + } - @Before public void setup() throws Exception { - tester.onSetup(); + @Test + public void testDeleteWithExcludedColumns() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete_no_produced.xml")) { + final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); + + assertEquals(expectedTable, actualTable); } + } - @After public void tearDown() throws Exception { - tester.onTearDown(); + @Test + public void testUpdate() throws Exception { + final Connection connection = tester.getConnection().getConnection(); + + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { + final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); + + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + + assertEquals(expectedTable, actualTable); } + } - @Test public void testSelect() throws Exception { - final Connection connection = tester.getConnection().getConnection(); + @Test + public void testUpdateWithExcludedColumns() throws Exception { + final Connection connection = tester.getConnection().getConnection(); - final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); + try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename_no_produced.xml")) { + ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); - } - - @Test public void testIgnoringProduced() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - final String[] excludedColumns = { "id", "produced" }; - try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-ignoring-registered_at.xml")) { - final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); - final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns); - - 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); - - Assertion.assertEquals(expectedTable, actualTable); - } - } - - @Test public void testDelete() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { - ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); - - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("ITEMS"); - - assertEquals(expectedTable, actualTable); - } - } - - @Test public void testDeleteWithExcludedColumns() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete_no_produced.xml")) { - final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); - - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("ITEMS"); - actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); - - assertEquals(expectedTable, actualTable); - } - } - - @Test public void testUpdate() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { - final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); - - connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("ITEMS"); - - assertEquals(expectedTable, actualTable); - } - } - - @Test public void testUpdateWithExcludedColumns() throws Exception { - final Connection connection = tester.getConnection().getConnection(); - - try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename_no_produced.xml")) { - ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); - - connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - - final IDataSet databaseDataSet = tester.getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("ITEMS"); - actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); - - assertEquals(expectedTable, actualTable); - } + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = tester.getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); + + assertEquals(expectedTable, actualTable); } + } } diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java index f797f153a0..039dfd1639 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java @@ -24,60 +24,64 @@ import static org.assertj.core.api.Assertions.assertThat; public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { - @Override public void setUp() throws Exception { - setDatabaseTester(initDatabaseTester()); - setDataFileLoader(initDataFileLoader()); - super.setUp(); + @Override + public void setUp() throws Exception { + setDatabaseTester(initDatabaseTester()); + setDataFileLoader(initDataFileLoader()); + super.setUp(); + } + + private IDatabaseTester initDatabaseTester() throws Exception { + final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); + tester.setDataSet(initDataSet()); + tester.setSetUpOperation(DatabaseOperation.REFRESH); + return tester; + } + + private IDataSet initDataSet() throws Exception { + try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/data.xml")) { + return new FlatXmlDataSetBuilder().build(is); } + } - private IDatabaseTester initDatabaseTester() throws Exception { - final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); - tester.setDataSet(initDataSet()); - tester.setSetUpOperation(DatabaseOperation.REFRESH); - return tester; - } + private DataFileLoader initDataFileLoader() { + return new FlatXmlDataFileLoader(); + } - private IDataSet initDataSet() throws Exception { - try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/data.xml")) { - return new FlatXmlDataSetBuilder().build(is); - } - } + @Test + public void testSelect() throws Exception { + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; + final String[] prepDataFiles = { "/dbunit/users.xml" }; + final String[] expectedDataFiles = { "/dbunit/users.xml" }; + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeQuery("select * from CLIENTS where id = 1"); - private DataFileLoader initDataFileLoader() { - return new FlatXmlDataFileLoader(); - } + final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - @Test public void testSelect() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; - final String[] prepDataFiles = { "/dbunit/users.xml" }; - final String[] expectedDataFiles = { "/dbunit/users.xml" }; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeQuery("select * from CLIENTS where id = 1"); + assertThat(rs.next()).isTrue(); + assertThat(rs.getString("last_name")).isEqualTo("Xavier"); + } - final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + @Test + public void testUpdate() throws Exception { + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; // define tables to verify + final String[] prepDataFiles = { "/dbunit/users.xml" }; + final String[] expectedDataFiles = { "/dbunit/users_exp_rename.xml" }; + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeUpdate("update CLIENTS set first_name = 'new name' where id = 1"); - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("last_name")).isEqualTo("Xavier"); - } + super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + } - @Test public void testUpdate() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; // define tables to verify - final String[] prepDataFiles = { "/dbunit/users.xml" }; - final String[] expectedDataFiles = { "/dbunit/users_exp_rename.xml" }; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeUpdate("update CLIENTS set first_name = 'new name' where id = 1"); + @Test + public void testDelete() throws Exception { + final Connection connection = getConnection().getConnection(); + final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; + final String[] prepDataFiles = { "/dbunit/users.xml" }; + final String[] expectedDataFiles = { "/dbunit/users_exp_delete.xml" }; + final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeUpdate("delete from CLIENTS where id = 2"); - super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - } - - @Test public void testDelete() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; - final String[] prepDataFiles = { "/dbunit/users.xml" }; - final String[] expectedDataFiles = { "/dbunit/users_exp_delete.xml" }; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeUpdate("delete from CLIENTS where id = 2"); - - super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - } + super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); + } } From e98323d913d19af96119a9d9220b8eebda64c2fc Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Fri, 3 Apr 2020 08:51:46 +0200 Subject: [PATCH 022/194] [BAEL-2749] Renaming test methods and running them with JUnit4 --- .../baeldung/dbunit/DataSourceDBUnitTest.java | 63 +++++++++++-- .../java/com/baeldung/dbunit/DbUnitTest.java | 91 ------------------- .../baeldung/dbunit/OldSchoolDbUnitTest.java | 26 ++++-- .../dbunit/PrepAndExpectedDbUnitTest.java | 87 ------------------ .../jsonassert/JsonAssertUnitTest.java | 10 +- .../src/test/resources/dbunit/data.xml | 2 +- .../dbunit/items_exp_rename_no_produced.xml | 2 +- .../src/test/resources/dbunit/users.xml | 2 +- .../resources/dbunit/users_exp_delete.xml | 2 +- .../resources/dbunit/users_exp_rename.xml | 2 +- 10 files changed, 80 insertions(+), 207 deletions(-) delete mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java delete mode 100644 libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java index 93503277b4..20b0337f4d 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java @@ -14,6 +14,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; import java.io.InputStream; import java.sql.Connection; @@ -23,7 +25,9 @@ import java.sql.SQLException; import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; import static java.util.stream.Collectors.joining; import static org.assertj.core.api.Assertions.assertThat; +import static org.dbunit.Assertion.assertEqualsIgnoreCols; +@RunWith(JUnit4.class) public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { private static final Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class); @@ -65,7 +69,7 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { } @Test - public void testSimpleDataSet() throws SQLException { + public void givenDataSet_whenSelect_thenFirstTitleIsGreyTShirt() throws SQLException { final Connection connection = getDataSource().getConnection(); final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); @@ -75,7 +79,7 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { } @Test - public void testEmptySchema() throws Exception { + public void givenDataSetEmptySchema_whenDataSetCreated_thenTablesAreEqual() throws Exception { final IDataSet expectedDataSet = getDataSet(); final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); final IDataSet databaseDataSet = getConnection().createDataSet(); @@ -84,33 +88,74 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { } @Test - public void testAssertByQuery() throws Exception { + public void givenDataSet_whenInsert_thenTableHasNewClient() throws Exception { try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-user.xml")) { final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); final Connection conn = getDataSource().getConnection(); - conn.createStatement().executeUpdate("INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); - final ITable actualData = getConnection().createQueryTable("result_name", "SELECT * FROM CLIENTS WHERE last_name='Jansen'"); + conn.createStatement() + .executeUpdate( + "INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); + final ITable actualData = getConnection() + .createQueryTable( + "result_name", + "SELECT * FROM CLIENTS WHERE last_name='Jansen'"); - Assertion.assertEqualsIgnoreCols(expectedTable, actualData, new String[] { "id" }); + assertEqualsIgnoreCols(expectedTable, actualData, new String[] { "id" }); } } @Test - public void testMultipleFailures() throws Exception { + public void givenDataSet_whenDelete_thenItemIsDeleted() throws Exception { + final Connection connection = getConnection().getConnection(); + + try (final InputStream is = DataSourceDBUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); + + connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); + + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + + Assertion.assertEquals(expectedTable, actualTable); + } + } + + @Test + public void givenDataSet_whenUpdate_thenItemHasNewName() throws Exception { + final Connection connection = getConnection().getConnection(); + + try (final InputStream is = DataSourceDBUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { + ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); + + connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); + + final IDataSet databaseDataSet = getConnection().createDataSet(); + ITable actualTable = databaseDataSet.getTable("ITEMS"); + + Assertion.assertEquals(expectedTable, actualTable); + } + } + + @Test + public void givenDataSet_whenInsertUnexpectedData_thenFailOnAllUnexpectedValues() throws Exception { try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-multiple-failures.xml")) { final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); final ITable expectedTable = expectedDataSet.getTable("ITEMS"); final Connection conn = getDataSource().getConnection(); final DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler(); - conn.createStatement().executeUpdate("INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); + conn.createStatement().executeUpdate( + "INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); final ITable actualData = getConnection().createDataSet().getTable("ITEMS"); Assertion.assertEquals(expectedTable, actualData, collectingHandler); if (!collectingHandler.getDiffList().isEmpty()) { - String message = (String) collectingHandler.getDiffList().stream().map(d -> formatDifference((Difference) d)).collect(joining("\n")); + String message = (String) collectingHandler + .getDiffList() + .stream() + .map(d -> formatDifference((Difference) d)).collect(joining("\n")); logger.error(() -> message); } } diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java deleted file mode 100644 index da4ac54f12..0000000000 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/DbUnitTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.baeldung.dbunit; - -import org.dbunit.Assertion; -import org.dbunit.DBTestCase; -import org.dbunit.PropertiesBasedJdbcDatabaseTester; -import org.dbunit.dataset.IDataSet; -import org.dbunit.dataset.ITable; -import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; -import org.dbunit.operation.DatabaseOperation; -import org.junit.Test; - -import java.io.InputStream; -import java.sql.Connection; -import java.sql.ResultSet; - -import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; -import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; -import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; -import static com.baeldung.dbunit.ConnectionSettings.USER; -import static org.assertj.core.api.Assertions.assertThat; - -public class DbUnitTest extends DBTestCase { - - public DbUnitTest(String name) { - super(name); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, JDBC_DRIVER); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, JDBC_URL); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, USER); - System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, PASSWORD); - } - - @Override - protected IDataSet getDataSet() throws Exception { - try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { - return new FlatXmlDataSetBuilder().build(is); - } - } - - @Override - protected DatabaseOperation getSetUpOperation() { - return DatabaseOperation.REFRESH; - } - - @Override - protected DatabaseOperation getTearDownOperation() { - return DatabaseOperation.DELETE_ALL; - } - - @Test - public void testSelect() throws Exception { - final Connection connection = getConnection().getConnection(); - - final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); - } - - @Test - public void testDelete() throws Exception { - final Connection connection = getConnection().getConnection(); - - try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { - ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); - - connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); - - final IDataSet databaseDataSet = getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("ITEMS"); - - Assertion.assertEquals(expectedTable, actualTable); - } - } - - @Test - public void testUpdate() throws Exception { - final Connection connection = getConnection().getConnection(); - - try (final InputStream is = DbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { - ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); - - connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); - - final IDataSet databaseDataSet = getConnection().createDataSet(); - ITable actualTable = databaseDataSet.getTable("ITEMS"); - - Assertion.assertEquals(expectedTable, actualTable); - } - } - -} diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java index a7821102dc..6243af9676 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/OldSchoolDbUnitTest.java @@ -12,6 +12,8 @@ import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; import java.io.InputStream; import java.sql.Connection; @@ -24,6 +26,7 @@ import static com.baeldung.dbunit.ConnectionSettings.USER; import static org.assertj.core.api.Assertions.assertThat; import static org.dbunit.Assertion.assertEquals; +@RunWith(JUnit4.class) public class OldSchoolDbUnitTest { private static IDatabaseTester tester = null; @@ -58,7 +61,7 @@ public class OldSchoolDbUnitTest { } @Test - public void testSelect() throws Exception { + public void givenDataSet_whenSelect_thenFirstTitleIsGreyTShirt() throws Exception { final Connection connection = tester.getConnection().getConnection(); final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); @@ -68,24 +71,27 @@ public class OldSchoolDbUnitTest { } @Test - public void testIgnoringProduced() throws Exception { + public void givenDataSet_whenInsert_thenGetResultsAreStillEqualIfIgnoringColumnsWithDifferentProduced() throws Exception { final Connection connection = tester.getConnection().getConnection(); final String[] excludedColumns = { "id", "produced" }; try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-ignoring-registered_at.xml")) { final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); - final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable("ITEMS"), excludedColumns); + final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable( + expectedDataSet.getTable("ITEMS"), excludedColumns); - connection.createStatement().executeUpdate("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); + final ITable actualTable = DefaultColumnFilter.excludedColumnsTable( + databaseDataSet.getTable("ITEMS"), excludedColumns); Assertion.assertEquals(expectedTable, actualTable); } } @Test - public void testDelete() throws Exception { + public void givenDataSet_whenDelete_thenItemIsRemoved() throws Exception { final Connection connection = tester.getConnection().getConnection(); try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { @@ -101,7 +107,7 @@ public class OldSchoolDbUnitTest { } @Test - public void testDeleteWithExcludedColumns() throws Exception { + public void givenDataSet_whenDelete_thenItemIsRemovedAndResultsEqualIfProducedIsIgnored() throws Exception { final Connection connection = tester.getConnection().getConnection(); try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete_no_produced.xml")) { @@ -118,7 +124,7 @@ public class OldSchoolDbUnitTest { } @Test - public void testUpdate() throws Exception { + public void givenDataSet_whenUpdate_thenItemHasNewName() throws Exception { final Connection connection = tester.getConnection().getConnection(); try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { @@ -134,18 +140,18 @@ public class OldSchoolDbUnitTest { } @Test - public void testUpdateWithExcludedColumns() throws Exception { + public void givenDataSet_whenUpdateWithNoProduced_thenItemHasNewName() throws Exception { final Connection connection = tester.getConnection().getConnection(); try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename_no_produced.xml")) { ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); + expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[] { "produced" }); connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); final IDataSet databaseDataSet = tester.getConnection().createDataSet(); ITable actualTable = databaseDataSet.getTable("ITEMS"); actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); - assertEquals(expectedTable, actualTable); } } diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java deleted file mode 100644 index 039dfd1639..0000000000 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/PrepAndExpectedDbUnitTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.baeldung.dbunit; - -import org.dbunit.DefaultPrepAndExpectedTestCase; -import org.dbunit.IDatabaseTester; -import org.dbunit.JdbcDatabaseTester; -import org.dbunit.PrepAndExpectedTestCaseSteps; -import org.dbunit.VerifyTableDefinition; -import org.dbunit.dataset.IDataSet; -import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; -import org.dbunit.operation.DatabaseOperation; -import org.dbunit.util.fileloader.DataFileLoader; -import org.dbunit.util.fileloader.FlatXmlDataFileLoader; -import org.junit.Test; - -import java.io.InputStream; -import java.sql.Connection; -import java.sql.ResultSet; - -import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; -import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; -import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; -import static com.baeldung.dbunit.ConnectionSettings.USER; -import static org.assertj.core.api.Assertions.assertThat; - -public class PrepAndExpectedDbUnitTest extends DefaultPrepAndExpectedTestCase { - - @Override - public void setUp() throws Exception { - setDatabaseTester(initDatabaseTester()); - setDataFileLoader(initDataFileLoader()); - super.setUp(); - } - - private IDatabaseTester initDatabaseTester() throws Exception { - final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); - tester.setDataSet(initDataSet()); - tester.setSetUpOperation(DatabaseOperation.REFRESH); - return tester; - } - - private IDataSet initDataSet() throws Exception { - try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/data.xml")) { - return new FlatXmlDataSetBuilder().build(is); - } - } - - private DataFileLoader initDataFileLoader() { - return new FlatXmlDataFileLoader(); - } - - @Test - public void testSelect() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; - final String[] prepDataFiles = { "/dbunit/users.xml" }; - final String[] expectedDataFiles = { "/dbunit/users.xml" }; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeQuery("select * from CLIENTS where id = 1"); - - final ResultSet rs = (ResultSet) super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - - assertThat(rs.next()).isTrue(); - assertThat(rs.getString("last_name")).isEqualTo("Xavier"); - } - - @Test - public void testUpdate() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; // define tables to verify - final String[] prepDataFiles = { "/dbunit/users.xml" }; - final String[] expectedDataFiles = { "/dbunit/users_exp_rename.xml" }; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeUpdate("update CLIENTS set first_name = 'new name' where id = 1"); - - super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - } - - @Test - public void testDelete() throws Exception { - final Connection connection = getConnection().getConnection(); - final VerifyTableDefinition[] verifyTables = { new VerifyTableDefinition("CLIENTS", new String[] {}) }; - final String[] prepDataFiles = { "/dbunit/users.xml" }; - final String[] expectedDataFiles = { "/dbunit/users_exp_delete.xml" }; - final PrepAndExpectedTestCaseSteps testSteps = () -> connection.createStatement().executeUpdate("delete from CLIENTS where id = 2"); - - super.runTest(verifyTables, prepDataFiles, expectedDataFiles, testSteps); - } - -} diff --git a/libraries-testing/src/test/java/com/baeldung/jsonassert/JsonAssertUnitTest.java b/libraries-testing/src/test/java/com/baeldung/jsonassert/JsonAssertUnitTest.java index ce9638c4af..822468e91f 100644 --- a/libraries-testing/src/test/java/com/baeldung/jsonassert/JsonAssertUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/jsonassert/JsonAssertUnitTest.java @@ -78,10 +78,10 @@ public class JsonAssertUnitTest { @Test public void givenArray_whenComparing_thenOrderMustMatchForStrict() throws JSONException { - String result = "[Alex, Barbera, Charlie, Xavier]"; - JSONAssert.assertEquals("[Charlie, Alex, Xavier, Barbera]", result, JSONCompareMode.LENIENT); - JSONAssert.assertEquals("[Alex, Barbera, Charlie, Xavier]", result, JSONCompareMode.STRICT); - JSONAssert.assertNotEquals("[Charlie, Alex, Xavier, Barbera]", result, JSONCompareMode.STRICT); + String result = "[Alex, Barbera, Charlie, Wolf]"; + JSONAssert.assertEquals("[Charlie, Alex, Wolf, Barbera]", result, JSONCompareMode.LENIENT); + JSONAssert.assertEquals("[Alex, Barbera, Charlie, Wolf]", result, JSONCompareMode.STRICT); + JSONAssert.assertNotEquals("[Charlie, Alex, Wolf, Barbera]", result, JSONCompareMode.STRICT); } @Test @@ -94,7 +94,7 @@ public class JsonAssertUnitTest { @Test public void whenComparingSizeOfArray_thenPass() throws JSONException { - String names = "{names:[Alex, Barbera, Charlie, Xavier]}"; + String names = "{names:[Alex, Barbera, Charlie, Wolf]}"; JSONAssert.assertEquals("{names:[4]}", names, new ArraySizeComparator(JSONCompareMode.LENIENT)); } diff --git a/libraries-testing/src/test/resources/dbunit/data.xml b/libraries-testing/src/test/resources/dbunit/data.xml index 290cc36890..4865dec54c 100644 --- a/libraries-testing/src/test/resources/dbunit/data.xml +++ b/libraries-testing/src/test/resources/dbunit/data.xml @@ -1,6 +1,6 @@ - + diff --git a/libraries-testing/src/test/resources/dbunit/items_exp_rename_no_produced.xml b/libraries-testing/src/test/resources/dbunit/items_exp_rename_no_produced.xml index b42d3804fa..4f14b17113 100644 --- a/libraries-testing/src/test/resources/dbunit/items_exp_rename_no_produced.xml +++ b/libraries-testing/src/test/resources/dbunit/items_exp_rename_no_produced.xml @@ -1,6 +1,6 @@ - + diff --git a/libraries-testing/src/test/resources/dbunit/users.xml b/libraries-testing/src/test/resources/dbunit/users.xml index 9ac3909bc5..f04943c4cc 100644 --- a/libraries-testing/src/test/resources/dbunit/users.xml +++ b/libraries-testing/src/test/resources/dbunit/users.xml @@ -1,6 +1,6 @@ - + diff --git a/libraries-testing/src/test/resources/dbunit/users_exp_delete.xml b/libraries-testing/src/test/resources/dbunit/users_exp_delete.xml index 2fe97ae6f6..20a2f2f1a7 100644 --- a/libraries-testing/src/test/resources/dbunit/users_exp_delete.xml +++ b/libraries-testing/src/test/resources/dbunit/users_exp_delete.xml @@ -1,5 +1,5 @@ - + diff --git a/libraries-testing/src/test/resources/dbunit/users_exp_rename.xml b/libraries-testing/src/test/resources/dbunit/users_exp_rename.xml index 95682118bb..1ab6cf53b8 100644 --- a/libraries-testing/src/test/resources/dbunit/users_exp_rename.xml +++ b/libraries-testing/src/test/resources/dbunit/users_exp_rename.xml @@ -1,6 +1,6 @@ - + From 902bb5308945cc37b148ee630832071209ce9361 Mon Sep 17 00:00:00 2001 From: Marius Catalin Munteanu Date: Wed, 11 Mar 2020 10:56:13 +0200 Subject: [PATCH 023/194] [BAEL-3011] Accesing Spring MVC Data from Thymeleaf - Code example for https://jira.baeldung.com/browse/BAEL-3012 --- .../thymeleaf/mvcdata/BeanConfig.java | 14 ++++ .../thymeleaf/mvcdata/EmailController.java | 63 ++++++++++++++++ .../mvcdata/repository/EmailData.java | 48 +++++++++++++ .../templates/mvcdata/email-bean-data.html | 14 ++++ .../mvcdata/email-model-attributes.html | 16 +++++ .../mvcdata/email-request-parameters.html | 20 ++++++ .../mvcdata/email-servlet-context.html | 14 ++++ .../mvcdata/email-session-attributes.html | 14 ++++ .../mvcdata/EmailControllerUnitTest.java | 72 +++++++++++++++++++ 9 files changed, 275 insertions(+) create mode 100644 spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java create mode 100644 spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java create mode 100644 spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java create mode 100644 spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-bean-data.html create mode 100644 spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-model-attributes.html create mode 100644 spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-request-parameters.html create mode 100644 spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-servlet-context.html create mode 100644 spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-session-attributes.html create mode 100644 spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java new file mode 100644 index 0000000000..19f0101cf2 --- /dev/null +++ b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java @@ -0,0 +1,14 @@ +package com.baeldung.thymeleaf.mvcdata; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.baeldung.thymeleaf.mvcdata.repository.EmailData; + +@Configuration +public class BeanConfig { + @Bean + public EmailData emailData() { + return new EmailData(); + } +} diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java new file mode 100644 index 0000000000..1bfe3f3428 --- /dev/null +++ b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java @@ -0,0 +1,63 @@ +package com.baeldung.thymeleaf.mvcdata; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpSession; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestParam; + +import com.baeldung.thymeleaf.mvcdata.repository.EmailData; + +@Controller +public class EmailController { + private EmailData emailData = new EmailData(); + private ServletContext servletContext; + + public EmailController(ServletContext servletContext) { + this.servletContext = servletContext; + } + + @GetMapping(value = "/email/modelattributes") + public String emailModel(Model model) { + model.addAttribute("emaildata", emailData); + return "mvcdata/email-model-attributes"; + } + + @ModelAttribute("emailModelAttribute") + EmailData emailModelAttribute() { + return emailData; + } + + @GetMapping(value = "/email/requestparameters") + public String emailRequestParameters( + @RequestParam(value = "emailsubject") String emailSubject, + @RequestParam(value = "emailcontent") String emailContent, + @RequestParam(value = "emailaddress") String emailAddress1, + @RequestParam(value = "emailaddress") String emailAddress2, + @RequestParam(value = "emaillocale") String emailLocale) { + return "mvcdata/email-request-parameters"; + } + + @GetMapping("/email/sessionattributes") + public String emailSessionAttributes(HttpSession httpSession) { + httpSession.setAttribute("emaildata", emailData); + return "mvcdata/email-session-attributes"; + } + + @GetMapping("/email/servletcontext") + public String emailServletContext() { + servletContext.setAttribute("emailsubject", emailData.getEmailSubject()); + servletContext.setAttribute("emailcontent", emailData.getEmailBody()); + servletContext.setAttribute("emailaddress", emailData.getEmailAddress1()); + servletContext.setAttribute("emaillocale", emailData.getEmailLocale()); + return "mvcdata/email-servlet-context"; + } + + @GetMapping("/email/beandata") + public String emailBeanData() { + return "mvcdata/email-bean-data"; + } +} diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java new file mode 100644 index 0000000000..9dc25bdaa7 --- /dev/null +++ b/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java @@ -0,0 +1,48 @@ +package com.baeldung.thymeleaf.mvcdata.repository; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class EmailData implements Serializable { + private String emailSubject; + private String emailBody; + private String emailLocale; + private String emailAddress1; + private String emailAddress2; + + public EmailData() { + this.emailSubject = "You have received a new message"; + this.emailBody = "Good morning !"; + this.emailLocale = "en-US"; + this.emailAddress1 = "jhon.doe@example.com"; + this.emailAddress2 = "mark.jakob@example.com"; + } + + public String getEmailSubject() { + return this.emailSubject; + } + + public String getEmailBody() { + return this.emailBody; + } + + public String getEmailLocale() { + return this.emailLocale; + } + + public String getEmailAddress1() { + return this.emailAddress1; + } + + public String getEmailAddress2() { + return this.emailAddress2; + } + + public List getEmailAddresses() { + List emailAddresses = new ArrayList<>(); + emailAddresses.add(getEmailAddress1()); + emailAddresses.add(getEmailAddress2()); + return emailAddresses; + } +} diff --git a/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-bean-data.html b/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-bean-data.html new file mode 100644 index 0000000000..59073b51c6 --- /dev/null +++ b/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-bean-data.html @@ -0,0 +1,14 @@ + + + +

Subject

+

Subject

+

Content

+

Body

+

Email address

+

Email address

+

Language

+

Language

+ + \ No newline at end of file diff --git a/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-model-attributes.html b/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-model-attributes.html new file mode 100644 index 0000000000..caf136383a --- /dev/null +++ b/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-model-attributes.html @@ -0,0 +1,16 @@ + + + +

Subject

+

Subject

+

Content

+

+

Email addresses

+

+ +

+

Language

+

+ + \ No newline at end of file diff --git a/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-request-parameters.html b/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-request-parameters.html new file mode 100644 index 0000000000..8bcd3e1c62 --- /dev/null +++ b/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-request-parameters.html @@ -0,0 +1,20 @@ + + + +

Subject

+

Subject

+

Content

+

+

Email addresses

+

+ +

+

Email address 1

+

+

Email address 2

+

+

Language

+

+ + \ No newline at end of file diff --git a/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-servlet-context.html b/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-servlet-context.html new file mode 100644 index 0000000000..b07573047e --- /dev/null +++ b/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-servlet-context.html @@ -0,0 +1,14 @@ + + + +

Subject

+

+

Content

+

+

Email address

+

+

Language

+

+ + \ No newline at end of file diff --git a/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-session-attributes.html b/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-session-attributes.html new file mode 100644 index 0000000000..9227171fc6 --- /dev/null +++ b/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-session-attributes.html @@ -0,0 +1,14 @@ + + + +

Subject

+

+

Content

+

+

Email address

+

+

Language

+

+ + \ No newline at end of file diff --git a/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java b/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java new file mode 100644 index 0000000000..5e1190e174 --- /dev/null +++ b/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.thymeleaf.mvcdata; + +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; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import com.baeldung.thymeleaf.mvcdata.repository.EmailData; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc(printOnlyOnFailure = false) +public class EmailControllerUnitTest { + + EmailData emailData = new EmailData(); + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenCallModelAttributes_thenReturnEmailData() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/email/modelattributes")) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("You have received a new message"))); + } + + @Test + public void whenCallRequestParameters_thenReturnEmailData() throws Exception { + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("emailsubject", emailData.getEmailSubject()); + params.add("emailcontent", emailData.getEmailBody()); + params.add("emailaddress", emailData.getEmailAddress1()); + params.add("emailaddress", emailData.getEmailAddress2()); + params.add("emaillocale", emailData.getEmailLocale()); + mockMvc.perform(MockMvcRequestBuilders.get("/email/requestparameters") + .params(params)) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("en-US"))); + } + + @Test + public void whenCallSessionAttributes_thenReturnEmailData() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/email/sessionattributes")) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("Good morning !"))); + } + + @Test + public void whenCallServletContext_thenReturnEmailData() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/email/servletcontext")) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("jhon.doe@example.com"))); + } + + @Test + public void whenCallBeanData_thenReturnEmailData() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/email/beandata")) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("jhon.doe@example.com"))); + } + +} From ba65e099896cce714f3616329971d58c47dfa99d Mon Sep 17 00:00:00 2001 From: gindex Date: Sat, 28 Mar 2020 19:01:54 +0100 Subject: [PATCH 024/194] Add blocking and non-blocking mono examples Add article reference Fix url --- reactor-core/README.md | 1 + .../java/com/baeldung/mono/MonoUnitTest.java | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 reactor-core/src/test/java/com/baeldung/mono/MonoUnitTest.java diff --git a/reactor-core/README.md b/reactor-core/README.md index e3cca35f86..f2dbd77981 100644 --- a/reactor-core/README.md +++ b/reactor-core/README.md @@ -7,3 +7,4 @@ This module contains articles about Reactor Core. - [Intro To Reactor Core](https://www.baeldung.com/reactor-core) - [Combining Publishers in Project Reactor](https://www.baeldung.com/reactor-combine-streams) - [Programmatically Creating Sequences with Project Reactor](https://www.baeldung.com/flux-sequences-reactor) +- [How To Get String From Mono In Reactive Java](http://baeldung.com/string-from-mono/) \ No newline at end of file diff --git a/reactor-core/src/test/java/com/baeldung/mono/MonoUnitTest.java b/reactor-core/src/test/java/com/baeldung/mono/MonoUnitTest.java new file mode 100644 index 0000000000..b493cd1159 --- /dev/null +++ b/reactor-core/src/test/java/com/baeldung/mono/MonoUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.mono; + +import org.junit.Test; +import reactor.core.publisher.Mono; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.Optional; + +import static org.junit.Assert.assertEquals; + +public class MonoUnitTest { + @Test + public void whenMonoProducesString_thenBlockAndConsume() { + String expected = "hello world!"; + + String result1 = Mono.just(expected).block(); + assertEquals(expected, result1); + + String result2 = Mono.just(expected).block(Duration.of(1000, ChronoUnit.MILLIS)); + assertEquals(expected, result2); + + Optional result3 = Mono.empty().blockOptional(); + assertEquals(Optional.empty(), result3); + } + + @Test + public void whenMonoProducesString_thenConsumeNonBlocking() { + String expected = "hello world!"; + + Mono.just(expected) + .doOnNext(result -> assertEquals(expected, result)) + .subscribe(); + + Mono.just(expected) + .subscribe(result -> assertEquals(expected, result)); + + } +} From 6d60aad5f9487c774e364b09b8446b3c23006732 Mon Sep 17 00:00:00 2001 From: Aitor Cuesta Date: Sun, 5 Apr 2020 12:51:27 +0200 Subject: [PATCH 025/194] BAEL-3075 - Initial commit --- .../spring-boot-persistence-2/README.md | 1 + .../spring-boot-persistence-2/pom.xml | 60 +++++++++++++++++-- .../SpringOraclePoolingApplication.java | 29 +++++++++ .../configuration/C3P0Configuration.java | 27 +++++++++ .../configuration/OracleConfiguration.java | 27 +++++++++ .../configuration/OracleUCPConfiguration.java | 30 ++++++++++ .../controller/BookstoreController.java | 45 ++++++++++++++ .../spring/oracle/pooling/entity/Book.java | 45 ++++++++++++++ .../pooling/exception/BookstoreException.java | 10 ++++ .../pooling/repository/BookRepository.java | 9 +++ ...pplication-oracle-pooling-basic.properties | 27 +++++++++ .../src/main/resources/application.yml | 10 +++- .../SpringBootJdbiApplicationUnitTest.java | 4 +- ...gOraclePoolingApplicationC3P0LiveTest.java | 27 +++++++++ ...clePoolingApplicationHikariCPLiveTest.java | 27 +++++++++ ...raclePoolingApplicationOracleLiveTest.java | 27 +++++++++ ...lePoolingApplicationOracleUCPLiveTest.java | 27 +++++++++ 17 files changed, 424 insertions(+), 8 deletions(-) create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplication.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/C3P0Configuration.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/controller/BookstoreController.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/entity/Book.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/exception/BookstoreException.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/repository/BookRepository.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/main/resources/application-oracle-pooling-basic.properties create mode 100644 persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java create mode 100644 persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java diff --git a/persistence-modules/spring-boot-persistence-2/README.md b/persistence-modules/spring-boot-persistence-2/README.md index 5d171fb2ca..a74bf7ff02 100644 --- a/persistence-modules/spring-boot-persistence-2/README.md +++ b/persistence-modules/spring-boot-persistence-2/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Using JDBI with Spring Boot](https://www.baeldung.com/spring-boot-jdbi) +- [Oracle Connection Pooling With Spring](https://www.baeldung.com/oracle-connection-pooling-with-spring) \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-2/pom.xml b/persistence-modules/spring-boot-persistence-2/pom.xml index 048dd45c7f..8f76bce1b3 100644 --- a/persistence-modules/spring-boot-persistence-2/pom.xml +++ b/persistence-modules/spring-boot-persistence-2/pom.xml @@ -41,10 +41,20 @@ - - org.springframework.boot - spring-boot-starter-jdbc - + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + net.bytebuddy + byte-buddy + org.jdbi @@ -82,6 +92,47 @@ spring-boot-starter-test test + + + com.oracle + ojdbc8 + 12.2.0.1 + system + ${basedir}/lib/ojdbc8.jar + + + + com.oracle + ucp + 12.2.0.1 + system + ${basedir}/lib/ucp.jar + + + + com.oracle + ons + 12.2.0.1 + system + ${basedir}/lib/ons.jar + + + + com.mchange + c3p0 + ${c3p0.version} + + + + org.apache.commons + commons-dbcp2 + + + + org.apache.tomcat + tomcat-jdbc + + @@ -96,6 +147,7 @@ 3.9.1 2.1.8.RELEASE + 0.9.5.2 diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplication.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplication.java new file mode 100644 index 0000000000..fa7f884112 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplication.java @@ -0,0 +1,29 @@ +package com.baeldung.spring.oracle.pooling; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import lombok.extern.slf4j.Slf4j; + +@SpringBootApplication +@Slf4j +public class SpringOraclePoolingApplication implements CommandLineRunner{ + + @Autowired + private DataSource dataSource; + + public static void main(String[] args) { + SpringApplication.run(SpringOraclePoolingApplication.class, args); + } + + @Override + public void run(String... args) throws Exception { + log.info("Connection Polling datasource : "+ dataSource); + + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/C3P0Configuration.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/C3P0Configuration.java new file mode 100644 index 0000000000..f357924807 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/C3P0Configuration.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.oracle.pooling.configuration; + +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +import com.mchange.v2.c3p0.ComboPooledDataSource; + +@Configuration +@Profile("c3p0") +public class C3P0Configuration { + + @Bean + public DataSource dataSource() throws SQLException { + ComboPooledDataSource dataSource = new ComboPooledDataSource(); + dataSource.setUser("books"); + dataSource.setPassword("books"); + dataSource.setJdbcUrl("jdbc:oracle:thin:@//localhost:11521/ORCLPDB1"); + dataSource.setMinPoolSize(5); + dataSource.setMaxPoolSize(10); + return dataSource; + } +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java new file mode 100644 index 0000000000..327374cb54 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.oracle.pooling.configuration; + +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +import oracle.jdbc.pool.OracleDataSource; + +@Configuration +@Profile("oracle") +public class OracleConfiguration { + + @Bean + public DataSource dataSource() throws SQLException { + OracleDataSource dataSource = new OracleDataSource(); + dataSource.setUser("books"); + dataSource.setPassword("books"); + dataSource.setURL("jdbc:oracle:thin:@//localhost:11521/ORCLPDB1"); + dataSource.setFastConnectionFailoverEnabled(true); + dataSource.setImplicitCachingEnabled(true); + return dataSource; + } +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java new file mode 100644 index 0000000000..67b4b40712 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java @@ -0,0 +1,30 @@ +package com.baeldung.spring.oracle.pooling.configuration; + +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +import oracle.ucp.jdbc.PoolDataSource; +import oracle.ucp.jdbc.PoolDataSourceFactory; + +@Configuration +@Profile("oracle-ucp") +public class OracleUCPConfiguration { + + @Bean + public DataSource dataSource() throws SQLException { + PoolDataSource dataSource = PoolDataSourceFactory.getPoolDataSource(); + dataSource.setUser("books"); + dataSource.setPassword("books"); + dataSource.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource"); + dataSource.setURL("jdbc:oracle:thin:@//localhost:11521/ORCLPDB1"); + dataSource.setFastConnectionFailoverEnabled(true); + dataSource.setInitialPoolSize(5); + dataSource.setMaxPoolSize(10); + return dataSource; + } +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/controller/BookstoreController.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/controller/BookstoreController.java new file mode 100644 index 0000000000..49b998bfb9 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/controller/BookstoreController.java @@ -0,0 +1,45 @@ +package com.baeldung.spring.oracle.pooling.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.spring.oracle.pooling.entity.Book; +import com.baeldung.spring.oracle.pooling.exception.BookstoreException; +import com.baeldung.spring.oracle.pooling.repository.BookRepository; + +@RestController +@RequestMapping("/books") +public class BookstoreController { + + @Autowired + private BookRepository repository; + + @GetMapping(value = "/hello") + public String sayHello() { + return "Hello"; + } + + @GetMapping("/all") + public List findAll() { + return repository.findAll(); + } + + @PostMapping("/create") + public Book newBook(@RequestBody Book newBook) { + return repository.save(newBook); + } + + @GetMapping("/get/{id}") + public Book findOne(@PathVariable Long id) throws BookstoreException { + return repository.findById(id) + .orElseThrow(BookstoreException::new); + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/entity/Book.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/entity/Book.java new file mode 100644 index 0000000000..fb2c3fcf6a --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/entity/Book.java @@ -0,0 +1,45 @@ +package com.baeldung.spring.oracle.pooling.entity; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Book { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + public Book() { + } + + public Book(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Book [id=" + id + ", name=" + name + "]"; + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/exception/BookstoreException.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/exception/BookstoreException.java new file mode 100644 index 0000000000..d2fb399ab3 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/exception/BookstoreException.java @@ -0,0 +1,10 @@ +package com.baeldung.spring.oracle.pooling.exception; + +public class BookstoreException extends Exception{ + + /** + * + */ + private static final long serialVersionUID = 1L; + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/repository/BookRepository.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/repository/BookRepository.java new file mode 100644 index 0000000000..a50a1b24a4 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/repository/BookRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.spring.oracle.pooling.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.spring.oracle.pooling.entity.Book; + +public interface BookRepository extends JpaRepository{ + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/resources/application-oracle-pooling-basic.properties b/persistence-modules/spring-boot-persistence-2/src/main/resources/application-oracle-pooling-basic.properties new file mode 100644 index 0000000000..9a1c7fc89d --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/resources/application-oracle-pooling-basic.properties @@ -0,0 +1,27 @@ +logging.level.root=INFO + +# OracleDB connection settings +spring.datasource.url=jdbc:oracle:thin:@//localhost:11521/ORCLPDB1 +spring.datasource.username=books +spring.datasource.password=books +spring.datasource.driver-class-name=oracle.jdbc.OracleDriver + +# Comment this line for standard Spring Boot default choosing algorithm +#spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource + +# HikariCP settings +spring.datasource.hikari.minimumIdle=5 +spring.datasource.hikari.maximumPoolSize=20 +spring.datasource.hikari.idleTimeout=30000 +spring.datasource.hikari.maxLifetime=2000000 +spring.datasource.hikari.connectionTimeout=30000 +spring.datasource.hikari.poolName=HikariPoolBooks + +# Tomcat settings +spring.datasource.tomcat.maxActive=15 +spring.datasource.tomcat.minIdle=5 + +# JPA settings +spring.jpa.database-platform=org.hibernate.dialect.Oracle12cDialect +spring.jpa.hibernate.use-new-id-generator-mappings=false +spring.jpa.hibernate.ddl-auto=create \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-2/src/main/resources/application.yml b/persistence-modules/spring-boot-persistence-2/src/main/resources/application.yml index 8b13789179..4b792fd5dc 100644 --- a/persistence-modules/spring-boot-persistence-2/src/main/resources/application.yml +++ b/persistence-modules/spring-boot-persistence-2/src/main/resources/application.yml @@ -1 +1,9 @@ - +# Available profiles +# - none for no profile +# - oracle-pooling-basic - Oracle database with HikariCP. Loads configuration from application-oracle-pooling-basic.properties +# - oracle - Uses OracleDataSource. This profile also needs "oracle-pooling-basic" +# - oracle-ucp - Uses PoolDataSource. This profile also needs "oracle-pooling-basic" +# - c3p0 - Uses ComboPooledDataSource. This profile also needs "oracle-pooling-basic" +spring: + profiles: + active: none \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationUnitTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationUnitTest.java index e4b623ee2b..93083f6c4c 100644 --- a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationUnitTest.java +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationUnitTest.java @@ -5,10 +5,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import org.jdbi.v3.core.Jdbi; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -24,7 +22,7 @@ import com.baeldung.boot.jdbi.service.CarMakerService; import lombok.extern.slf4j.Slf4j; @RunWith(SpringRunner.class) -@SpringBootTest +@SpringBootTest(classes = {SpringBootJdbiApplication.class, JdbiConfiguration.class}) @Slf4j public class SpringBootJdbiApplicationUnitTest { diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java new file mode 100644 index 0000000000..5a2d3f2d29 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.oracle.pooling; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {SpringOraclePoolingApplication.class}) +@ActiveProfiles({"oracle-pooling-basic", "c3p0"}) +public class SpringOraclePoolingApplicationC3P0LiveTest { + + @Autowired + private DataSource dataSource; + + @Test + public void givenC3p0Configuration_thenBuildsComboPooledDataSource() { + assertTrue(dataSource instanceof com.mchange.v2.c3p0.ComboPooledDataSource); + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java new file mode 100644 index 0000000000..ab8fc1e121 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.oracle.pooling; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {SpringOraclePoolingApplication.class}) +@ActiveProfiles("oracle-pooling-basic") +public class SpringOraclePoolingApplicationHikariCPLiveTest { + + @Autowired + private DataSource dataSource; + + @Test + public void givenHikariCPConfiguration_thenBuildsHikariCP() { + assertTrue(dataSource instanceof com.zaxxer.hikari.HikariDataSource); + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java new file mode 100644 index 0000000000..229375dadd --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.oracle.pooling; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {SpringOraclePoolingApplication.class}) +@ActiveProfiles({"oracle-pooling-basic", "oracle"}) +public class SpringOraclePoolingApplicationOracleLiveTest { + + @Autowired + private DataSource dataSource; + + @Test + public void givenOracleConfiguration_thenBuildsOracleDataSource() { + assertTrue(dataSource instanceof oracle.jdbc.pool.OracleDataSource); + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java new file mode 100644 index 0000000000..4fb6aa6bae --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.oracle.pooling; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import javax.sql.DataSource; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {SpringOraclePoolingApplication.class}) +@ActiveProfiles({"oracle-pooling-basic", "oracle-ucp"}) +public class SpringOraclePoolingApplicationOracleUCPLiveTest { + + @Autowired + private DataSource dataSource; + + @Test + public void givenOracleUCPConfiguration_thenBuildsOraclePoolDataSource() { + assertTrue(dataSource instanceof oracle.ucp.jdbc.PoolDataSource); + } + +} From a3c69eba43cd3e32dfa6d78532736a7211e2f824 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Sun, 22 Mar 2020 18:36:02 +0100 Subject: [PATCH 026/194] [BAEL-2808] Added tests for physical naming strategies --- .../spring-data-jpa-4/create.sql | 2 + .../default-naming-strategy-ddl.sql | 1 + persistence-modules/spring-data-jpa-4/pom.xml | 5 ++ .../com/baeldung/namingstrategy/Person.java | 36 ++++++++ .../namingstrategy/PersonRepository.java | 6 ++ .../QuotedLowerCaseNamingStrategy.java | 12 +++ ...DataJpaTableAndColumnNamesApplication.java | 7 ++ .../UnquotedLowerCaseNamingStrategy.java | 12 +++ ...owerCaseNamingStrategyIntegrationTest.java | 78 +++++++++++++++++ ...PhysicalNamingStrategyIntegrationTest.java | 82 ++++++++++++++++++ ...owerCaseNamingStrategyIntegrationTest.java | 83 +++++++++++++++++++ ...oted-lower-case-naming-strategy.properties | 9 ++ ...spring-physical-naming-strategy.properties | 9 ++ ...oted-lower-case-naming-strategy.properties | 9 ++ .../upper-case-naming-strategy-ddl.sql | 1 + 15 files changed, 352 insertions(+) create mode 100644 persistence-modules/spring-data-jpa-4/create.sql create mode 100644 persistence-modules/spring-data-jpa-4/default-naming-strategy-ddl.sql create mode 100644 persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/Person.java create mode 100644 persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/PersonRepository.java create mode 100644 persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategy.java create mode 100644 persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/SpringDataJpaTableAndColumnNamesApplication.java create mode 100644 persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategy.java create mode 100644 persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyIntegrationTest.java create mode 100644 persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyIntegrationTest.java create mode 100644 persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyIntegrationTest.java create mode 100644 persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy.properties create mode 100644 persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy.properties create mode 100644 persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy.properties create mode 100644 persistence-modules/spring-data-jpa-4/upper-case-naming-strategy-ddl.sql diff --git a/persistence-modules/spring-data-jpa-4/create.sql b/persistence-modules/spring-data-jpa-4/create.sql new file mode 100644 index 0000000000..1bbe1640a7 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/create.sql @@ -0,0 +1,2 @@ +create table PERSON (ID int8 not null, FIRST_NAME varchar(255), LAST_NAME varchar(255), primary key (ID)) +create table person (id int8 not null, first_name varchar(255), last_name varchar(255), primary key (id)) diff --git a/persistence-modules/spring-data-jpa-4/default-naming-strategy-ddl.sql b/persistence-modules/spring-data-jpa-4/default-naming-strategy-ddl.sql new file mode 100644 index 0000000000..34d5bd1867 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/default-naming-strategy-ddl.sql @@ -0,0 +1 @@ +create table person (id int8 not null, firstname varchar(255), last_name varchar(255), primary key (id)) diff --git a/persistence-modules/spring-data-jpa-4/pom.xml b/persistence-modules/spring-data-jpa-4/pom.xml index 8a476012c7..71fc21527f 100644 --- a/persistence-modules/spring-data-jpa-4/pom.xml +++ b/persistence-modules/spring-data-jpa-4/pom.xml @@ -33,6 +33,11 @@ mysql-connector-java + + org.postgresql + postgresql + + com.h2database h2 diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/Person.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/Person.java new file mode 100644 index 0000000000..c3e7f50403 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/Person.java @@ -0,0 +1,36 @@ +package com.baeldung.namingstrategy; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class Person { + @Id + private Long id; + + @Column(name = "FIRSTNAME") + private String firstName; + + private String lastName; + + public Person() {} + + public Person(Long id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public Long id() { + return id; + } + + public String firstName() { + return firstName; + } + + public String lastName() { + return lastName; + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/PersonRepository.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/PersonRepository.java new file mode 100644 index 0000000000..3c7c25bbcb --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/PersonRepository.java @@ -0,0 +1,6 @@ +package com.baeldung.namingstrategy; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PersonRepository extends JpaRepository { +} diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategy.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategy.java new file mode 100644 index 0000000000..16b01e50e3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategy.java @@ -0,0 +1,12 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.boot.model.naming.Identifier; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; + +public class QuotedLowerCaseNamingStrategy extends SpringPhysicalNamingStrategy { + @Override + protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) { + return new Identifier(name.toLowerCase(), true); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/SpringDataJpaTableAndColumnNamesApplication.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/SpringDataJpaTableAndColumnNamesApplication.java new file mode 100644 index 0000000000..09aaf12b60 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/SpringDataJpaTableAndColumnNamesApplication.java @@ -0,0 +1,7 @@ +package com.baeldung.namingstrategy; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringDataJpaTableAndColumnNamesApplication { +} diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategy.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategy.java new file mode 100644 index 0000000000..69e96aee27 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategy.java @@ -0,0 +1,12 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.boot.model.naming.Identifier; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; + +public class UnquotedLowerCaseNamingStrategy extends SpringPhysicalNamingStrategy { + @Override + protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) { + return new Identifier(name.toLowerCase(), false); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyIntegrationTest.java new file mode 100644 index 0000000000..ffa282da72 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyIntegrationTest.java @@ -0,0 +1,78 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) +@TestPropertySource("quoted-lower-case-naming-strategy.properties") +class QuotedLowerCaseNamingStrategyIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PersonRepository personRepository; + + @BeforeEach + void insertPeople() { + personRepository.saveAll(Arrays.asList( + new Person(1L, "John", "Doe"), + new Person(2L, "Jane", "Doe"), + new Person(3L, "Ted", "Mosby") + )); + } + + @ParameterizedTest + @ValueSource(strings = {"person", "PERSON", "Person"}) + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenException(String tableName) { + Query query = entityManager.createNativeQuery("select * from " + tableName); + + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + @Test + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { + Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + @Test + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { + Query query = entityManager.createNativeQuery("select * from \"person\""); + + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + public Person fromDatabase(Object databaseRow) { + Object[] typedDatabaseRow = (Object[]) databaseRow; + + return new Person( + ((BigInteger) typedDatabaseRow[0]).longValue(), + (String) typedDatabaseRow[1], + (String) typedDatabaseRow[2] + ); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyIntegrationTest.java new file mode 100644 index 0000000000..8ad59fe2db --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyIntegrationTest.java @@ -0,0 +1,82 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) +@TestPropertySource("spring-physical-naming-strategy.properties") +class SpringPhysicalNamingStrategyIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PersonRepository personRepository; + + @BeforeEach + void insertPeople() { + personRepository.saveAll(Arrays.asList( + new Person(1L, "John", "Doe"), + new Person(2L, "Jane", "Doe"), + new Person(3L, "Ted", "Mosby") + )); + } + + @ParameterizedTest + @ValueSource(strings = {"person", "PERSON", "Person"}) + void givenPeopleAndDefaultNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { + Query query = entityManager.createNativeQuery("select * from " + tableName); + + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndDefaultNamingStrategyAndH2Database_whenQueryPersonQuotedUpperCase_thenResult() { + Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndDefaultNamingStrategyAndH2Database_whenQueryPersonQuotedLowerCase_thenException() { + Query query = entityManager.createNativeQuery("select * from \"person\""); + + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + public Person fromDatabase(Object databaseRow) { + Object[] typedDatabaseRow = (Object[]) databaseRow; + + return new Person( + ((BigInteger) typedDatabaseRow[0]).longValue(), + (String) typedDatabaseRow[1], + (String) typedDatabaseRow[2] + ); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyIntegrationTest.java new file mode 100644 index 0000000000..2d84a17526 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyIntegrationTest.java @@ -0,0 +1,83 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import java.math.BigInteger; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) +@TestPropertySource("unquoted-lower-case-naming-strategy.properties") +class UnquotedLowerCaseNamingStrategyIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PersonRepository personRepository; + + @BeforeEach + void insertPeople() { + personRepository.saveAll(Arrays.asList( + new Person(1L, "John", "Doe"), + new Person(2L, "Jane", "Doe"), + new Person(3L, "Ted", "Mosby") + )); + } + + @ParameterizedTest + @ValueSource(strings = {"person", "PERSON", "Person"}) + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenException(String tableName) { + Query query = entityManager.createNativeQuery("select * from " + tableName); + + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { + Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { + Query query = entityManager.createNativeQuery("select * from \"person\""); + + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + public Person fromDatabase(Object databaseRow) { + Object[] typedDatabaseRow = (Object[]) databaseRow; + + return new Person( + ((BigInteger) typedDatabaseRow[0]).longValue(), + (String) typedDatabaseRow[1], + (String) typedDatabaseRow[2] + ); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy.properties new file mode 100644 index 0000000000..dce43e2da5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:h2:mem:custom-lower-case-strategy +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.QuotedLowerCaseNamingStrategy +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy.properties new file mode 100644 index 0000000000..a8ba1a3e4d --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:h2:mem:spring-strategy +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=default-naming-strategy-ddl.sql \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy.properties new file mode 100644 index 0000000000..63f400db0b --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:h2:mem:custom-lower-case-strategy +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.UnquotedLowerCaseNamingStrategy +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/upper-case-naming-strategy-ddl.sql b/persistence-modules/spring-data-jpa-4/upper-case-naming-strategy-ddl.sql new file mode 100644 index 0000000000..b26697ac66 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/upper-case-naming-strategy-ddl.sql @@ -0,0 +1 @@ +create table "PERSON" ("ID" int8 not null, "FIRSTNAME" varchar(255), "LAST_NAME" varchar(255), primary key ("ID")) From aebba04be7812a3ba020cfddfbc38da245dca10b Mon Sep 17 00:00:00 2001 From: dupirefr Date: Tue, 24 Mar 2020 08:09:31 +0100 Subject: [PATCH 027/194] [BAEL-2808] Added a few tests to illustrate my problem --- .../QuotedUpperCaseNamingStrategy.java | 12 +++ .../UnquotedUpperCaseNamingStrategy.java | 12 +++ ...rCaseNamingStrategyH2IntegrationTest.java} | 5 +- ...NamingStrategyPostgresIntegrationTest.java | 85 +++++++++++++++++++ ...erCaseNamingStrategyH2IntegrationTest.java | 85 +++++++++++++++++++ ...NamingStrategyPostgresIntegrationTest.java | 81 ++++++++++++++++++ ...sicalNamingStrategyH2IntegrationTest.java} | 11 ++- ...NamingStrategyPostgresIntegrationTest.java | 85 +++++++++++++++++++ ...rCaseNamingStrategyH2IntegrationTest.java} | 11 ++- ...NamingStrategyPostgresIntegrationTest.java | 85 +++++++++++++++++++ ...erCaseNamingStrategyH2IntegrationTest.java | 85 +++++++++++++++++++ ...NamingStrategyPostgresIntegrationTest.java | 85 +++++++++++++++++++ ...ase-naming-strategy-on-postgres.properties | 9 ++ ...oted-lower-case-naming-strategy.properties | 4 +- ...ase-naming-strategy-on-postgres.properties | 9 ++ ...oted-upper-case-naming-strategy.properties | 9 ++ ...cal-naming-strategy-on-postgres.properties | 9 ++ ...spring-physical-naming-strategy.properties | 2 +- ...ase-naming-strategy-on-postgres.properties | 9 ++ ...oted-lower-case-naming-strategy.properties | 4 +- ...ase-naming-strategy-on-postgres.properties | 9 ++ ...oted-upper-case-naming-strategy.properties | 9 ++ 22 files changed, 701 insertions(+), 14 deletions(-) create mode 100644 persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategy.java create mode 100644 persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategy.java rename persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/{QuotedLowerCaseNamingStrategyIntegrationTest.java => QuotedLowerCaseNamingStrategyH2IntegrationTest.java} (95%) create mode 100644 persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyPostgresIntegrationTest.java create mode 100644 persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyH2IntegrationTest.java create mode 100644 persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyPostgresIntegrationTest.java rename persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/{SpringPhysicalNamingStrategyIntegrationTest.java => SpringPhysicalNamingStrategyH2IntegrationTest.java} (85%) create mode 100644 persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyPostgresIntegrationTest.java rename persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/{UnquotedLowerCaseNamingStrategyIntegrationTest.java => UnquotedLowerCaseNamingStrategyH2IntegrationTest.java} (91%) create mode 100644 persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyPostgresIntegrationTest.java create mode 100644 persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyH2IntegrationTest.java create mode 100644 persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyPostgresIntegrationTest.java create mode 100644 persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy-on-postgres.properties create mode 100644 persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-upper-case-naming-strategy-on-postgres.properties create mode 100644 persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-upper-case-naming-strategy.properties create mode 100644 persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy-on-postgres.properties create mode 100644 persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy-on-postgres.properties create mode 100644 persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-upper-case-naming-strategy-on-postgres.properties create mode 100644 persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-upper-case-naming-strategy.properties diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategy.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategy.java new file mode 100644 index 0000000000..3cb62aa5a2 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategy.java @@ -0,0 +1,12 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.boot.model.naming.Identifier; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; + +public class QuotedUpperCaseNamingStrategy extends SpringPhysicalNamingStrategy { + @Override + protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) { + return new Identifier(name.toUpperCase(), true); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategy.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategy.java new file mode 100644 index 0000000000..cb87af10f4 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategy.java @@ -0,0 +1,12 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.boot.model.naming.Identifier; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; + +public class UnquotedUpperCaseNamingStrategy extends SpringPhysicalNamingStrategy { + @Override + protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) { + return new Identifier(name.toUpperCase(), false); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyH2IntegrationTest.java similarity index 95% rename from persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyIntegrationTest.java rename to persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyH2IntegrationTest.java index ffa282da72..71a4dbda3f 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyH2IntegrationTest.java @@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) @TestPropertySource("quoted-lower-case-naming-strategy.properties") -class QuotedLowerCaseNamingStrategyIntegrationTest { +class QuotedLowerCaseNamingStrategyH2IntegrationTest { @PersistenceContext private EntityManager entityManager; @@ -45,6 +45,7 @@ class QuotedLowerCaseNamingStrategyIntegrationTest { void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenException(String tableName) { Query query = entityManager.createNativeQuery("select * from " + tableName); + // Unexpected result assertThrows(SQLGrammarException.class, query::getResultStream); } @@ -52,6 +53,7 @@ class QuotedLowerCaseNamingStrategyIntegrationTest { void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + // Expected result assertThrows(SQLGrammarException.class, query::getResultStream); } @@ -59,6 +61,7 @@ class QuotedLowerCaseNamingStrategyIntegrationTest { void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { Query query = entityManager.createNativeQuery("select * from \"person\""); + // Expected result List result = (List) query.getResultStream() .map(this::fromDatabase) .collect(Collectors.toList()); diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyPostgresIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyPostgresIntegrationTest.java new file mode 100644 index 0000000000..79c47e86e0 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyPostgresIntegrationTest.java @@ -0,0 +1,85 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) +@TestPropertySource("quoted-lower-case-naming-strategy-on-postgres.properties") +class QuotedLowerCaseNamingStrategyPostgresIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PersonRepository personRepository; + + @BeforeEach + void insertPeople() { + personRepository.saveAll(Arrays.asList( + new Person(1L, "John", "Doe"), + new Person(2L, "Jane", "Doe"), + new Person(3L, "Ted", "Mosby") + )); + } + + @ParameterizedTest + @ValueSource(strings = {"person", "PERSON", "Person"}) + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { + Query query = entityManager.createNativeQuery("select * from " + tableName); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { + Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + + // Expected result + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + @Test + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { + Query query = entityManager.createNativeQuery("select * from \"person\""); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + public Person fromDatabase(Object databaseRow) { + Object[] typedDatabaseRow = (Object[]) databaseRow; + + return new Person( + ((BigInteger) typedDatabaseRow[0]).longValue(), + (String) typedDatabaseRow[1], + (String) typedDatabaseRow[2] + ); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyH2IntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyH2IntegrationTest.java new file mode 100644 index 0000000000..f819327a5c --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyH2IntegrationTest.java @@ -0,0 +1,85 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) +@TestPropertySource("quoted-upper-case-naming-strategy.properties") +class QuotedUpperCaseNamingStrategyH2IntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PersonRepository personRepository; + + @BeforeEach + void insertPeople() { + personRepository.saveAll(Arrays.asList( + new Person(1L, "John", "Doe"), + new Person(2L, "Jane", "Doe"), + new Person(3L, "Ted", "Mosby") + )); + } + + @ParameterizedTest + @ValueSource(strings = {"person", "PERSON", "Person"}) + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonUnquoted_thenException(String tableName) { + Query query = entityManager.createNativeQuery("select * from " + tableName); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenResult() { + Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenException() { + Query query = entityManager.createNativeQuery("select * from \"person\""); + + // Expected result + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + public Person fromDatabase(Object databaseRow) { + Object[] typedDatabaseRow = (Object[]) databaseRow; + + return new Person( + ((BigInteger) typedDatabaseRow[0]).longValue(), + (String) typedDatabaseRow[1], + (String) typedDatabaseRow[2] + ); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyPostgresIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyPostgresIntegrationTest.java new file mode 100644 index 0000000000..20250a7ecb --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyPostgresIntegrationTest.java @@ -0,0 +1,81 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) +@TestPropertySource("quoted-upper-case-naming-strategy-on-postgres.properties") +class QuotedUpperCaseNamingStrategyPostgresIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PersonRepository personRepository; + + @BeforeEach + void insertPeople() { + personRepository.saveAll(Arrays.asList( + new Person(1L, "John", "Doe"), + new Person(2L, "Jane", "Doe"), + new Person(3L, "Ted", "Mosby") + )); + } + + @ParameterizedTest + @ValueSource(strings = {"person", "PERSON", "Person"}) + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { + Query query = entityManager.createNativeQuery("select * from " + tableName); + + // Unexpected result + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + @Test + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { + Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { + Query query = entityManager.createNativeQuery("select * from \"person\""); + + // Expected result + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + public Person fromDatabase(Object databaseRow) { + Object[] typedDatabaseRow = (Object[]) databaseRow; + + return new Person( + ((BigInteger) typedDatabaseRow[0]).longValue(), + (String) typedDatabaseRow[1], + (String) typedDatabaseRow[2] + ); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyH2IntegrationTest.java similarity index 85% rename from persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyIntegrationTest.java rename to persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyH2IntegrationTest.java index 8ad59fe2db..1850fea173 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyH2IntegrationTest.java @@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) @TestPropertySource("spring-physical-naming-strategy.properties") -class SpringPhysicalNamingStrategyIntegrationTest { +class SpringPhysicalNamingStrategyH2IntegrationTest { @PersistenceContext private EntityManager entityManager; @@ -42,9 +42,10 @@ class SpringPhysicalNamingStrategyIntegrationTest { @ParameterizedTest @ValueSource(strings = {"person", "PERSON", "Person"}) - void givenPeopleAndDefaultNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { + void givenPeopleAndSpringNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { Query query = entityManager.createNativeQuery("select * from " + tableName); + // Expected result List result = (List) query.getResultStream() .map(this::fromDatabase) .collect(Collectors.toList()); @@ -53,9 +54,10 @@ class SpringPhysicalNamingStrategyIntegrationTest { } @Test - void givenPeopleAndDefaultNamingStrategyAndH2Database_whenQueryPersonQuotedUpperCase_thenResult() { + void givenPeopleAndSpringNamingStrategy_whenQueryPersonQuotedUpperCase_thenResult() { Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + // Unexpected result List result = (List) query.getResultStream() .map(this::fromDatabase) .collect(Collectors.toList()); @@ -64,9 +66,10 @@ class SpringPhysicalNamingStrategyIntegrationTest { } @Test - void givenPeopleAndDefaultNamingStrategyAndH2Database_whenQueryPersonQuotedLowerCase_thenException() { + void givenPeopleAndSpringNamingStrategy_whenQueryPersonQuotedLowerCase_thenException() { Query query = entityManager.createNativeQuery("select * from \"person\""); + // Unexpected result assertThrows(SQLGrammarException.class, query::getResultStream); } diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyPostgresIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyPostgresIntegrationTest.java new file mode 100644 index 0000000000..97f2b601b0 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyPostgresIntegrationTest.java @@ -0,0 +1,85 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) +@TestPropertySource("spring-physical-naming-strategy-on-postgres.properties") +class SpringPhysicalNamingStrategyPostgresIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PersonRepository personRepository; + + @BeforeEach + void insertPeople() { + personRepository.saveAll(Arrays.asList( + new Person(1L, "John", "Doe"), + new Person(2L, "Jane", "Doe"), + new Person(3L, "Ted", "Mosby") + )); + } + + @ParameterizedTest + @ValueSource(strings = {"person", "PERSON", "Person"}) + void givenPeopleAndSpringNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { + Query query = entityManager.createNativeQuery("select * from " + tableName); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndSpringNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { + Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + + // Expected result + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + @Test + void givenPeopleAndSpringNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { + Query query = entityManager.createNativeQuery("select * from \"person\""); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + public Person fromDatabase(Object databaseRow) { + Object[] typedDatabaseRow = (Object[]) databaseRow; + + return new Person( + ((BigInteger) typedDatabaseRow[0]).longValue(), + (String) typedDatabaseRow[1], + (String) typedDatabaseRow[2] + ); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyH2IntegrationTest.java similarity index 91% rename from persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyIntegrationTest.java rename to persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyH2IntegrationTest.java index 2d84a17526..6311c42e93 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyH2IntegrationTest.java @@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) @TestPropertySource("unquoted-lower-case-naming-strategy.properties") -class UnquotedLowerCaseNamingStrategyIntegrationTest { +class UnquotedLowerCaseNamingStrategyH2IntegrationTest { @PersistenceContext private EntityManager entityManager; @@ -43,9 +43,10 @@ class UnquotedLowerCaseNamingStrategyIntegrationTest { @ParameterizedTest @ValueSource(strings = {"person", "PERSON", "Person"}) - void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenException(String tableName) { + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { Query query = entityManager.createNativeQuery("select * from " + tableName); + // Expected result List result = (List) query.getResultStream() .map(this::fromDatabase) .collect(Collectors.toList()); @@ -54,9 +55,10 @@ class UnquotedLowerCaseNamingStrategyIntegrationTest { } @Test - void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenResult() { Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + // Unexpected result List result = (List) query.getResultStream() .map(this::fromDatabase) .collect(Collectors.toList()); @@ -65,9 +67,10 @@ class UnquotedLowerCaseNamingStrategyIntegrationTest { } @Test - void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenException() { Query query = entityManager.createNativeQuery("select * from \"person\""); + // Unexpected result assertThrows(SQLGrammarException.class, query::getResultStream); } diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyPostgresIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyPostgresIntegrationTest.java new file mode 100644 index 0000000000..4e1d69ccdb --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyPostgresIntegrationTest.java @@ -0,0 +1,85 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) +@TestPropertySource("unquoted-lower-case-naming-strategy-on-postgres.properties") +class UnquotedLowerCaseNamingStrategyPostgresIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PersonRepository personRepository; + + @BeforeEach + void insertPeople() { + personRepository.saveAll(Arrays.asList( + new Person(1L, "John", "Doe"), + new Person(2L, "Jane", "Doe"), + new Person(3L, "Ted", "Mosby") + )); + } + + @ParameterizedTest + @ValueSource(strings = {"person", "PERSON", "Person"}) + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { + Query query = entityManager.createNativeQuery("select * from " + tableName); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { + Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + + // Expected result + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + @Test + void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { + Query query = entityManager.createNativeQuery("select * from \"person\""); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + public Person fromDatabase(Object databaseRow) { + Object[] typedDatabaseRow = (Object[]) databaseRow; + + return new Person( + ((BigInteger) typedDatabaseRow[0]).longValue(), + (String) typedDatabaseRow[1], + (String) typedDatabaseRow[2] + ); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyH2IntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyH2IntegrationTest.java new file mode 100644 index 0000000000..7af8001854 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyH2IntegrationTest.java @@ -0,0 +1,85 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) +@TestPropertySource("unquoted-upper-case-naming-strategy.properties") +class UnquotedUpperCaseNamingStrategyH2IntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PersonRepository personRepository; + + @BeforeEach + void insertPeople() { + personRepository.saveAll(Arrays.asList( + new Person(1L, "John", "Doe"), + new Person(2L, "Jane", "Doe"), + new Person(3L, "Ted", "Mosby") + )); + } + + @ParameterizedTest + @ValueSource(strings = {"person", "PERSON", "Person"}) + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { + Query query = entityManager.createNativeQuery("select * from " + tableName); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenResult() { + Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenException() { + Query query = entityManager.createNativeQuery("select * from \"person\""); + + // Expected result + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + public Person fromDatabase(Object databaseRow) { + Object[] typedDatabaseRow = (Object[]) databaseRow; + + return new Person( + ((BigInteger) typedDatabaseRow[0]).longValue(), + (String) typedDatabaseRow[1], + (String) typedDatabaseRow[2] + ); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyPostgresIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyPostgresIntegrationTest.java new file mode 100644 index 0000000000..0fdb05b0ee --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyPostgresIntegrationTest.java @@ -0,0 +1,85 @@ +package com.baeldung.namingstrategy; + +import org.hibernate.exception.SQLGrammarException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.TestPropertySource; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) +@TestPropertySource("unquoted-upper-case-naming-strategy-on-postgres.properties") +class UnquotedUpperCaseNamingStrategyPostgresIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PersonRepository personRepository; + + @BeforeEach + void insertPeople() { + personRepository.saveAll(Arrays.asList( + new Person(1L, "John", "Doe"), + new Person(2L, "Jane", "Doe"), + new Person(3L, "Ted", "Mosby") + )); + } + + @ParameterizedTest + @ValueSource(strings = {"person", "PERSON", "Person"}) + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { + Query query = entityManager.createNativeQuery("select * from " + tableName); + + // Expected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + @Test + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { + Query query = entityManager.createNativeQuery("select * from \"PERSON\""); + + // Unexpected result + assertThrows(SQLGrammarException.class, query::getResultStream); + } + + @Test + void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { + Query query = entityManager.createNativeQuery("select * from \"person\""); + + // Unexpected result + List result = (List) query.getResultStream() + .map(this::fromDatabase) + .collect(Collectors.toList()); + + assertThat(result).isNotEmpty(); + } + + public Person fromDatabase(Object databaseRow) { + Object[] typedDatabaseRow = (Object[]) databaseRow; + + return new Person( + ((BigInteger) typedDatabaseRow[0]).longValue(), + (String) typedDatabaseRow[1], + (String) typedDatabaseRow[2] + ); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy-on-postgres.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy-on-postgres.properties new file mode 100644 index 0000000000..04b29de41f --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy-on-postgres.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:postgresql://localhost:5432/quoted-lower-case-strategy +spring.datasource.username=postgres +spring.datasource.password=root + +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.QuotedLowerCaseNamingStrategy +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy.properties index dce43e2da5..6643c12c8a 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy.properties +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-lower-case-naming-strategy.properties @@ -1,8 +1,8 @@ -spring.datasource.url=jdbc:h2:mem:custom-lower-case-strategy +spring.datasource.url=jdbc:h2:mem:quoted-lower-case-strategy spring.datasource.username=sa spring.datasource.password= -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.QuotedLowerCaseNamingStrategy #spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata #spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-upper-case-naming-strategy-on-postgres.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-upper-case-naming-strategy-on-postgres.properties new file mode 100644 index 0000000000..36898d5b4f --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-upper-case-naming-strategy-on-postgres.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:postgresql://localhost:5432/quoted-upper-case-strategy +spring.datasource.username=postgres +spring.datasource.password=root + +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.QuotedUpperCaseNamingStrategy +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-upper-case-naming-strategy.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-upper-case-naming-strategy.properties new file mode 100644 index 0000000000..6d56d58749 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/quoted-upper-case-naming-strategy.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:h2:mem:quoted-upper-case-strategy +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.QuotedUpperCaseNamingStrategy +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy-on-postgres.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy-on-postgres.properties new file mode 100644 index 0000000000..706b12b1b6 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy-on-postgres.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:postgresql://localhost:5432/spring-strategy +spring.datasource.username=postgres +spring.datasource.password=root + +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=default-naming-strategy-ddl.sql \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy.properties index a8ba1a3e4d..c9a0c6f24c 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy.properties +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/spring-physical-naming-strategy.properties @@ -2,7 +2,7 @@ spring.datasource.url=jdbc:h2:mem:spring-strategy spring.datasource.username=sa spring.datasource.password= -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy #spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata #spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy-on-postgres.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy-on-postgres.properties new file mode 100644 index 0000000000..b22472bd8f --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy-on-postgres.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:postgresql://localhost:5432/unquoted-lower-case-strategy +spring.datasource.username=postgres +spring.datasource.password=root + +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.UnquotedLowerCaseNamingStrategy +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy.properties index 63f400db0b..8083515b4b 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy.properties +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-lower-case-naming-strategy.properties @@ -1,8 +1,8 @@ -spring.datasource.url=jdbc:h2:mem:custom-lower-case-strategy +spring.datasource.url=jdbc:h2:mem:unquoted-lower-case-strategy spring.datasource.username=sa spring.datasource.password= -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.UnquotedLowerCaseNamingStrategy #spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata #spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-upper-case-naming-strategy-on-postgres.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-upper-case-naming-strategy-on-postgres.properties new file mode 100644 index 0000000000..da03a0d7b5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-upper-case-naming-strategy-on-postgres.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:postgresql://localhost:5432/unquoted-upper-case-strategy +spring.datasource.username=postgres +spring.datasource.password=root + +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.UnquotedUpperCaseNamingStrategy +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-upper-case-naming-strategy.properties b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-upper-case-naming-strategy.properties new file mode 100644 index 0000000000..d1b63e008c --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/test/resources/com/baeldung/namingstrategy/unquoted-upper-case-naming-strategy.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:h2:mem:unquoted-upper-case-strategy +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.UnquotedUpperCaseNamingStrategy +#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata +#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql \ No newline at end of file From daab2b383ff6059a9a64af89300e3adc2ae1d743 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Wed, 1 Apr 2020 23:10:07 +0200 Subject: [PATCH 028/194] [BAEL-2808] Last fix --- .../spring-data-jpa-4/default-naming-strategy-ddl.sql | 1 - .../src/main/java/com/baeldung/namingstrategy/Person.java | 1 - .../spring-data-jpa-4/upper-case-naming-strategy-ddl.sql | 1 - 3 files changed, 3 deletions(-) delete mode 100644 persistence-modules/spring-data-jpa-4/default-naming-strategy-ddl.sql delete mode 100644 persistence-modules/spring-data-jpa-4/upper-case-naming-strategy-ddl.sql diff --git a/persistence-modules/spring-data-jpa-4/default-naming-strategy-ddl.sql b/persistence-modules/spring-data-jpa-4/default-naming-strategy-ddl.sql deleted file mode 100644 index 34d5bd1867..0000000000 --- a/persistence-modules/spring-data-jpa-4/default-naming-strategy-ddl.sql +++ /dev/null @@ -1 +0,0 @@ -create table person (id int8 not null, firstname varchar(255), last_name varchar(255), primary key (id)) diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/Person.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/Person.java index c3e7f50403..cfb6e67c2c 100644 --- a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/Person.java +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/Person.java @@ -9,7 +9,6 @@ public class Person { @Id private Long id; - @Column(name = "FIRSTNAME") private String firstName; private String lastName; diff --git a/persistence-modules/spring-data-jpa-4/upper-case-naming-strategy-ddl.sql b/persistence-modules/spring-data-jpa-4/upper-case-naming-strategy-ddl.sql deleted file mode 100644 index b26697ac66..0000000000 --- a/persistence-modules/spring-data-jpa-4/upper-case-naming-strategy-ddl.sql +++ /dev/null @@ -1 +0,0 @@ -create table "PERSON" ("ID" int8 not null, "FIRSTNAME" varchar(255), "LAST_NAME" varchar(255), primary key ("ID")) From c73b8dbf724d4fe5bc2a3f4b5ffbb424b4747c22 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Sun, 5 Apr 2020 16:16:27 +0200 Subject: [PATCH 029/194] [BAEL-2808] Migrated PostgreSQL tests to LiveTest --- ...ation.java => SpringDataJpaNamingConventionApplication.java} | 2 +- ....java => QuotedLowerCaseNamingStrategyPostgresLiveTest.java} | 2 +- ....java => QuotedUpperCaseNamingStrategyPostgresLiveTest.java} | 2 +- ...t.java => SpringPhysicalNamingStrategyPostgresLiveTest.java} | 2 +- ...ava => UnquotedLowerCaseNamingStrategyPostgresLiveTest.java} | 2 +- ...ava => UnquotedUpperCaseNamingStrategyPostgresLiveTest.java} | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/{SpringDataJpaTableAndColumnNamesApplication.java => SpringDataJpaNamingConventionApplication.java} (69%) rename persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/{QuotedLowerCaseNamingStrategyPostgresIntegrationTest.java => QuotedLowerCaseNamingStrategyPostgresLiveTest.java} (97%) rename persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/{QuotedUpperCaseNamingStrategyPostgresIntegrationTest.java => QuotedUpperCaseNamingStrategyPostgresLiveTest.java} (97%) rename persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/{SpringPhysicalNamingStrategyPostgresIntegrationTest.java => SpringPhysicalNamingStrategyPostgresLiveTest.java} (97%) rename persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/{UnquotedLowerCaseNamingStrategyPostgresIntegrationTest.java => UnquotedLowerCaseNamingStrategyPostgresLiveTest.java} (97%) rename persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/{UnquotedUpperCaseNamingStrategyPostgresIntegrationTest.java => UnquotedUpperCaseNamingStrategyPostgresLiveTest.java} (97%) diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/SpringDataJpaTableAndColumnNamesApplication.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/SpringDataJpaNamingConventionApplication.java similarity index 69% rename from persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/SpringDataJpaTableAndColumnNamesApplication.java rename to persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/SpringDataJpaNamingConventionApplication.java index 09aaf12b60..f223015db8 100644 --- a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/SpringDataJpaTableAndColumnNamesApplication.java +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/namingstrategy/SpringDataJpaNamingConventionApplication.java @@ -3,5 +3,5 @@ package com.baeldung.namingstrategy; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class SpringDataJpaTableAndColumnNamesApplication { +public class SpringDataJpaNamingConventionApplication { } diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyPostgresIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyPostgresLiveTest.java similarity index 97% rename from persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyPostgresIntegrationTest.java rename to persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyPostgresLiveTest.java index 79c47e86e0..6b1c984600 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyPostgresIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedLowerCaseNamingStrategyPostgresLiveTest.java @@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) @TestPropertySource("quoted-lower-case-naming-strategy-on-postgres.properties") -class QuotedLowerCaseNamingStrategyPostgresIntegrationTest { +class QuotedLowerCaseNamingStrategyPostgresLiveTest { @PersistenceContext private EntityManager entityManager; diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyPostgresIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyPostgresLiveTest.java similarity index 97% rename from persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyPostgresIntegrationTest.java rename to persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyPostgresLiveTest.java index 20250a7ecb..bd23b81b4b 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyPostgresIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/QuotedUpperCaseNamingStrategyPostgresLiveTest.java @@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) @TestPropertySource("quoted-upper-case-naming-strategy-on-postgres.properties") -class QuotedUpperCaseNamingStrategyPostgresIntegrationTest { +class QuotedUpperCaseNamingStrategyPostgresLiveTest { @PersistenceContext private EntityManager entityManager; diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyPostgresIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyPostgresLiveTest.java similarity index 97% rename from persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyPostgresIntegrationTest.java rename to persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyPostgresLiveTest.java index 97f2b601b0..e26ebb148d 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyPostgresIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/SpringPhysicalNamingStrategyPostgresLiveTest.java @@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) @TestPropertySource("spring-physical-naming-strategy-on-postgres.properties") -class SpringPhysicalNamingStrategyPostgresIntegrationTest { +class SpringPhysicalNamingStrategyPostgresLiveTest { @PersistenceContext private EntityManager entityManager; diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyPostgresIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyPostgresLiveTest.java similarity index 97% rename from persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyPostgresIntegrationTest.java rename to persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyPostgresLiveTest.java index 4e1d69ccdb..033a213cf5 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyPostgresIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedLowerCaseNamingStrategyPostgresLiveTest.java @@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) @TestPropertySource("unquoted-lower-case-naming-strategy-on-postgres.properties") -class UnquotedLowerCaseNamingStrategyPostgresIntegrationTest { +class UnquotedLowerCaseNamingStrategyPostgresLiveTest { @PersistenceContext private EntityManager entityManager; diff --git a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyPostgresIntegrationTest.java b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyPostgresLiveTest.java similarity index 97% rename from persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyPostgresIntegrationTest.java rename to persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyPostgresLiveTest.java index 0fdb05b0ee..0151e7ece4 100644 --- a/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyPostgresIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-4/src/test/java/com/baeldung/namingstrategy/UnquotedUpperCaseNamingStrategyPostgresLiveTest.java @@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) @TestPropertySource("unquoted-upper-case-naming-strategy-on-postgres.properties") -class UnquotedUpperCaseNamingStrategyPostgresIntegrationTest { +class UnquotedUpperCaseNamingStrategyPostgresLiveTest { @PersistenceContext private EntityManager entityManager; From b2bc2dca8f3651e54edf7e62c8be87601ba1bd92 Mon Sep 17 00:00:00 2001 From: Aitor Cuesta Date: Sun, 5 Apr 2020 17:10:49 +0200 Subject: [PATCH 030/194] BAEL-3075 - Adding ojdbc8.jar, ons.jar and ucp.jar --- .../spring-boot-persistence-2/lib/ons.jar | Bin 0 -> 139977 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 persistence-modules/spring-boot-persistence-2/lib/ons.jar diff --git a/persistence-modules/spring-boot-persistence-2/lib/ons.jar b/persistence-modules/spring-boot-persistence-2/lib/ons.jar new file mode 100644 index 0000000000000000000000000000000000000000..637cf11887b54ddf4d567b7251ee51a18d235af7 GIT binary patch literal 139977 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 z zujvIL_+s#*21xBix^@5r(s(wxk3D=zOLB+a*T6ksIU|P9`z4w zHqG-o(#I6-+Etp#1N9(*u*RnKVfRVX<<o*?BX;9n+xRgP2@K@W~^jK zvRKwgO{+e%Xb1TpePR!)3+$2G#pNPJ=uLJ*#8s+tv21t$NQKWI9wOhrmfzi1J?=~4 z_WxU^mHJ9Q%w0t6zEa_TuQ|0Tl`pww{#+=qWDrsy*Q-zpIkLp9eK0XJs{8>dCi<@| zGkCBec#dO=I!x z1}LQ^mU2G3)G|Iv1$2&Sc8s*O1I)XqDU;lcOj^L}b#uS%J@Fy^mKd-h%n3=c`9xNG z)r1T|+@D6!)!gER7Zd?xnmp?)Tj{=Iq_T#iG)}f5U8Q_$u^={dNyX4#1cOeXAXBCo|$2b^HZt;+e5e4AnBMFDAGUJ}VgnGQ#I zVMFT^J>HWS&S>FGHIHOQ-83jxsj1HbguS&fwnMbZ8GG2i%YJ*K)J&3jV(l(+B`=eg zvEUR^Pvhd3lCzo8gTe>{wry#(TYE)yQ<9V@_#gO04R0&xLr|L5s>nxzrTWk@+_VM} z8{9l2^ m8!btlA+}-+zO@A5w9-0vADYUg(eCvPHdq%GT}$cMgAr2E0M`dwfr)j_ z5Q|)pc!{Nk=O+~pZyw8T%$<3MDV{sT#6Ej_N-Fji!Bd1qZ6VVX08G7dcIg0T4LJp_ z8F1up_I4{;P}L*)<09I?8ORUHg}!(N0X?z6=VcWgsPRU4!K*;04{UmW(A`y*k9_3U zy#grfD-v*K5&xoLZXgN3nu7>FS>Glmsb^G^Trco55e>Yp)G}@%F*-nuSUIfmH`6IX zc}8JGA)#gWiRNiam$Tlz8)>^7FHwQIUct24Fj~8Y=JGj{vT(&iFUi6_&S};l0_R}v z@Kfi5E@^TjU`oa_03)|!*wT%qdw|X=h?C%bsJ}Kk7W9 ziX)jIjf%t{a;}d9;4Uw2Xr+P)-$4G9pIuXnTf=X~vwaCXbr9t{-h5L~X6hgOPKaYy zY`i3~GKwiGaTjDn-S*}?-IGw2wW%sW0{QT}N;t@PH=dG#zVl(1p- zwq8W1 zuJ{qe5vpJdc`RG>n)zgdTy%r7-0v@8QO_}4XXG{%Y|OTsfck5C`PJW#E7R}vrt}EZ z>TNezAJVFXrZlb!mp6ld;H*8=M(S zo0Hk1+vL_TeRj*gPkD$7TW&hf=qq+3u`ud*e}pysDxUk z!-n*CF#<%@oQsPq-{oMk1-ypzy@_E zSAK3y(`yuu%6i;KKzSc>5I{`f8HcdHQFAA3-F=jwE^{}iyDBr)9n+M2@7y#wO*+k-`Cm{$O*Ayq}7itU>2-Eqls`^#n) zIzw4;P)7Ws{4@{^c~whGsugU1EUm0!FSVe$I*O!K&%Hv&+;Gnp?qDWy1y=6B^Uq)L z4XwN?4{3XsSptO#(r@#Cb)n`l46iokzY{ng*faGTTy`*3`3o5G(2fHCq@(ASQ;vml zZ#i8YiCHYuFl>ZX+QJsY7oX3bt?c7vPA$o)*3eSiPcURVjNGdfaeQf%{VXW(h(lSs z*#SVUTUd0^<1JhH5|NUdZrACQs9>mD#*Pul;S!n8yb5HS3X)7F&$=TvIb|RvilRVL$y76Hqs}L>>2eA z%WA*0M1NPv_T7QePh^8Ejgt{?{hfdLj>vlf;*)#^Sw;(#mxczPbbyy~iJuS>lUkDHYA^2P?uG?aKGg_kz$Y%nZtgAjA-H;M&1nu9KI=!jjdLMaw$W(?@a+0n^?In1<+37PgKaP5NclKP2U z16Dmk5jpjv=jRxON+z@u#hJH4UUGlevIuGca6ULbs%T2`2}~5CLb*_-PjuMJVm#CX zXRe{H=FrZ*?XM;Ndj9~R;yR0HYHvtfD0Y!WYcJ3)-UII>7 z2ZFVnN13M4yG%=_k#pa}xT8P@RS}@y+eoS@u*}#+<_tE7I6}8aAra>uah^{27A=>% zo~3qAe9JMu$1)v~1XUk06GCAd>!mYanNb<&-v>hgL7cc%#u1<#8Z&OxUT?zB)(g(!w6+CdN#uwH69Cjrl8FM2aQY&pb0b zvAHPL34Mz~-rPuw@inYARNoxarg%xTKkfvXDXC|>+;$_T7E#^ZA?N-D8S;4|M*T5K ztqcGu4f8rv3iR_c2iKw^e<8B7aWPf3Ehfh-a64nm_mk4r>(bUL^x#hii~bCMv>2ClkIrJ$YwKvx^PeqT#Pk?OC_ z^TL+|C@#)c!khwjcxiseb(l2ry6+2u`7Q*$34r}jv%btLZUwATiK7ve%aR+k#jfI z-*EBE78NLvpMiq7uV_0mS=w$~x10;723u6bJY5)$9JiJOAFQ7ydv&bu z*}r;%`|!Nf_wrE9bs9F}mmoib*3fD7w|J+Q9oSYryP~z(^N0tT&rAgw>?hGsTpu zEF|t6%}0osL1vxcv}RFEi7>WUDXl&VR0VKjw9M!aGiWT*wYjmo%Oozzp=vbNdI}|R zsjgWGW^%&0>1XGPgdR(V1KpN%1ypDIgahct$*&mhvDw+cq|e3A_w$;Yv{4-L8sOio zRtRYpX>64?e=+Mf`9p576=e2^sBJt^2$+>x)xrC1noz#6fh{g=3}Qr;t+z;+@A6tL zWO*BJ=3q2T9~7vO;`TA7lE=qTwD@1gWuj-WwX98x{y}ws=yY=7k-aJot;Biuv_r=V z{cE_nOI#cV?TeMJ#dOJJ&a^x}y#+@Z@qFPiJF zV!q_XVefmmtsmK%qeqS7LFdnwoe6ih&Caow>tn!)PPX2Q{NbA5)kmPMy|dqg_6Of0 zJ~z{TehttOHK!+i&3nYs&kU8eaCAR1C$P;Hwb%Jby!&uGUA_+eGgy9Ng&M>g>jH|dEcbE--a)ULUt`p6XYUpVnaNUu>B%mhdJ%Z30Og z{*r-rjrY-6UsXEIeO~%DeuQUIPzYL@(y01VV?=q4I2(GBEeviV1o%n`dZRPFeq`-J z5JQs?mv2*c83P56c3d-;3r)J*4@ql)Ujxvw4e4F}UJ6Be`XWg+JeRs=RFY``TnLjV ze16u$zJ$Mp^DNV`ZWE!CSn`>jF}@J-zPZz7!b9zHWYx_$0BEq~LrellLhJsx^>7G; zd@xcYLCjns?{wMP*kLRmaE#<~y9$06Q1zGyZ$#|^&A1IFDyLaI!jpHH93OH^SG*^k zNyGRNxn;P_JniM^-+i$(RIB(-w>K+PD`CD*tvM^4P84Dz9?(%rqlYQhQ6y`RoSUt= zEMB>Ei%|rvgdI2=Tirxt1n2y1GRrx|4T{8K_Ei)Y?jO7#uEM7qgOZ=3gQdcfU4JeY zP~aKlW4aVYq5Aj>QvI_6VDkFz^A#7>0n|S_o3nphH+ol49sdlcCnuXjn>&5?fQ?zq zlAhjG#82i9kn_`@chO;sgK(7cqLw|&?jLlf&r-l&9{z1=Lw=ARTb(wETKPi>LjQ60 zQkloO-s@el}iV*L8EM%u5>ycZ-<(G-k zFQeM6@yX>G__)UU=YtSC(3eISd?OFvq>@8!xQ|n_O;_#6rl(oANNS+z9ITJjFRPX z$9DqiBM z*}CkHL1!CZ;Gq8m(g}QDsr}XvQdO z^+&j9hZanafJP%JHeQrwwnJJvhC)p7dQqSwi$I>)*c)Tb3;N|Bw(=2It+4!hNB%jq z|A(!249+YF&~Rhhwr$(CZQGvMwrx)AWMbQ2Y&#Q8aI<&!*4FOcs&jsvs{YkgeY(3| zJc6gkr{aM33_H&LgTF`Q53l&0AK^()x`3~QE4g15%Kljv{@|VupjSx!{qcuveZz_k zj(c$V>M(-p1Rt>l92+~H?EjAN0U^C~<+p>~+_r@+FK1o;KisEp8En6S<6RlFRQ2j5 zt>dvg+|Q1hS9P=k5{v{t18#ADECPKF%&5)_Q4fh2T|Q!cgR{6n-c%gk$C!DwE~&?G z79=&{Y1I)Z=RTnsXZAsHgjha~i5FWdkV>GPrEyjCMgQB`HgSsRZ4623mAkkms$&`1 zteTebG)b!G%kiZ=XS^CL=Zwg1&CYjYrczMiHJEluk;7+;MlY^}*k$D2rx6L|{p5ko z4CWK58CO|-cMaa{VOdx;@RMqp+=}YoiO~IOVNOxm3AAePUCSa{V!iLnCRZx5OydeZ zF)+OwB9OBV~-t3hHQvS`36R6MT)Jr{dqRD9`Sj*5|vHw3aS<R?XI_N+-gnl>m1c!mUQ4PCc~OlR@^Ze_vG0 zV9v|y2f?|S)jfPY%+KTZa-neD=|;V~8}knj|F+z$$T2fI{Lv+j(G96g)d83HQ7`?B zNT&SR9j5@lS<|%9W)#MqezkH&Z2RItSQJ4Ulu_*ah6q*GkO=I>5|+4VgBvv~SYwE* z*0GA88iJt$dF@)102W_ToH)D^ZL-clTWWDTDDFPUyZ& zKQy^T1@=RM1bIcfNslYQ$n(|Pq4*OK!qTZpP=L%^fF8Ajap;P3vvl_c#PG*~u#afA zk81ShWnU@qnGoqOBltZLLGoB)xIHkOsTc?k=f;%(Y{7Kj&#)tbw@pUtU-IdF1bV@0Yw+ zawIGL>-RQh@75K?k@XlIY|tmD2a5BzQfA0vi8in zGy~rl;J+5-{%-1Sl2scSP>_7Klz31r=Qg!+XGpQ+jgV!ENcWTPw@4jDcW7Wp8~QEi zP&rZ?ue8_dw~|_vUx%h0@M8KeN;m>c0QEb1gmoUAk4apLSNIL8G4>X4o0H@DYVosd zG%s0MSE2Tj_TChxaBUQLzk9WLO>xxn`1gCf=Q;4xTDf`intAcSgH}Bb?ksXmsB`@R zB0S=;Wp?3Kj7AQck-wD&Qsi?iaw7|*5(b{Q#BHL*J4?I0sT+Gj#*!$LmS+nH;CD@o zO=CwnV0X&WTSxBQUv%z;2U!x$M?mp47*JU?DTggrsPSr3h}>ENoipPj$~@plJ2(Pw$!W!?DVZmnPY;tBU6ek>G(m+OHwZXaNCiAUmhN}1lH zD$+;H@PaG%bor#^8Cldt;QHZn2@#MF0~VJT7o*Lt!8)71b=b}BA8>+ecd+>V!;d%y z^Y^qLI%5h~i}$!a<4fI61Ho-hM;~7H>ty0H9oPk!3R!Dmk8(@*DE0IAx;?drp0B;} zf_n*v+PUMlVHZont&izg7q1j0cVtK_&{cd)y@`rpz(}vmMP;H|(fu&o`+HHw78F zv@@@es49WY0XHXMEia@klW{v%agg_RJ5GxV*WdEFm{6nQMevrLV!%lLU$y zjb`n0B^;F6Ib>jcoNGFGGgV$bk=!f|ke%Y1o}ES4g%7unah_>28ztB)(s_Z&HzLjB zQ00qYCEcb~xb{1|j&a^t^-8IYMYB&zfm&wHY?bFg$w+Iad}(r5L`7qs`!YI+gZZ3Au`d)Y13VGWBceSyt*$seJIz#vHR? zvzj|f!DZSdf` zmyi#(cYPk3^rEbZEliQwV)k{PFz#g+RXk7G+&N+SY2M|#vofZRsvA4S6?Eq&O)gtJ z^~25gs9r9KX7^uo*#*znC5}dmj>@KaqvqIi>BC}BlyLCFqvMN9ZL#Vj_5_AoQCdU< zG-Y!YML5fg;*#^%Bzad|o=oxU>DF~Leyel9AkKJ|)QgkOhwt-lWX@izQee{#`M7cM z^fbYY)|ZN6jy;@(I3W)FxbyYrw;=aDw#U>nOlK~y>YeD+xznd$jiXwS^Zfdwnjp!` zHohCDYvMkx7wi&dVY2>(VA$enSkIP{BmWsb?5vAAf)+UQikklv1!RM`yXbd~2`#E>Cx=|WyBjOgRw4(v!Et{hO3Wco)X!zETVoDk{v zP;aZ%MtwA#S3+g_aBN>vc}CNKCn06z1*Cp#*-0qso?-hAWy2%k^o&&Ajl)Nbc)uZ6 zJZ<&F(w%kOd^4)Dke|1f-paz6JjUrvj^{GvqZr~#FyV*qtc{um5+OS93WdRO#-5)oM1{2& z@w-xWG(X%Z&JqgqW{3@&@nY-T{HTEd50{(EBg5-S^WY%y-zv?oG>eccrW}ncp~qz0n6Y#hALGmN0_J!Q)s~>qYMMmTQN3 zwW+M@_`@FL%$xhtj%V9fH=GDZ)JWKUW1rlRNhZO-LeJ7kXGdIfmNs_({`#M%Lc`|* zlII^~)!|3=CjFlZtAeAdxr>Lni>t7Qv9;ZQClLLW{wwRYBxc&$s>C1V^#}^*RfiV6 ztQr|1b-UTIoaU~{VSV@iW!(x zI(SFtixDT)$`sR5na2{d@D_`-1CW$HGoKvydt=GC5uRpe4Vg|CnG03z`=T6rmsSr= zndVWp$!dHWEv=!5Qv%GzL8*C1w8n*&{+898 zKAOC1Os?r@hp2*mK!4rI_F#@h)-XQ;pPn5&fIiJq2~9IwZy@YKZN?&em;WBZZ?VGM zUbSslx%&QJwE4If`S7%#>FWG>G5`0pnVFOQmwiuPP8eoT2x-d7-JV|S*WN&LOn@*N zUnQjBZ-)p#)0Ig3I~StBAIT`y9&Te45b2$QQ`kQcoxv*OP#ff1x>NrE%*6a*$(nKA zSc7(_b+C=kD@onDROscQ-d1t$wIK;za|~->NDm<|TMl_qNu)(*m@TY*i>J0jZ7Hq& zCXI;zpnhB!B8CAewgD}!v^g@-URsL(C9y-7;eN$K00EgJ{2!aze_-AJU$*;CfX~6) z)J@p*Ka!9CrMPRp{X!K-`&Q8HI%koJ3iN^$lh-8%kH!N>gBf{+rbnT}n7g*vWU%ub zvKZR;-+l3iHSi*hw1$O=e)0ci4-mNU?Y0)pDXSDT^ElbQo$<6V==;3H=xgI#>wW=Kw*Uu*`=k+vb zc0-YGf09*JjMxT38C)A(wT==r)x?cX@F2H=Gr&=9mtYhTY^y%}TOj!I)t7(Cac?7z z&KniCCo4jC^iX4~eD4|RM#-r{#yD|Uze87?zm2McGT2w0?LYwGJz&*KXdncJ0HyNT zXJ%_!B1oEgY{hL#ipzsx;lwP~!i0g@eo2>tiQ8bb?h>ierYP&raH=(~{aYWykbZ-^ zwpdg-o_;eA+uD(PlGaH5IC4!pSDXFWj>|SHzOE33^?93?4ufUlxOPeJ4Bb-E8O=6d zmBuJHN*S%A4)#!)Qo^df>5+>LVg(6RAa#{IK!e`c+C$M~#bf)&Y$q?}o89Lfm;M*D z%!S%Z3kc*iy+R*j1Fs(ieG}I^lhny1GBhyTX)DFf z;B%maINvnnvAM|RJQAdNRlnd(q;_}psKb=rYaZ~!GtZLhUG0S9gf2x&Q0 zL7@%zaNu*zHpS%jA61E(yXzdrl^We>C1QprZ>B;6x!Te9O|Z- z?@(BRXHXb56S2!V|2t|&<9Btnb&zSH49&`G66>hiJZ%dPQ`d&3put_c6`-0dUtM={Y#&vo6&x~=O;%4ihy6I%tljJe%V6Gddh)v zfFn9OFS9b>d~wUiHsn z&58qfocz=>mR^{tF_++%i;R=TW4<+cri74msh`0kQn zOkwE8fotf^JCx4cG%R}26GdEF^R8p}zV_Han!VvEQ8|jCsnud_4NU#TnK9Vn+N;oe zp@Yg~PWD-JE&k_Y0ToZV=Id|Dq+jS~Z?SRa#_LqXsr6hu4fV#p&@-;@a{P^3-(>c4 zP>C8Z4Pnrr{1Sm+!Q-ikJy^HO$=a7Z`6av>_sE5tHDo+?bO+o)IGZx7VZ===Q{%dL z2h_u!uS)_!gVep8TeYD+)vHa~L*=#s8d^H$r3cMwExR|oCl%60x!-Q{)Ukx5g+<#r zL*1B!xE7*1dTS_rxSv#GJ;)NG7Jx=CwBHWg+@{0-I9ljew$-@e%rL^xjvtoKAel=Q zW(Iz8KYkyv>3}f%Y}Yxl?OhNm2<3D z#A;yPtN+3i78mysrukZ{2a&UBq`=*=r7u!_c1D|PAvhdp6q5f|LJk_l7*2oxti%#h z2R_UnKp!af5lr=u6tjgn3ZxRZ0X_`L+Dd>PYDNu*m+R>!lbZqv%Tin@@Sc;&wynC1qiFAK9^>LE` zwuEoCSS$`~mM#o*^?QT|fxBMu!wf6(GMBH6ccbF}PrA<~nfnh`oX@#HVe93GRShh+gSy zrxyp(6YGzv{6gK1`3lu;7ZG+LelrMFL)N5)Moo(?dJhkXbdnnZi7J-PuOrqREND&g zl{nEcd_>Wc+NGK~S=z0IJ@aMuSH^vV{GVqUPt<)Ih#%M30Spij{r}JA{GZ2~|Edgj z`j0(L$;Hvj`#(3fG!1=M)E}~kLbAuwHAq?NLmX8ZSrNItdJEdTiV&$iFsK?$<>m}A zoxJDJ4Ma3mBvgQJ!>>QMjAr2&^Vnmy-+{jdWE=1${bniH>{C1@%})3YZ~x_k2d+EoTxxp)2ShODXwJA% z|Asv$ZdXdwFzTKS6jEKC<+V_HDE-sdB?B3*Ki2}oa?KOKqnmw4KgUoVk^%sClho&U;;p^uw?4^`=B{{RFPNB5mWxH{;WY8g z>jSnr%ZcUgD${)*c)dPA9MmT^bNqfa)v#=9n zX>)0)ZXoTDETj5^d)Oe%>n;l!6T^E&KG>Zf6svc+*vHJ4I!;#)0XM&w%MS z{3iUBNJY@L6qeLMq)_!m$}x||#A7Myd~b!S##8BZ9?b*_?O}8f5IMXiyxvet_$7qE zF#Kq1zu}N1gutjgd^?<9a1Pxkpq}kFD*na6X6^lzUXevS)+?GPoL_i1#Ld3zYDf^{ zU0G1W9ea#pCk@AZ!Y4%EKs!jcCKhc_y3L-VoSp^6Mo&!axv)KTb47JJc0{*971sEc z-nGUfX1b=QNx;f<4AVfl9W6f=0t^+SdI6bct=ynDHXKi9tf{w4w2g6r*=rBI8P>%p zXuF;f$R%o4m-||iS3*K@j|vNHUlXnJ#`9)=$Z zqN>~12M}*G0!DD>t9g(>=A6;@18Qt!XLZ$eo%m|AQLU_%KPOrxw#igdeLLP!nZE*I ztN2+X%Ls~z|I*^j@rQDRNYU_woRJP&E<8cKTY1_((!~bOdHWFuC}$QL~GaPh;Od@8z6~en#1sv#ZY`vS`DFb3{cJlTCUBI!)+h2ZNQ?X((!d48gBH74uE8l54kIf5!8&VIFY7aguCs_((Xo|fXt zMMKGpembVb$Ru)d4YF&>Pl*c_FgChy!{5CAbePg#ZRZXMx}9a%Lf9ycY>Fc$B#NL? zY)`x$P^xf^H>O0`XNS)fkvabT zKYysf4cP8{KmJ=gHXtDM|NBGzuN#35w2_|riooeCnInt$_F}nxSGjL`xwNL$VtV;` zI)|+FVtT0vZ(dK!l7hwHbSZt|9tccvWu#Ri$O9>GolKFmPIX|RxEhiY8m169x-v4R z(CXK2=j}|o9Dt_G)AuFc_xV`i*X!3OBGLlL@yjB94>{zFhIN~?YY-d#V$0;(HOqS- z8>WnFQbx45B*Lv(!9aHpTkNNSgQ={r(aQyGuwEbqTFIGT3%62`+5a6XtB z(qYiOksg(97*d zNch*O;m_5h$s*$nGa}*3-6w$nv6kQF&~B3Y)DWWAt1z~}(f+N^n{mMK-tENaZpKJT z=LgmIpS`irJwl&XNrULSgfefwjDo#_qlc7_R5nH24^>9}Nx>AyIjj#?#_!;Qw3Cd% zb3^YcX(zkmLa2i^l7jBCw>Y*r><_;m(`O{(A!g}YozWey@l~G4n)5pI67hd(GYt&w!bs@4E-Vw|u(A zZ+0}C55|yh`@2iIVYAh65sgxcvlxjws-?jdyY;&Nws4YPi9>k9z- zUrCU>rVeTp0WW9-$7*}6_L9!F0Qtjo3yPgTX0HGMi3VEX=vo-5z^{24#E9Z!kT$@V z%1G+=e#~esl&bN2zE&as-pd5|-@Zi0cJu**c0oKF%k12)=Efput~N*yPw^)QU~Kq* zFWSuI&{eo4dB7W6rTxZhQ1jR|kSIVqcxS&e`SOD19elZpSyAG{KKJ)DXi-*DUFm_Q zAZp^OS{xc2`x|;_F`&{xDSv5_nS_}f_i1&I?lCs3ZdW^TS-pW3C`0-ICt}sbYi%-t zz}<~%o8n}F)G#2SFS}%ebc^kNK(f!y;SXoHZ5uMxN0J4E#kN&(okWjd2u&U)PIi_ zRh!2I=9HWRDO)5In*;m@v*VWh9>o@BNupC+b!n+e@hHn>StJ_`d>2lT$sqM;a z0^*05z}8pZqxH#@`IVy4_jXP@6~6chLF++;w^0%Gbkk^PFp zDVhV#5#0$89L_%C_vN2h=Q;)TO)%9z=S+zc->s@Um|NUDe?}9OYrhG%G~LWSz{ZgW zkmWfVBhsZBIG+{d3H}4qCYHlcCS6DeBX(y1%Uaee)|F*+$PHu-PTZDhyH8{E|RDJ z8==)d?RtvTghmKv5&?ZtrotZ5xA%GQ;ttr4ou}Ia9CU&I&R@zeTV|Onyeb5JaavJCiwKDZLX=8C6a`DLUul++ zZ|H6M+yZa7I2v5;QbAG7$3xq%YnTN@NAgdQMH5ipnVl$7~okAaaL zo%YCfXK+$PTKlfQNUz+bhR&;Upc)Dc)d11SEF;UN^-f_^KCLeHsEe#yieY83Ec_vp zMiTg1fXA*^YrZTj<$Reyy=_wGs5ddSlKe$d%qm*1Y80qeufgYD-lR3#!m4T4+ z)gz6# zL@L+JYM`2eRsSOXLNvvC?)&6VmNc;)g_tlI(fnssS7i*0Oq`AAsolF z+K(NhsD;Aht+bftiIPQj-wx_s-KyHzrl$&K8LVS3D9BdHnf672ZJA6}UPD!mJuRQr zyRTA-*e#Xz;6qk1T8+9$RY}qRaGnp##rLraHv`I%X^+|aNNWuIm2`=&8iI(E?v3S)cm1kYEC$H z>uQ?TSnCVy2V$pKTDexeI;Lgs;BT2_49l$g%xaw$>%sK-J|q)wW0q6uTKzg?wiOz6 z)9MwQxT4i;n>?Kay+O5Bl2CXXQnq_HT)(JP7tD@n-8buTlr;DlG0P?bU`@}1p^}FLy(vZ6o(sp!iF1rs^%SnYDVVrK zPb+P?xj^^eFtQk>OlQ6-qeln^n+vO+|-Sc!D?$P#6atz8Bqw z$h;0pBqtCQM3tKmatG*U?b}k|v5+~P`}Km&BDyb7NeUk8*9joOO{#(>pTf(bDyIAa zUUs0hpbg7~gS8n2HY6(zJC2TK3$N&pHO8Lg3KZBJxtLtiH#>b1AAi(6j1uLksr}SI z!d+YCs7<;sjl@^kG77RbSV+`mY1Z0NZ5!AMHa651(JaS=muZ2xs#}B@Z-8u1v8?dmfaNWj&jDh6^57>wuH> zg-dz2aAKfwr0`G%6NeI8b8{OlH4u4q6cuc`mK zIm;th6fHZNX)6nkRC*W>NZ~|5G7tUpyx-BEs{__!EJ=)r!~2jaH70Ww&3>4Wy0hUW(dQKcOomC!p66&-f9OHLIO^o**`)f=nyKI-V^TlxJGR~G77PDW&KheIoepQ`vKIw%IaYsPn<)`fbPS)At{($L} z4!G+?i0EbTBs}(5l89}NPxcNDZ+%*F8mLN;cv=|mQMP)gYDkdC$Sq{1_kR0i<8aj5 zc@>};&q?G&))&MkAG1=fuhb`Z=R;cu>eA9~!C@AFJ zo9CBy%C*>*U2^0SE4L6KoZ(VoX)UmzXvC6z(0zo!k#L`1@R{aZ5aSU%K9P>fp)A|F zA|Z&`k9k7jm}r%p?_R*n$S>vYu-B0N99m2xsMv^ZGvB6wh%_Ak8>=1zpQ z&k7P{wQ9TB#;JfVj5!mTW*Cge|6@uiPfUoOBnaMc0A?`q1o=*y_@*jCXm)H4xpZHu z0NgQED2V$ME&Pjk`RRg>XTh&@7I zA3$?X?l|d%Fj|)QzGaXdW{e&F=u?F^1Os>avIqi)Y0^=dfnnMqHk-F33v=k&*wd0h zBP-)ubZp+6st>|cPYSJXC{DVN52lbp4XKBvplZz~FS;pKHlIQ62Cu%m9v1Ftj{aK}O%VQY1!pMZCtV#*4S&Ky%Wtgc~p316FB*?0Y;& zr)9Sy&n7Z@V<#`ZJ)C2-`PqVFdy|rg+;tcVQW6n;8NqVZ>EFVju=gId4GjdtWSg*e z!mTC@Yh5R*4E@0he0YDS6!yD>dww3~>`cV!hQ!JN_GuB49!`is#GH7RzF7N-;!|?U z!coM<_nh8mbHSd`JdTqC_i2_6wAu5VKgXm#7#tdswEmc!9v*QF+aDLZzDW{+m+aVn z{2jsG&N=N_Szk4#yENe_fvr8BD}h+wW@|Y6vFo=M@fY25kZs2Zdf8nC;fuhpE)}*9ekJed zrsFX`4`l(%C6w7B90CPgFEI88D!`x*{X z&69^M;8_zu23|6HfT{kGy){8~`<#G_%ujCtL7TW#H)oU45a6fzYFuvdA;a z$H8j`?#kfJR0iY!<>9hv`~riL&UYP3KxaNWOwWa*or8GO;Z6-?JZTV`Ovw9JhLF zA~u~u2VsjPZpu6H0)WmQHb)V{w=U~Of~(|dQ_FUQN@@eDIl=XbcmWn8MO{EXA8ec+ z>h7+9(LaZ`9Z6r5yTWPJ!+esxHh%FPgFQ3esK2iQAdt_UhaiSQX&92Qzt@!(Rn7yv zTsYIxQcu90Z?N2nBBNW)Hulx{oYJ5FnC@u}^0U$Hr?#Va5Fc($+C719Adde1tC72? zt(Gg#|EI8dQGYMMNIKnC+9SXtVD;L~KZsY*SGX)l6&5D;(5*2TUy_C&JYN!d_7Isi z8?(8JhRH5k<7wU^@%I+7jdReLe{5G9x>x+d*P&Zr6-x!tDHpz(*T_AKi1rhbzRo%Q z-NCpye}w_fozb1}0PiW5{*I)kUe*kM1y8)t)0`-&LD;W%^wUSLNIyQs)z6X-F2N`& z`^zKw@sP-zi7DNp1p1b2UE~OcQY=F;&O3#7lz(Sb?F-Tl6_#Fzh1X@LogrU?c~3ME zXY2?|mw3h}SiY|)vxie1iHxTzUrd^Jl3oIaBWZr@j>n2FyuYGf?%h9}zu*jq)*dlm zA^NbdOSa&19Zo3UC<3zkr{_$*AN^|D!f2By`y{maP`35A0g9&TYI zQ(x|%yJL+ic^~qxG#BE+eLu>$BZBN{!;l=_SffYy&~?W}nlFquI5k(PAW@KEJLyJh!@V_QDD zNK4jT9}q`k@ik5|RGE|%QE&&U9!j5Vs`^!?7H?(oY5JOinl7>Vs*IGf8T&3cGH3g@ zD%gU#2er*^f7GbFDQ#NO_)g10bM;hiRq|H@p@po!5~=)8VyXN&KxHU{77+s%O}}Yn zhG9_}oxpwe9XzC|Y39w0iFTt1BY^pnRM5;R$x^SuD$I_uMq!hT)_kxWXCYSH{oj&!3Q-QHF+(){9-J{A-n zcZ&|doy<^A4)9GU)1Z9$phWt|66p^<{Dp4wm&WdjU1$2cH130EagDPwZdZnQT?WaH z9BLxkm=ge&5K+RDk--DD#n%%gK>yReaXzRC(eF@MN={XdLbiN7nO0nk4&6lSh0RDwaK4Z3m+$&W z7Kf_#Z14cJn)`6T3c;)C(rSv8CW;l_%(+69=sOx$OtDP`+TV;=33|4F}dHatO5YY-b|0#o5X@KL#)j!&-B6f+}q`EvY0AI_<7zL z|BS^=WJ46-0|N#{bUb*>8{eC%|BLK|N|h^H!mvbk*~) zDQ3{HQw%o_R9`Th4hCFSX?!wMYb%6h&vvVK(GlC{`8QvE4ZaoupI;yFf1nFR69ElK`{FHRr4Z+!I<1#w%z=M?d0 z*{~HU4bT2$IFE}i3#@p(8^3&pkO1_sT6OO{W-gdieNBh=XcV()QO0WvV_In8pbt8fKF_CO$}O z8!{k-t~cUnw?VOabm7`%*oMpf{<9;5Y@~bJ^r>v*Q542H!7H9a+*$KUWl1wM<1@JP zHyw1JsTjRzwrV@@LmYlqWtc++#R{YNiS~gb2o^f&mE*p|IgYlZOtIe_3BT zbh+2`V!p4%WTdcL81{PDOJE6DaWh&+LDbj(`&aX}_q|W^^Yr$m07%AbIS|c9u4S($ zC^?F1mU9n;fx>yB^u-*%Gg-_L#oxzAz2fCE78rHSN#C)@c&|K47i)PaF=!L+zM2t( z7Vf+e{9Xsmet#N$s;?rqGax)vu%SAOAbiNQo{~=Y2N$lB>*W7eM0-%Pz9a=AwdCUx zZmh}I;+TMSIDAWcVxF%Yk6T$cH)*FOv$3q)gWgyWBY*Ld32SLNRUgsSu+MalG@i7V zSXZqk8O6od*`n>5tSsD5S2;hI{OQW-hFbIx_jtO?akB5u4}xQIUd;9KxT7+Z<)BZu z`2@RI+dnkaPaTz`kzjf??Q&o`xaA`NetfGg4Nj1m>{Q%6pce>?eb6X(b z&GveAlUrwD)EP=2&VG}ZRZI1`_6crlA8S;<*niF$krc0_L$M|YF3EC^dz5L`83>Y_ zB9Zwn&=f@#4^i3T?0v2YJM(0mWXu`k6ia1uPU7KNs91(-EF+)vN_wtNYEHAun10T~ zHJh4FR%61J|EO)}YBn`5X{$aSJuTX;a_H1!V7-&Hw$vf6*W-ZnpyFfYmv zrb2xUturz(jum0eCsLCU3C`{RHprqCfS&Y$C{|EQqM;?irz}IcYE(;<VGk{pU0sZQ`BjO>S=Qs~{ zk~c}xSk;?CNnwq&lr9L|CHW1A@6%oMnddBxXJP`0E%?TW?!e56&jswWQxWKY*Z+H3 zg)89y7=&wn+UW8Bw{rg93+_MnvO4XbyqzYxfaPk&1nCqRut;FjFbYMeP$5;QiU<@F zdDgrfRC&uHG4|m6gj{Zx(1H%_>Z-#kK)h~6L+^L14h*>+hUf3Pw$;`ZfR3(hjeDJr zuJFg4zoUggGGn;E3kB;v9INl$RM_LR4`R@$IKr`?JB#svh3U;1)#wV`Z z%q#@RF{6A_^4QOq*zqW)$FDJA^q#kLgUmHU3N@*7X7S0ZQ!}w-(JrY|fYI^qf>`|9 zS#QtGRK|N{^dZaAt$_U(DiyK3N;WWIe~Rj&tSlp`8)R>f{vp0V_6Tlir`%y4PQPr| zZTj03>>IzIIB|bQL+XjY!H&8V{6~Ow{o*TV)16IR!@_F_jv;L=P?y4UhruE4ksqhc z2l3mES|Gn5-Id|>Va^-rVz+p#;phPA4&fY=C6*#9g5VOyM^Nq==1IK zL&Zsm0-C+NSp#aR=ehgMvhYj< z(oZW9tW{dY4bD&FEb~tG3eP5{W25MD`CnERwoMrmfM^l9wq_ zZoTT`E2LxyK3`aor6@_SJTbK~JUWAyy1blWYn+_zp+jUgbmWFSu(^_5D z*=&AXe)8PreqEHVWT}FP}Fsf58W>UBWEiqz$S? z#y|^GXqSWD6eIU9Q>JN&Uca!5x#8 z<#%-9%9S1ym~wcwu3U?W)>&m0ok5g&`|9&a`KtVN(W*lhb*mIbOP@VBhpi!bgu&Y4 z0ybOeY5RCvC;u|Fq^&)4-Hje;vpEJ}|1a&}48E{ZQkF}uSt)$m=pwci)+la#`4ZDR z(N_1cNy_CKq-HeclPS+4Cj4`KJPC+6%LJNgow>du%K~er%)s^q^9JE%m7_{Q?L@Gc zAsZ@NJ0dx1(SR2oOEvUt8$89#gaI^YU85Kq+j@f0BJ~%25#iriCq> zfi`!#F03$g+PohZ>Uk$xd^uARA+p$jCT4J2G|e%4+tn+nZkw1d%fily*|!i&kg7?y z^Tq&@SDMzEWh4Yur}sjL5RMKf^(q5|Ap&x#ZEHnjUZzEK*SVjc#yT9ONhy zu{`8v96N*31dwPr->0rnyR$*UR@XhO#mp82z?e7J$J(x(i>A`6={^lBfhj@xU%jUM#U*u)bO-0rDb zOxw0>Uc*iCEZ-V@aipY6TObB8r9tb`wnt}gJh$cyqf<}ur2WDKx{54^Jj5n%Ej0GA zmuL&D0o5v^k-|JH3U@;cL|9F?NIoH9eP%GrRyAE&=o*;0*Ycq)Wtzs5qoa0&Y@$ug zykZ&<`jwvM;!A_Nm~_3cQbNkffW;-t5G<28+gKa#(`Tj8L>|A6MyNrc5py-l)Lsi~ zWGf-!BCbN689_@Rzjt^ejS%hTg)7Hm9_>E*tKzr}x2FedGAM#3#9DFK6Q`>wFy3o% zUMiz{S-&^rb1$%jdnu0mGUU3GbV%+-@~XNq=0<@W*|1ddLGy2q_oL7!%L>t=t*q~X zg#vX9nEm7_OU!kBRB1cTS{iwY8^xv3jy z$^XOHI|kPlbq%_)ZQJHavSXjvHcxEZwr$(CZQFKof)m|z-LI>=-@4s>tJYq%{;pXy z#$0oZJ)UQ$@OIt^;GJf(a!%?5OGb#ExpFSbuyStEAyz84@b1hfE9dbRBx`%;D&V-Z z0^pxobo!b6T|QUskSWy>DByo|b^apYhuFj#=c71hBohB#I(PX;Rd9wa2H3x{H;-uW zQa>g`-CaHR=nyQ$Jr@RSlTEu0(d5j%L2B17Iy+U*@E;MLe;9p1Px(Z}fiBx@g^_+H zU3IitSgIZI=|eKz?KsUu8Hl~Q%c&c6eFtY>K{V-`t#F-< z8LRspSKjKgqwjl?*}Hqb9&bf6rLTH`T$eo-uJ@=(&$UG?7Mv5%>&(`C{h0}4w-Jcd zLRPYh5a|Z?c2L*1-#Ahu@T^V9f8zwb)$xrGh{=YhD!Dp9LsI3W^l&jipl zCjCZ(In&?sFL_JW2?sNJtOwV>r^O&33ZT_hx3ST)-x5q5WFCDpRtiuE1{7yfOc}{7 zjNsT2l!NCK-WIR5M;x^%~) z1srK-5~AzX5N3=Hm%t{GnG%BC0&*MZpTGSBL$jSeI3)vN+k zt+=6Eu0?tBUY1dpDOx#~E;t>{+iSQ|txt$!$^Df!%GX-P_jPK4AGpGzx@^?WP z`u9S;^1*(P_vy9ty@2jm`V#_m&4S!Qe&m7k0lAHV5Q2IA+#tM$KnTG<&|yE2_KYxI zEB$&+{d*B!aWP&q{d!IOd*NT(!1;h*xg}@#%1M_nlfio)nInZzXbB;gz{mV;MfU_9 zl-cnpx6iJKTX);lcGS<`AAUs~i`aXBT)Tn#`v~wSL25tw6#e?D?@CA*+&wDJ1^S@o zHNRnw#e>;Ky(1u7)g9K$G5fKBN260Hl$1KG!BezQL?yf7h#lP4?OAet``W;LBq+SPt{;3y~z@WEjatZ5RA>|6xqe(@k$;dk3B$jQw=#I(}{_7K&qx6@oqEq?S^$F(nqkG_ApnC*=2G936&z*Ch z!*?tXf55ZC-G|QI2k+enmYa|Eeb-#x8-=@RyIY3Wb}Tm6@PqeJC4RxcU=cSG(P;2R z%%YP)rA=7GNl-C8b!R38_z7OY0jP3AXauvCCif}RTXqw19HO}raut+)0a%YFf^Q~F zW-fTArQg3)!O#KMzBSg-7l)%?fw#v`6$hPQ^VhXc9CJx`Y63BdOMAt=n1=I~Pl$&v=e~E`!iC3RMIpERYT*tIeU>Gw%)`|B{lv0`T=zx@1^?pSWr1 zKd6F~_aemLMUZA|Q<~#&E@V#*C)r1Gq;Ht8u)pxLG*gZyWzg?(2jnWP-RfcZoSeL- zXCD5kNRUq<4DFYzj3<{32$RVP+mFe}_Ys0tCkZyZuN2gqs`Ls`n^w38Twu+!{= zRQ$;uhQf7(`*o7E9!82aQN^CDfhZE*S&3k2GX zq&*zcZ6@V_ z*|P*G*}u`|P6ffTG7p*!Ie3FCs|cpw6z0l?=E@0&UM#-{u28TiZslG~a~5+x*o)cv zKxSzWdBTpdJGNClV5ugn#tf5Cs)Pg+9by#3sOOHl6lO zNwA@7qC!V+@k;C*X_uT$U#syr(lWNAMiKmv1#|XX9Atv&l*NYpue9}8^dlDbA7;QK zwn8(pv3v!$G%Ogytm0tbz?Gk%-R!yT^1oR@+c1o46&tDpF5L7uPSHay;YBy@=@a}W zj8E8C2gyftCrUjD*ZUf6^&BX{?ik4hLGuim()HLvJ)u*3?16Ns3j!ti!*h(9y?dlZ zutm72zo;^cVq=`5sNLG*@V0U9Wa#eh3%K$?lfpITBywr~9ctl!tC1`%tySx66G@N3 zv~tm}nl_k?J2)v9M}x)Ak?7;&HGPeANkR^11=1*cAo3qHGsadI;d-5m&3%MvRcV@OY_GssS>2D$9J#(9Q$bRocoxKI3ZsVU7;Xx1l? zEl2yAQU?CL$ZPcBJ>_zXOb!v(IT>$>0uSWoDfT2*yejECw+=s^z{hr~-0``e{^Clr z#kkT{;fbkQeS5?Z+Npwl)Zm#Gxn-I!Ewh6;SHr^pb{B5)a?&tH>RuIciU{WBXiMw} zEj_)+`D^-*4zr==DtdKUKlSEWGpm{BwCcD*drZ%5+KD6Z&&C!Gj9AX@^9qseg{g<0 zRZg!RA$xy_DxAXOnC1c0)LB`ubiTw$O_MKmX)2GJaFYX>+Njkni`pihd6=dciSHmp zd&cg-AERWEhQvA)ZKSpXs_F|2J?`I?o18^ebGBfG?9!oBX4*_5#ES^?ZxG5;gV-*7Ss^Dt_{c>~UI+APk=urZ&OfztW@x|jq6+{GVkg@3A_qJD;Rc}o|v zqq7$#A*PuQj#0y^vJJ6>n+UdRyq2!~Opy5{0lujbugn=Uu|~1CgO9!(jM%(BFd8rtnoyE@Wik)C^m# zH0QNpbv9+?f}-lFWfYd%VJwYp5EV=9et#T+Xy^%!~>fz)?vjZrf{25kfy)GTWFb!4+?=;~~&niBc!axw|?k{E4A5rd!mp!1V(Wy}MN zMc;n7Ua;9$2+JzBmJw z%=>~Jq6^wa$G1$&*rGVeWec+P4i+P4Fez(5;n)p$=&55MGO|1WmD`b;wtD*!@dX0c@Fcur#kA?)ap%PN zj#x$4*7H}34wQH8YIf z4Asmu@1-^K;;S<2L+c7bDT_PDoo!P!s`81`Qv6AprNo7j%mj|)vPpZ?jxWi=X z!ah$XT!b6@Ld5B&NB;xfgXqa}(FawsE2LW(15QCC;sW<`%Rk2T%DM>REt!>ngY`tC z7Sv4(L$pgB4pRPs&X-+VRWxDA?JxsvBT_XnQAw91ljqy*X@?`c@93Q`{wVORw^#3e z$H)6|XySvp!k;UtkXx(Kt-y%23J%MhY0G>Z=>=|U;oK`enwpCKwylf3TwB)Jbe^)kev^Bh&xyB4-JblxF$>4rGl5SzpG*IM;5*;u=!Pnjo#1bnIOa`7qI5ej zce|IwA>TN8hbSEiI?`tpzasRd*uD5_gWVc-{zNrpWUP$aN7y_&;4WM$lLg0xi-{>?jN_VccYD~b9D=b z@?BBR2M}gg%M*!*=E|Vtt$7rC14V*Nr0-XgRS4we~RO}e{g)Lktn9|{$rKp|ij0pqpBK~)WoKQL8< z7;fJQxqzxjEc}5R-%hAaeldp0i_Sn^kq_McJI?_8(V!o03G(UD*(>(b5S7pbv*i!B z1Z*;@g|D=3;D=j+{=+S)Uas=}4;}FbPiX1akK6?HhxqY-ShxSQkSS}){rG{tO153D zJAz>%_Ta&STC`iXy5y^b3hOoJzy{vybS4KHq+D8IzRMXYB1RyE4F>|h`^}`Im`5;o z*>f~1_7^lex6@fqvv^OrceB!6dv$w(nPR-)nBi#UnF@%a6~J*=SVqu9m>7(Nh#!lh zsIk>dw2i|4RhF#g8k|uB7*^?p9j)ZF?7SZ9%N=)}uH0=N8}?1dT}PT^_($hbtxmEu zP2(P9$MwzVGg|89*VUP~$a@UqORCS#wlq&_s8`sF$^4l71nJjW_D|?<+#$?8GLJ3@ zNzEE=tgIYT52W$>Ras1>$XD;WtVq2p`ubY10JvOn?wJ+44_-a><8f3q_mtX=Z8|Fv zF*+DiR;yO`qPdrsk6x^05pI95qzUeP+Zs&Ie4g9H{GhB&z_>=O288?#BTd&&d_d;W}7A-LwYZgjJ4J5 zK^JM1hg6z~Dh(kxOpcVd2CPF;2EoeHhVg{Oy{Tws3KIX-t}~$Ci(8s<>eQNrNPQz< zJi)T3huu-RhjC7l(7T&nTEa$W*!SP%0&YC!UiXWz&}%N0b$uy>J3V^e!nxw&`p(f; z*{yONzL9V3ZIf{#pRM=4d7yu<=fOZ;u<2LmrVd+#nvENn$q`&XCln(M0N}Lz|{>{cL1+G(r{^XYhE^+@f$8coe;c8c)nVOvAJ=*(rcqXc+A6uAP zgk;i*;>G3HuP;j?+9<;Di8S*wW1FY@?-SyG%{&zBpNcO(y>ve~AfTUd*#Ft9^*^`J z|9b?<7?|7qXnzfCj7*db9RJI=Rjhg`ho^$}y=}6-o}E3AB4qFm1k$JG(SY)!<_LtKQxr~3i%q& zcF@i`**MlBnc_K{^_J~;^SSLfvqkvz^#YrtRkO*ST?-92*2#xIi+W|G0{~6{CRUyoWugnW;?-t@M z@7`cc9Kee?lRFuU76Q&g-iM^m;#TFeTou8R)LIP3l}{a?WFxkrl(JDtVJszcZm*I0 zj%Gw@fUBa@?82-Z(%@ei%hZ;sBoR#9E3=&Z{3IW1=rqoYV-B;S2(7_Qf=lB&L$&Qi z927HIVMEOGMmFl{ zoUy6AXb3e`e}Ln0xthI)&}UsPECOR`GA30N<`+~<)=p^XH;kn^Q)=hrmNBv|Mc=`^ zIpR7mM1xsXeP2^;r~J84Hmt*V*>p6duT9W`Y56DLgwjy6k6O|gxD>l@E`hzbfm|>< z+rK8Bitqx9rU92JEW5lZUjDf}Yb-%jzS(OQrJ_z(2%M%}d9uzhC7d^eIMx9G7WErz z7#mnl$_?TVI1lYUUJmMASJ0!Ie+%6{h;Gsyims`8_fWosTd=TX>Pc!^(jAR%;vK+( zyvx54WoJlBSsqqaZeWw=O0Na?FCwVY49QMrAoMjX|M|-z8pYFv z6w(ud%Cdapj|#rIj_U%OtmNf-@F{I4*% z%19X68VelTUrQ*O-`VR?{1dQT@$%A*6%3N+OBvlS)70=4+tORVAEVp^e!Z7NQ62u; z!cEY;rPh#oJYa;LcHYfeU?WKnNNgM!ep+%_!sb((Va-{r3G!LDQWK-gOgLQfaeB|U z!{I*_aOb~P;#8ESz>W}dC2b4!5}rp}S2pYp{o7Pd_D7@Yl+I(!Ew+RiOgPdu^!={V z^wH^-G&bCaoH?iJ*|FE^3F)O#utnq&d*=K0SHqo_qW3pp?mGH>3-=AN z`9E5)*}l=T7w}-{u&53FG%24DtvH-6!CTIhZ6V!2#Vg_1m5kT(XWSeZ|} zCoc{N-@xCF@*k#)U?4{$s87aQXpZA9iKE%EMsI6NgzU0wAlz3l4@!-5Ri-0VbIi0I zFnaRp95Kls<*ztAm=5b}OLC&^t8ug2^_f)X1j1wX_;9`f%`t5>g>P_`u=S>9AjLM? zlzg;vp}>YVelE)dI}4Lg2JwQQ-6As)tlspy|mZ;}iOI z&TV5fcIheyFj}#4>tb7`%dhdl_pqB$dK&aTMhYJ@7x$E#A-!t|()AD+#?jBzIr)xP zMYPsn3a?1Q&=+StSHl|PvsNjT#^geNgDt}8`9q$)Rnhv^`>=YQ)Gl2~z>XO(qQRT#B8|+m-ThbmI%P zwDF_Q**!)eX{2P}6^X=10oPm z6d4fE&-H)VNdDh{h!m?sd!d~=fAgC+H{wJiL`uOzFk&5wf{-C_w*>VI5h0!RB>=%* z1sS-KtyH-j^CCSY4-tnOQOX_?gnJgr93&OVXxT-9sTy$;2mdnPC^26sq3=#8vG&N7 zu(JC1ZR(=dSvlW7o3}gVb?f=!x$AkmS=;^hffnf3c;hkD-t5w0=f(Z$#XaW5eJVhx ztzy5{$?Vk<{0$f0xAO4zju(G-beDDvk?kWehDQ7EKB4z3B|iTUf916A{l1>_2kuul z-naj^a@_aA-7et5PKCGal@Nb2Yxuk3`dewsr)Yol;u96V_Wdp-My0J}Uk1OGns;Zx zzOw*o4?qa=7fDC5C8wHGobl>>HM9()K{M&pu92cP2GcIe3xeLDs9HW+ zol*5XZVf;HOs!CvwpM26QCK=ZNd_`p8h6VSkB2y1%$M0^B=tq}trv}(;)@$garwI@ z^}nep61z@tV?nn|@!qTyX~=Jzh#6ATnvMvm_NMa?GXV^lY3DK66D4S=sj%@ezyOEP ztZ2VeUr zbdMsn>}K&)#@5rWa;`k+*ik`K%47tSuZ1SK->?&g_jL~5yIsvx`nWBcgZn|r(k*C% z);G%$?=!DvR&r$N5tJif-L_gYNz>W)YjN}=nBn9~G?ftzl)G2uU1bCevV$dDVXBzq zH4`z_@#o$bAI9c9tMyyS90@uO-Vjwjur$hxr_*#KINr{l{rJG zi}sQqDp?fm@gEJtIFIE+b>8uo5~J9>`jddtt<1f1$#Q$U0eP6tyUA2Ha|v+aT!GMRMB&( zJcgq{{M({IM;=F+2Q#r$%IypoCXMw*Xm>j!R*Vo{EMx&1myxnAcsZ*lzpOw&7WGg! z%i^~Nk|D*hQ^$c}G3{bjBK4YXoD%Q0H+V+Nl$qtT+2RV;4>8o8CsKVkJB3yW#mmDQ>P(=cUwIc3XZ6<_B&{i7Rc49x!ahPh zjjR)Rb!2@3%=2lfvlb5yxw6I)!gZRIUU3j(Lc>`qC#rz~L1qk`vM5P1)@2KOb(l;t zKyX`HG>)FBAwvR?5C)eSUJuunD5~ndqoQJ1iG$6j8m7Z;m1E%;r4|~UzPPW91zta3 zeeV>dKB5o6QGwwUVRt7%3!36+Q~zZIug2avt}?A5aS=H*6Hp~lNx{uoYuAOG<$`!Y z_rwvwUn^2JMz1olgOi0QV`6h|TwxO;gx20sUM^ARDu&U1!}6V8bfmn9_8u+c9x3w{ zIW3b3CO1RMoX+M<}tUNiK2rLh(tQNJgC}+<6Lt z%rmY-?i0=e<>!^K<1}+X@}j~&l0j01O5Pl-UrJRxA$W0tA$SSz@Oa`un8E9$rh8;! z<8Cwke(aT$82GSrC4MN_(4vaK0ERdNv@kMIQ#KsJ<^g|Xh8Kb>#Tx>os+q%WUmk<> z{m*+hrwuoIDS{1I%Qc{wIFKw+V$IX$v-E%+SIBqk+XfQ7}5ll&W5Mtt+8+sD!d=ft@x z5j&58I4UDxkWzu}7LI$uyDRRDs$T6d!f{259O@FeQ4q_8Ve0};3K&@V;_DQ84$56SIAoXgR2Is4xmnm4uv<27!}Vpx0Nu6 z9_N;tG)*Twj~|eo-8cE?)~|_jCC}U7A=&h)6u=tTnqI~Cq}8;E*RmAUwsPH}#Ie{N zBnTx-nf8|;@iw{Mc*5{+RUXN^`+5TkwXV;t!#-zWln^iG!-X@E`87v&hNaqI(LE9!x<(|NgWcl|R?Z4mtRO4GEtI}_9hHD{^ z(!6-O_Sk$0ik9VC-<|J%*ZIWP>GVLblRe@Lzc4;)Lzfk=&Q@K*YjmT!d|>V3z>h4) zSZY|kL5f!oyhaaVRIw9p4xKHX3MN0g^yoQKU(mD9Q{=PlzU2^8k$hm!_p-pG zPrs}ag9EVSQY8-Cti!gflW8f0|GO3neLM8=1`q zmy27($iSyebv@)gl7QUnZpmCqh4EX{qX8p7+6<>0FGl+zt4ugIJes-nh9H`~=7p3( zVR%8waqABMLP@^6R!LFLX(Y{$nzJ^;6}@drR=?6e7V*5sVjaALBj@bGxn@5z>NvHE zNnV9;*|36xBpxi$jy@Yw+}DvTYp5{-1_9O4b4R9SEObDrgs`y9?z>Q&!A8m;#UosS(aJ zFZ3Ho+$7Sk4Tu&#e6TW6Yh)Ln>1c7CZtj(E^%d`Sgtn6xe{&k zX}LDn{RP8j08&jTerRc?DEj_9%W)dt$A9ml2+;Oo4fx0f;My zXTudmy+Pk?y1*l+Cc+!<&ze~?Xt|E-J<}}DxjCtL;~G@s)-Nkv)aEk^in4np5PX?z z#mE`p^GypsfFK++Ru$xuKA&1YUPv^it^boaNJeP{?G>_eRu*$CwNGlw&BxUpYa8tU zwkm-G+jmE$P1C{gY1SD`w_F=Ob$*~~rX4(0K7e+lXVl?I`m#*Nf=h^%EcZChsM2cz z__R}Ardn^&k?Oy5-te-ih*$iE%`$rPh$p{~bU&@+EA{5}!Pm>9L-Zk~d}OXcTUqf+ zuV!G8YGi4AVALN4Zz`9UHdnBGw@lFd_|^Q10((j8o?$g@-oRc6eV6%4PZ=&r@CQYO zDcy#lyU_}TyL_z1^!6bn(hO6(@5b7PvG*luFK)M!;oTlNt005D*9G~iZ?;g5x{ z9e)t_@TjU)ySnw(GOM@JJ>Eb_%6TsNTCAQRVbr$X_N|qPQ%1s3AQc?5m0F@RM%$Ig zWpe@#p6fb@Z>;V&p!*&EX%BHe*0!O* zD-!;C(@J&Mfa4#7=a|aHC#lC1rw6YLv5uQ(dWHFXpQCkG}{G)1v{sBh2{)GqtcE zH1)j<2PVm#9}Y8G<*(_2jI6kDzQiaVe`xGE;-AEG>MNVj-BVTA;C(?pq}B_U{?HIob&ecS3|>oipFb7a}> zrG`c~%2rLhdr!TJP?OMs8Oz1|tO85x%W>%@t7`9@ibwSaibU@U^e+bCPbc9Oli?MP zBFnF7EP9USz$U}=c{O?9UOM%}_qUxWo+siT@M;GOZ^+-kkDJ6c5*YnbtyZ!#X4e220-RqL14}Pu>GgK# z%tGoHR~;R1li&Wbfck(~x3sl%?6UhC8S3ymt1B!Cqh~Qj$O;<3jOtYQa#(U7!bgAG z{U61Nnt(t;qn|2w_76gr`+r}Y`0p>OXkz*^l4V*rBSReciZ> zQ=GT_OtKi&kDw6A1T~>+T1keYz|a=~n}Z9Aw2rrEbZkd=;%@wl^qqRWi2_BOc^yJU z%r=KTg9ALAyq;Cc#q@B^-0ek`?X_nnQOJjFNZ;;w-njO7-n8%XcJ6M!KVbOTXg?H! zhk7mHJ(C6*?BMQCBlE|QbR*p8eZmup#or%d#jGBRX2mg`ghmx*M~x%{dvCtTvmnJO)G?uVulUenen#}+Wu9(r=jY>c;o17?z{57AJ zXB|$5UdB4OlVb6Z14umivYHjya_J%Yrd-9mHEWA-4^Y@uXx1aD z(5qUc0b?6HO_6}e(*lMGVKlhx{>*&N#f)nvt6F2;6l~I43F`{8_NjPuym%ZFsY+GBV)WW~lD7XJ$j?yNeMJSDCP~>c~9t^l6;xp4~9iUYy z&3oz+%3>^PzAi+LmRO`5{8Y`c9Fwk|$`tLqbwrQI%4z@<3TPBgO>HSGJOly`M z;nt`~H@y+aSNRd~*EECK?*uaF5qM>_sPduu@JBY$1a}LG3JTAu?d*9lccjOa+9ct#70R--8ByY69U@V;Xh@aX@fn(tIc@)lISXoO5!wKW^bXwwD+g=ZS=qxV z7PWk9kKQQxtM!E7{a0TSyzW!-vgMfr~>M-lU`8<>qVV!DA=INzykMcV>h5$U4l z!&b~Kteya`e*m0+Jb0d<(H!+T`EoE49LV}@QB=3q`mYc&-aB!w$hfuopra2yj$@5c zGHSQqcUY(U;#rJ^mL{URG_ay=<#?83m=AVFaj~iOZx^4#Sl0217`@);UwpnFE@R(+ zL5`({__p%t;PyCP+#!2A<>sf)xU5Qweo*l)ZtJQMe{hAYAP1^IdFevPHp78e!qG0p zGOoq^|LVtF50kHi%Bl0$)C1Gif3^)n-1AE9Q~nClTQm5W2)T#EwU;}i^P(aOJFSD& z%@Pdo$&Ry&H0?ZtoeH%)qn`B<+x=av!RRycScC@*{1LXjgc?7Bxh70N;8SsodYk`E zlrL%3J)|o17sY~c`tN`*q69Q!Siv2KCb=X}!hI*wmk{XRuOWqtUCMkYlz-3=6b8FG zZXiVNH;j{yMDzj+fs`1%2rV?f5itp&6Kq+vg^~sjx&<4UTU~*uACSUAJrRf{<$Sm_ z&kpS%H8QB^xy>g**~I$Z|3k!XEFJJ0>Sy9N5&{T__y14s{$uXwWa98Y^U(iC_OAY~ z*1xINS_@s1fS^b)MtF(?HHRSBeL$WWH4GRdV#c{k6|70>l@0itFkd3tZ?8MZ*TSej zA!70jGEp)fCsXOSUZ*U7o=0bGcY&h}xj;aL4N%gdaG2?uk*UQxDBNBS)w}A zA_PXep-Pww4|`%X@DZ^BT9lCBrZq;7O(l%+HYbn9*rw%MuK}HUSRJyt)hUlT=bD>6 z$7_toT)>x~aw)6aQ*p0}!>xRp6scobcdmG@N``;vHXr_At1344{ZZ`TiS2Q&FqKt7 zoz`p_OKyD_&^dfV(a>y&8JD`;YCh_*fSc&T2B?b6KX~ouoM<2JPz2VSZ4PA9+Rvf} zWmUvG+=@yoyYAhTB$>or5^@7y|`< z_u{HnrXepYTDz)8{Jd*1meE=H^#qcJ^F$3b2HpBajHA4812DwKoJ}6OeYrDk7>Q{f zHa&m<+bxPKWW^Du_%Phxo$k!dVhhaAxD4FApzKI36dxOmJQ^2|6FSanO(?rMrvL>aNhXh?%H@ETZZV zA$iV2Fxz08%(7sr@K?iGjICO9zY@~qI(#7Ej>o|?tn{Dk^i#!c0-`@R1Bv0BYnx@F zzpn5_mE|q~<%!&~Xx&!GkI$72CyqY@fe0f}Shy32jY~MFL#Xqm33dTT?uAf5ijX*t zfKz~p*UhiPyTS5|Xq|-F3g6%vN9GD%b6rcD+*4>cybzT`xu`9ooLWWVU$LRGLV!0wxvB-Ct;5;D(!VlG^WVlD zp^S1Zf>Ue1@V@&yiV;zT(4ha$4Cwozq3U-xTfX_ej zQ9~cJsf@0qS)pkHFkXxcyrAW1G)mluPG4cf2wRFJhp7$TQOoFTIxR($&eD9bZjpwk#WDTz!rRZHK6YV~;A#%@%xPkCsCecIYOumhYcf=} zR3qE;$PAFCKFZHCRGP*`J)&WQBm8+@0%g}xjaKw1)?ETivD0xEr@#5LT=6@OL2g6| zf{F9HQ{!4P9ql^l0##eufq8hCZP3nB4Z?S)N<-9I<<$D77mR%dH;*VPEPzNz8&`2I z&@VvuY22-3k1GW`AeBvW1QwiDJ^5a-pSFtHEt-Rc1*Tz)dFpGCo*8ULxEk}hsX$oC z(PpCzdt`k{WOG^W@nzKnseKtI`6PiD! zpj<`=VU*E>q6MkARvmNNheP|Ryl@`qd)^7iABYfVqn+p;n`8-oqq{Uab48xT8IIZ= zM$O>~>*i>UnMd3>bxy7!)<_+k&onPH9jbxGCV`jcAc)D2n?&*VP*TuHVF%R&QAkET z!g)~cZ~}b9oZl%JzTUY(A`SbVbzdsL{~Ih@{0PWN5t~Kf4vgeZ9t85tIG5TV;IT$2 zvW^)q67<`XN*j%NAJejgRoWL@QFdfo*FpsACBwa|&>{?B$JoN@3hky_~FkBK#>^;==b?)Kmi-G?x74A5|O2WF-aCDj+0`i zO$}*))Gu#rR9IIx->hwDcFqO26p+Q0M9^1jT3Rk!T$^HATK-&W$otPF+hQ$L21&Irse3kw@)pO!snuoKuhTILyf-lG0btNYPQOUJ59=N0AuY5``Zt%XIvNa)RDJ#_7HxHs1~=_9IZaXY3FEPs!N#| zPR+3qGg2$4gFTny5yQOY!mB(L!#;B+)!m$V7CmD!*i?(JH?lTv$0d9Bx)_J4Ut8eR z1rf5_spp5SiGY~-u(f|Idy_zMw4V*QP3W&n?c^$OR6Zp@)H^T!+r@&IF!aDRb6I4* z%oQ)5$$5UPyF))s;C}sB&^|GE8&BERm0F8&VGYnb+2O?KAWY4#j+>||{X=$O#Ehhg6irzK7c^d=6dUw9$cB|bymuWgBVV^M5SmHRpSOd0 zod99D)7Y(xw+Vo8eID;Wkg~F|!oG>S+GJyGu~X;mytpD(VjoAI10{l@1+rh14hjiI zg-S2kG+q5S`m)7#hYU5!nngqX5C@~Gy4u!kqoKszQ%6ZDa5#OnQ{pq#H*Gwc7llH} zWN=2nHV=>v6+;hR6IIO>2({Ild%cu$}^_r zhX6Y^EU3+vKiFFh^;4zuAjNE*#R2O_XjTZ91jHL70*FwStm3MgwfjI$a|vOB=(JfZ zoa@#RqAyR>rkx9F>e?>&Y zX-sU8Va#f;iMv?PP*2A^$h+WB-i_6XrXh|XT6vkd5Ha{mj4ZI%R{EJ~<7Z;Oti*1* z1^sEGQys@x_!EG5<^?qlf=5dLC$e&N4lM!*8Psx47lw46w_Ah3rEQ3fU_KV<@UYW~ zQI@h6ha{2n3SNs`Mh8a649dCiU>hW>5uk%uq;2<-4yeNh?w{I!n~v9sKf4(lo_8Av z&!iY|Q|j;LOW1KLI+K2*uAs2b1J@WA)6kM6W9}IIUFigfaSEqS!*5lp@-2M|Xoif3 z56rY588<1!6QtVWMR86y%>vMX&WA;`>P8+~2tYsI*BBQFJO53?{sn3;f8?^a5k-`p z7X8~}!|oCuvgSg|x;9OpwS2dpD7LL7gZy%6M}V7Yf4P>3jejR`z(dyf7tJ7N?0<{oFd7!bs53 z`Zvf%5*_X7Bp|RyT95e*_sLIC{EREmrf?I!LpX!`+@<7!bta=Or`LS$^NA~vPcAp` zL@xUs>N8I8{Y)y%WU#2YUOjIX1{gI|oDpHDQ+Z7H;d_GBxYic?iHMgig7$_t5CP?2 zeh`9xK-^9X&{7teK1P7t6>7wBvo~#j*%o_{!S=fOfuH>&CeiuI5zNigg8#?4Z8(Q{ z7TNY2-Y1H1^$j|(cUBJP1JnlwGpL`x=#SG^e81ddEWA%hE_)l$-lO9O>d_UpxD~Te zciW+bCun}1GZ#8n_ZTBbJt0SJ|Lh|y1h3#O$7|^a$&Eyyuh@U{fP8`D=?6vPJkfn8 zl+#s4#JydyaI-LQ2U6PS_xB#8+6`lWSbjzK_a3LF&EVjlht9K{xjx}Jq%k|CAf(34 zuH^Egy+rQfesKH1to+F)5H{V4jT|GCdwvozg7&4W+q~^cJAmk(Vmy>(etr3f==a@I zi$h0xUQ%zIMjYIBY zz1~vqt^&TMp}yj5Cx{`!e(Qt*yF(=Yb-Pi+1ncuL@X8)VDO+rg8k_gee3JTkM9B)_+WsCnTo(EK8o>FE;;e9gYu)I(VL`i+1 zV}xdb-1>(Q9it}?e%H1w(=9qDdh~nN7N`}f|K*37e`{(eyt}8G6_CY zCwRj&@#tilnFY@km6#{mSy?yaqni&y;1>*bsFEP4k;G6$|2mg0(0jIpVwLT-vBH#L z)`hYKBtEdPdc=@{vKV2IQ1dG}Rx2v2&)b9)nxce;lY8zpBV5ws>5vnNa(aKoI1m-C zfS1m@yOiYqDcMMDByY!>Ns%=X!Jf=3iYix2SJe14dC+#;sQhvgeHKd2;dH$SjC49Q zF7p)M=jAOV!q>sXNRF1(3Hk=BY_Q)7U$mZ3-q+y$@nA-o_?Rn1sOaRF9H5ow6#5Nc zteDBM;a$T?nDZA`c~vQUdYRUcu}g`ITXVuq;uY@1{VOAi>+oLgKT?9fSoI(S&410f z$q~_`8Hr)zERWzQj1$LhuJ6gu?=g|lQ98Uxar$J!=sv0qSJ$(?n=qz=Am!<_`ZUJ~ zOFImhzsV7ps)}}^@(eLpro9(^uk*@Fs#qZY@+ex*ZyH4Vqo2aiYClvX&^5o67$>5` zOYtWy+Sw@JCaZz9yk8|7VoY2;b$a+89}>DV9p7hoqeMKe67pPw+m>j!857Qqq0Xm~ z>Si1@BeIO=M^^(g&GD7<>(G;;Ct=e6!`C?li4wHgwr$(CZQHhS+O}=mwr$(CyHDHJ zX-`MY+=uyZ+#6Ak^;VG?^=0n8R(q}p%kfc${e~@wU;>0QIKZigX7|+t&HNwZ16UWa zc*(YW@6lXGeQ}^2Q!0=c3O&Q1evsDQ$~r|wRnx~?M(DkJ4H^&O%q-~#a>nch9Tkl% zrqwnjPHzgM$k+2O;D+!(N`90!Cs)Y{oCM4_PPC^<_Jj74)fxzwee-Ev zB(3U+^W=;~8jT>Cat!P0)7b>vyle8Gg#4oHnIQ2TDd^zpXNm=kffO2x@ zbU_ZPZOj7892^6k%=veKcw@(5oXE-(m#pIOk>YD_8?fi`9pgLJF%E z+r4-=T)X&9AKO-p6xyrhZsJ3%drrbKaiWI@8n2xFn~)-Y>Lr@agjJ*k5l2bR$Xsbl zWgd0uh`L<2^*QbpC#szg@}-@JA*kzL_fzbv{K1!U?5o%Px5c~6`xoD*=y{xPfy$31 zze@iFE@`i)Z$>ZBdmYt#-QgGZlfe5Iz;_{!x^wyH(jl-)F!`e46Zk^aD9qt`Er-M= zaO6>zxzmaPD{KKP4bVFpZ* z$E9B^Gx$X(UrWS8Mdq*qgqZpMho-WavpIXVfU6Q`puN1dA-E~nZ(%^)*Ign3) z`W%c4AI+Z7*(CvJ(k{RNn6$@kND1RIb;0e7!r-HJ5j+nh3MZ$xY{{65x7N4ZE3ntj zBDjhmDYn6i;JqD?>WgKj!o14CM;wJk!U@B)xa%c>dhC>|vu`wJ^^}jOnHj&h1K4?1 zufIYq^}5L7?6|`btlaz3IT~J3RNL^FFw^Y_1;;7G_y$peF<`b-NkU2L_yRMZ z$Qz<5Xhn96Tb9A~bw^aYbS^$7K~Kpkm$U@@)ZC~Rv$_VvTn2a~}7T-X!|=7vcGi=A2E! zKio7Wx}v-T=DgjZXJilaGxJNdcWd(VC?a#3;Vn*xjBAEbXv52F!wWXyMcn&Iki&DA z2;6oe+n*3bC)eR=ZiL>DrRYOLs{v&Ol}kcrq6{;jUm~nzp1WDC(><*wp7ob==jc-S zUT10Ht#t3GCsBlLtglL*HvlIh^d?7~a>~x{&yW^=#*}B-#>F)a)tZ>Ec5wq>d1_@Q z8adK@j~i-h0qhGdjDdQ>q=9f3=i+{g13}MuyVKoRPtSMYSai{eA(w?HC{1K)Pn$oYFjIn zN3#mrwRXJH78_2XuG(V;T^gkJm$ftD=H43nAwo+Ipd$>o>7M#4PwW9K5uieS;H*8M zfwX|X_z2YcpeuQTkLpm1Rw$)wh6{ECbN|@YzQOtK_5Z-wQL1DG4ETg^_yP6As&b?D zb_jfEh19wCf3x&{oYViEsC>oxf<4OvrT515Ix$#_Ti9D@y86K5A=`^r^3AZ_;X7*+|}^*ev| zLyoUG&UCdsp@~42vU~ejqolm;n!Do?06^a#|t0QroLE+3dD0?si(>6fJrd0_NL{{=tW26;Y}f=UflraT!*v=6&1S7t(&QUmN@%JzLGCp^=W*3?xFSzb zI$TAKV6xkiwwWK6DA*}PmW6|Ok*yNExl6IJ576Tk4rGIxqB>5$1x{IxSW9sKCgoCQ zlQKQQD}d`t$BJWNCjIm`OX4)EBAZ_h{hn53tWAk{PfYutt0($iMy&R+%HW%V9Gri- z)L0GmV!ke539sE4tpaYDk&DmV<9_hr5;;yGPK#|8Z7!wy4b#UlkMycDin3!D$zc=8 zo&!AQBnvlqxilF#MROY22F71TOEgGYz&C_=H*8`Z$Rt@fSD$jF$yaRX*-7q-I^SJevq(vC{qE zFaRm-pxzUhIXfH=jblTwrZ3Rf$DF=dTII0!ry*qaDPJE_z(+VM7G z*3Cp?#q(~M4E~~?>b-#JLI2#s#wU;Jy*%LO9PUS6R>zOfzkkI~-%;0_jO;UulQlg? zsGnYr_tbD|9cp|gSSmSnxNoNdkm2WBf}VVju<0bTQpi;#=4RQqXX}rh zxDQvGKE{b9SHVL^>f*iRjUBD9WEXW*3JIYHbu~+l_un5E;b`*)H$gg;vdUv!07+~` z1*1|_=L zEP~j8pO^#2t67k+7bR#M2o^HL3YlX>ys#qFz>$z8xdo-OB~aYm$v$jwvhj7@kHph} zPQ}r4OI(-TTP^2GQ# z`)#Io|2C~j|KB&Tzt(Ac6G!L&VJ(L!YD)tNV(=b%N^UJyU-{mbEEmS;MG-{i78eSg zIp~mMYnmD1hJ33EB0kN-pNWg^#U?5W!9VKGaqb1Y{qyz$uMb;+K}we=jt!xpDXmW) zWD?f7Z#5WK*X|zc@vka%GZCuD{D6tTgYRsX!IL1JAsjM2r@y)_)*;?7-XSn;rApzr zY`rAvK6&oPTjYbc_d*7C*p%e0<7kU)PO)p$C zPNz%}*PPWkw>^te#+;ywUR;mR0O3J=EyzzXN4RUOinfl*ypmvYE>31k6)A<{pM~N4 zpj*^%ND!GE!BB#+`f)cKhYgv%q}|5`D^sa0koZZ+myZk(^;Bt)NNf~V#lnm{T;4$# zEXc0u4peQ`L#VRu>-T6>Ni)g~_7{zm7SSFhQDYEHdghCHr!lC)nPAqIRb1iE#?QW| z5bqK>#%vg~yD!GI)evlh$AA#C6;H_7JK90~1HOdD8l-ty!yqsRsQ=n(Dli2vj139Y`u`U`3bM zydD`mVVWq@)rD+ohOH%laxZ`)F9Kp$5*bcAPeKY+u0uqH=k6bg9*&L|4g~c4)02@i zZOd+9{V|p0VYlnn{qxcL^GX`m?fS|q;#{erDS~aD9R?XfCXA9lG~&!Idq24*^yJb> zF7mqQ!{Z%Pws+KKN9pVrj+YPa;Z7l9Ha`UA!!2U+1Tp0k7AB7RZX1ra_^NU7!NXHJ z402{z zC!`|ZXHv0uf9Hjld$Nxi@{LezCj2D+u8bJUA9hCnq>h)Xd}c?eCGV$xhF^W12gOTY z-dxqx*4NciR@B#4N51G$oB!~lyNOrBSV|g-?PW710b_^6Qa2()Vnb_aw`N4iEAit< z+U3dC*4*}zx3;oCB_RUjuhO2U)ycI*bo$aJx~c8KDL)UCCsN$hX6IxU^@)PetkAiz zw6eCcxU$>V(^AI1xH7T#0E#L$GaS!IV=mccVX=_D3!#riI8U^uoN9_~3M5y#na^qI z279$wMX60BkwhhgU5zrU)Cm2 zKP|JNX(Y86eaS)TmFMC5f)|?T*q09_-e<_>dN``X+6~UN zM#Yz}?Gp_Ho`Shzw8c90x1%fFE)FA}b^#1r`(GxGOe)h3XG7RM?6R~@bTD8UC{E>b0G8x>`_M9lf=v%gWnAY;ipZwxbps7?8mcFtHAopR zs$|GFYRJen=+}NN|U(41HwplQ@GiQZGLJZe>d+t&>WdwXi&svRUSlCHFj`h2cW<3206(1pGviK-q7D{TW)sn8wxDyW@H+A)vXt4Pa4GF` z*g#9u0)`Z&r$iz8swaI<(GoT;^#XNOEHaT#XsRBuE)^~zVk&pxaw7TsIIZ6s97T~{ zDkzZxDik!i1v-Wemdz|$>8+{#Sb3syC32UFWm(;R$`}Cr5Kww$(FBN!LX6ak*|?rQ z757lk6+7uGxqQ0iSWC16q}~;{3^iJY3X^&mTGOi}CaP=Gz1cE6)#)Na)no`&)RID& z>6*y5LLF4-GgDQX;;emdxJ31H-0HuMd^)0XiARU3{=|+8_}3fd;fIOZ{WZKatGX>xj;5S)cd<@O>b8<(J2kIyEvRnc@J zkEr{BLz^aPn-kQj0};ozIT?ey;qp|YO1!mczu!>BU*09Oh# zCErUA$5WR7v>W6&SvBNbm;>hs2C6AQ(iSpX5bv_z+ubb(ziBRC&CHE{KKH(vPS4%X zXfx~`WVJ1N*BU+Gk}B{ig5LM&_PYHAXBF>tn>tmi1^yHVy(r=9=#}LIwF&da(-ru< zjrm78ya~r+b-yiXH|S1iIMzVCyu=sjuwVDO1eDxty6jf@i?zxU zfM|i2f>ea4`-;Ul>uPvee-nTj6ui4H`s4^&g}e(}`#Z=hXzg7^t$lpRnB+w2-bE6; z=L6Wad-!YJUaTYduCdEw~=~gcqEFo&;m0beLK@97qGR zU}@AP&?I+Y2v3L@YG?5Li$+NDQ6IHoP)r`mwL|wv8PNH)hI^pY&>KYB9ZJeIMSA{Q z7zI5IoFXSYw54rITNnVLhhysgonCaFiy@;Zv|DvXJ`|&5N?5r)e+^7sMlte{m5Y1K z-RkM@uUG7YD6)zVJhG8QS-hLF6urV^_g>iLqO`l23aSHW+VEB183nk)bLvh zL}uH;NgWZi&m5j-Sr}aG!N?}YH@mdkSiT`~?DQE;aUih*CIA=5w_ZQ0QdHyLjnmO# zJ@$8XeBfMrU^(>OBs6*PX-6HX1urL@Garfi%ktdaTj}_f+@&f~O^91gJH?Y{?& z*LMd18rS(xOwnJL0^sTd(!lGga(03$C;NY%!>8LMX|i^hb&d-!uROc3!yYO6{-IJS zon0X7k0$;F+vQ!hz=MxnnzTmB3_c#>Y_EsVyrcW)SRf-!*f0f71%6~B_xP8W^CAqO z@YdC2Zjgo{>Hfp;6L60e)qPDxU~S%uAXECSWgPhQ&kjIpN}BvaCGLJGD;=ZUyyS-S zS3P~n6fgDhcy7!Cw{VBzfh%p}#KNxlv>CwYie8%VZPD&CqrXK@WtqCm^8sKX{$m01!&6wXTJH)x5o%7e;)B`m=rUETg^E&LWYNYL)=)>{pEgGqwDmy)CESt2?4)1T}Iqa#iT}-jqcR|B`tW5V?9YRjH zrz%dCe!{R4#0e3{3&iHlcp@zc$`J2b(vV;gpCF;&W99;ta0g82SSe$_Xk3wK{(0Ef zA(N$M&66rO=OTMv7k)x=<(L5RWwb0Fd771>`;$6HWi666@5!DcF}$b!5lHc0>x%~H zm~=|*+X=OkQ~yS--jUOH;k>tY)XFWA>lzqS8f2zbpm^5-fjgj8pTaBV7Fe5QRG07o z;1$Jo%@38Izif2i+=4!%3g1278A3vz1=>f`;a|}Yx~Dt8FZj<1wIC$9r1&?$nD855 zr24<+o8KOXsfC$~U#aYY47Vm-eEM&DXlp^(e=~u zb=zr{_my+b`(g00?2T*jZ8!;>0fJ@ERr<>&Fl1-c!g2MJCRvWJYRU%o)b$6S=}kWLuvAODdT~ zM;z`qI3uf00TNpGQywE_RwAdlt%2kN@Q0o@p zS_WAjPO*7bNtuiUKZp=RlC)dVtecTLIsQ0MRr5eOeBv4$$j(`K6`E@1Kk~~tcG7K> zDudE3;p{iG4>|4pi$MVW!hb;9*#;8_cy()Vy!1^2i zu=dvfmSdZ*n+NvOZ>=4uD-b!3q6%N`VXhmc|Km3%R?IHWAWTpe z!r~LseIZ&o^48$|=~j zD*V?f#jL{Fvyx`Q%{5p&F#FPDQ=p-SrDzVrjo zd7dfTXTU(hMDu+NkSl!=Q*%hlx0zeKHT3aM0@8%3RCGg}>F<_LzfcF8&gnWVtfV)EE^*yCMJp;s1ZF|MwE_@rHEQ9zngy z=xB7I-J?l8B$=dYOc>WjOZ3MT!r79{b{}#?1GZ4G-au<0C7#fPup&&R6DSbC-UKpn zDi9Dx8zT&iVJb%n>Q=dyIBJIBR+%CA^G=43 zCyC<`7rt$R(%r+~*G6R@a^PIO5IybWq55&xPP~jD+d@LnO!V zGOux`hquc+Gs2LU%!ZIFrepQx;+WVcNkb+l=OXvWZs(Xd9sc_#SUJ`?K|O|2+<_@G z38>7u%bbiPAw-UIRJ6$?AxbXAm=iM$i!*nR=aX$fH0oGHf}FhL=np3;{KPWPc}m%t zW2UrR8gsjCsq*aNamBVP8@ZG7`Qd{Rx{qw?Q9-dvnn^k0?PVj5RH9RdX)fJq*Ab8h z7CCf|V*(vI_wjir&yc7~b^b_WAZYDTL+aUs44vj=MiYnTNuugv(bTb==FHH_S)*DS zb-sE>;-z}WpB$ZbV0S6$bmsr;*>jn3>w?KDEQP0-HmgF@ep zq2r!Tn5J!H4&;DFO>m#?YG}>~M+ccS2edBzG;Nm-*|aT}4&gNPb4PM@{pktP>K|z* zi7$0`SZEJSc>4}%JwpD=MD@uk_i)|r^s2|>(<9bw?_J8i{3&|JA$o^2E6$EsY}>zr z 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

ewb;D-r7XArVu8KG|V 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 f6l~YCbtn6nEB3w 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 OhYSiT6$(iBp#BHktRXf4 literal 0 HcmV?d00001 From 222a1363756975e00c7580f40db6ab3190457fcd Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 15:02:49 +0800 Subject: [PATCH 031/194] Update README.md --- cas/cas-server/README.md | 145 --------------------------------------- 1 file changed, 145 deletions(-) diff --git a/cas/cas-server/README.md b/cas/cas-server/README.md index b224738732..8b13789179 100644 --- a/cas/cas-server/README.md +++ b/cas/cas-server/README.md @@ -1,146 +1 @@ -CAS Overlay Template [![Build Status](https://travis-ci.org/apereo/cas-overlay-template.svg?branch=master)](https://travis-ci.org/apereo/cas-overlay-template) -======================= -Generic CAS WAR overlay to exercise the latest versions of CAS. This overlay could be freely used as a starting template for local CAS war overlays. - -# Versions - -- CAS `6.1.x` -- JDK `11` - -# Overview - -To build the project, use: - -```bash -# Use --refresh-dependencies to force-update SNAPSHOT versions -./gradlew[.bat] clean build -``` - -To see what commands are available to the build script, run: - -```bash -./gradlew[.bat] tasks -``` - -To launch into the CAS command-line shell: - -```bash -./gradlew[.bat] downloadShell runShell -``` - -To fetch and overlay a CAS resource or view, use: - -```bash -./gradlew[.bat] getResource -PresourceName=[resource-name] -``` - -To list all available CAS views and templates: - -```bash -./gradlew[.bat] listTemplateViews -``` - -To unzip and explode the CAS web application file and the internal resources jar: - -```bash -./gradlew[.bat] explodeWar -``` - -# Configuration - -- The `etc` directory contains the configuration files and directories that need to be copied to `/etc/cas/config`. - -```bash -./gradlew[.bat] copyCasConfiguration -``` - -- The specifics of the build are controlled using the `gradle.properties` file. - -## Adding Modules - -CAS modules may be specified under the `dependencies` block of the [Gradle build script](build.gradle): - -```gradle -dependencies { - compile "org.apereo.cas:cas-server-some-module:${project.casVersion}" - ... -} -``` - -To collect the list of all project modules and dependencies: - -```bash -./gradlew[.bat] allDependencies -``` - -### Clear Gradle Cache - -If you need to, on Linux/Unix systems, you can delete all the existing artifacts (artifacts and metadata) Gradle has downloaded using: - -```bash -# Only do this when absolutely necessary -rm -rf $HOME/.gradle/caches/ -``` - -Same strategy applies to Windows too, provided you switch `$HOME` to its equivalent in the above command. - -# Deployment - -- Create a keystore file `thekeystore` under `/etc/cas`. Use the password `changeit` for both the keystore and the key/certificate entries. This can either be done using the JDK's `keytool` utility or via the following command: - -```bash -./gradlew[.bat] createKeystore -``` - -- Ensure the keystore is loaded up with keys and certificates of the server. - -On a successful deployment via the following methods, CAS will be available at: - -* `https://cas.server.name:8443/cas` - -## Executable WAR - -Run the CAS web application as an executable WAR: - -```bash -./gradlew[.bat] run -``` - -Debug the CAS web application as an executable WAR: - -```bash -./gradlew[.bat] debug -``` - -Run the CAS web application as a *standalone* executable WAR: - -```bash -./gradlew[.bat] clean executable -``` - -## External - -Deploy the binary web application file `cas.war` after a successful build to a servlet container of choice. - -## Docker - -The following strategies outline how to build and deploy CAS Docker images. - -### Jib - -The overlay embraces the [Jib Gradle Plugin](https://github.com/GoogleContainerTools/jib) to provide easy-to-use out-of-the-box tooling for building CAS docker images. Jib is an open-source Java containerizer from Google that lets Java developers build containers using the tools they know. It is a container image builder that handles all the steps of packaging your application into a container image. It does not require you to write a Dockerfile or have Docker installed, and it is directly integrated into the overlay. - -```bash -./gradlew build jibDockerBuild -``` - -### Dockerfile - -You can also use the native Docker tooling and the provided `Dockerfile` to build and run CAS. - -```bash -chmod +x *.sh -./docker-build.sh -./docker-run.sh -``` From 911c746f23022890bcc39b2a1e936f7109dbae11 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 15:02:57 +0800 Subject: [PATCH 032/194] Delete README.md --- cas/cas-server/README.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 cas/cas-server/README.md diff --git a/cas/cas-server/README.md b/cas/cas-server/README.md deleted file mode 100644 index 8b13789179..0000000000 --- a/cas/cas-server/README.md +++ /dev/null @@ -1 +0,0 @@ - From c76c811b1cb72b71c8c127c9e3da41a731e4adff Mon Sep 17 00:00:00 2001 From: patkorek Date: Tue, 7 Apr 2020 10:23:15 +0200 Subject: [PATCH 033/194] BAEL-2660 few examples to convert String to Int --- .../strings/ConvertStringToInt.groovy | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy b/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy new file mode 100644 index 0000000000..40c53965a5 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy @@ -0,0 +1,92 @@ +package com.baeldung.strings + +import org.junit.Test + +import java.text.DecimalFormat + +import static org.junit.Assert.assertEquals +import static org.junit.Assert.assertNull + +class ConvertStringToInt { + + @Test + void givenString_thenConvertToIntegerUsingAsInteger() { + def stringNum = "123" + def invalidString = "123a" + Integer expectedInteger = 123 + Integer integerNum = stringNum as Integer + def intNum = invalidString?.isInteger() ? invalidString as Integer : null + + assertNull(null, intNum) + assertEquals(integerNum, expectedInteger) + } + + @Test + void givenString_thenConvertToIntUsingAsInt() { + def stringNum = "123" + int expectedInt = 123 + int intNum = stringNum as int + + assertEquals(intNum, expectedInt) + } + + @Test + void givenString_thenConvertToIntegerUsingToInteger() { + def stringNum = "123" + int expectedInt = 123 + int intNum = stringNum.toInteger() + + assertEquals(intNum, expectedInt) + } + + @Test + void givenString_thenConvertToIntegerUsingParseInt() { + def stringNum = "123" + int expectedInt = 123 + int intNum = Integer.parseInt(stringNum) + + assertEquals(intNum, expectedInt) + } + + @Test + void givenString_thenConvertToIntegerUsingValueOf() { + def stringNum = "123" + int expectedInt = 123 + int intNum = Integer.valueOf(stringNum) + + assertEquals(intNum, expectedInt) + } + + @Test + void givenString_thenConvertToIntegerUsingIntValue() { + def stringNum = "123" + int expectedInt = 123 + int intNum = new Integer(stringNum).intValue() + int secondIntNum = new Integer(stringNum) + + assertEquals(intNum, expectedInt) + assertEquals(secondIntNum, expectedInt) + } + + @Test + void givenString_thenConvertToIntegerUsingDecimalFormat() { + def stringNum = "123" + int expectedInt = 123 + DecimalFormat decimalFormat = new DecimalFormat("#") + int intNum = decimalFormat.parse(stringNum).intValue() + + assertEquals(intNum, expectedInt) + } + + @Test(expected = NumberFormatException.class) + void givenInvalidString_whenUsingAs_thenThrowNumberFormatException() { + def invalidString = "123a" + invalidString as Integer + } + + @Test(expected = NullPointerException.class) + void givenNullString_whenUsingToInteger_thenThrowNullPointerException() { + def invalidString = null + invalidString.toInteger() + } +} From 5e90298049ebf59769a0397e2cfebf14eabd3a8b Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 16:24:27 +0800 Subject: [PATCH 034/194] Update README.md --- libraries-3/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries-3/README.md b/libraries-3/README.md index f3c3375098..62bd3b9f66 100644 --- a/libraries-3/README.md +++ b/libraries-3/README.md @@ -15,4 +15,4 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m - [Introduction to the jcabi-aspects AOP Annotations Library](https://www.baeldung.com/java-jcabi-aspects) - [Introduction to Takes](https://www.baeldung.com/java-takes) - [Using NullAway to Avoid NullPointerExceptions](https://www.baeldung.com/java-nullaway) - +- [Introduction to Alibaba Arthas](https://www.baeldung.com/java-alibaba-arthas-intro) From 2ecd4cb204e6856476f5cf2b24877a591612248a Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 16:27:04 +0800 Subject: [PATCH 035/194] Update README.md --- persistence-modules/spring-boot-persistence-h2/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/persistence-modules/spring-boot-persistence-h2/README.md b/persistence-modules/spring-boot-persistence-h2/README.md index a0f9c67a33..d11ec1f409 100644 --- a/persistence-modules/spring-boot-persistence-h2/README.md +++ b/persistence-modules/spring-boot-persistence-h2/README.md @@ -1,4 +1,5 @@ ### Relevant Articles: - [Access the Same In-Memory H2 Database in Multiple Spring Boot Applications](https://www.baeldung.com/spring-boot-access-h2-database-multiple-apps) - [Spring Boot With H2 Database](https://www.baeldung.com/spring-boot-h2-database) -- [Hibernate @NotNull vs @Column(nullable = false)](https://www.baeldung.com/hibernate-notnull-vs-nullable) \ No newline at end of file +- [Hibernate @NotNull vs @Column(nullable = false)](https://www.baeldung.com/hibernate-notnull-vs-nullable) +- [Quick Guide to Hibernate enable_lazy_load_no_trans Property](https://www.baeldung.com/hibernate-lazy-loading-workaround) From fb594d2b2734aa68bdffaf636729f52461b9439c Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 16:30:42 +0800 Subject: [PATCH 036/194] Update README.md --- core-java-modules/core-java-io-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-io-2/README.md b/core-java-modules/core-java-io-2/README.md index 62461be0ff..84cabc5992 100644 --- a/core-java-modules/core-java-io-2/README.md +++ b/core-java-modules/core-java-io-2/README.md @@ -12,4 +12,5 @@ This module contains articles about core Java input and output (IO) - [Java – Append Data to a File](https://www.baeldung.com/java-append-to-file) - [How to Copy a File with Java](https://www.baeldung.com/java-copy-file) - [Create a Directory in Java](https://www.baeldung.com/java-create-directory) +- [Java IO vs NIO](https://www.baeldung.com/java-io-vs-nio) - [[<-- Prev]](/core-java-modules/core-java-io) From a59aa144001d35a75c7014eb03f7e0457e67161f Mon Sep 17 00:00:00 2001 From: patkorek Date: Tue, 7 Apr 2020 10:34:38 +0200 Subject: [PATCH 037/194] Renamed methods --- .../com/baeldung/strings/ConvertStringToInt.groovy | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy b/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy index 40c53965a5..3b179ee193 100644 --- a/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy +++ b/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy @@ -10,7 +10,7 @@ import static org.junit.Assert.assertNull class ConvertStringToInt { @Test - void givenString_thenConvertToIntegerUsingAsInteger() { + void givenString_whenUsingAsInteger_thenConvertToInteger() { def stringNum = "123" def invalidString = "123a" Integer expectedInteger = 123 @@ -22,7 +22,7 @@ class ConvertStringToInt { } @Test - void givenString_thenConvertToIntUsingAsInt() { + void givenString_whenUsingAsInt_thenConvertToInt() { def stringNum = "123" int expectedInt = 123 int intNum = stringNum as int @@ -31,7 +31,7 @@ class ConvertStringToInt { } @Test - void givenString_thenConvertToIntegerUsingToInteger() { + void givenString_whenUsingToInteger_thenConvertToInteger() { def stringNum = "123" int expectedInt = 123 int intNum = stringNum.toInteger() @@ -40,7 +40,7 @@ class ConvertStringToInt { } @Test - void givenString_thenConvertToIntegerUsingParseInt() { + void givenString_whenUsingParseInt_thenConvertToInteger() { def stringNum = "123" int expectedInt = 123 int intNum = Integer.parseInt(stringNum) @@ -49,7 +49,7 @@ class ConvertStringToInt { } @Test - void givenString_thenConvertToIntegerUsingValueOf() { + void givenString_whenUsingValueOf_thenConvertToInteger() { def stringNum = "123" int expectedInt = 123 int intNum = Integer.valueOf(stringNum) @@ -58,7 +58,7 @@ class ConvertStringToInt { } @Test - void givenString_thenConvertToIntegerUsingIntValue() { + void givenString_whenUsingIntValue_thenConvertToInteger() { def stringNum = "123" int expectedInt = 123 int intNum = new Integer(stringNum).intValue() @@ -69,7 +69,7 @@ class ConvertStringToInt { } @Test - void givenString_thenConvertToIntegerUsingDecimalFormat() { + void givenString_whenUsingDecimalFormat_thenConvertToInteger() { def stringNum = "123" int expectedInt = 123 DecimalFormat decimalFormat = new DecimalFormat("#") From c9847d5036664bd35d88332b33836e85e293249d Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 16:37:03 +0800 Subject: [PATCH 038/194] Create README.md --- linux-bash/functions/src/main/bash/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 linux-bash/functions/src/main/bash/README.md diff --git a/linux-bash/functions/src/main/bash/README.md b/linux-bash/functions/src/main/bash/README.md new file mode 100644 index 0000000000..5fb6958b9d --- /dev/null +++ b/linux-bash/functions/src/main/bash/README.md @@ -0,0 +1,3 @@ +### Relevant Articles + +- [Bash Functions in Linux](https://www.baeldung.com/linux/bash-functions) From 23a7314302d4f9bb1f7949d1b009f965cb43d340 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 16:39:13 +0800 Subject: [PATCH 039/194] Create README.md --- lombok/src/main/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 lombok/src/main/README.md diff --git a/lombok/src/main/README.md b/lombok/src/main/README.md new file mode 100644 index 0000000000..4092d8ce99 --- /dev/null +++ b/lombok/src/main/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Guide to the Linux wc Command](https://www.baeldung.com/linux/wc-command) From 4d9ae47da774264f984f77203e20a9908bd42d40 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 16:44:15 +0800 Subject: [PATCH 040/194] Create README.md --- linux-bash/read/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 linux-bash/read/README.md diff --git a/linux-bash/read/README.md b/linux-bash/read/README.md new file mode 100644 index 0000000000..56c1dd5b24 --- /dev/null +++ b/linux-bash/read/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Guide to the Linux read Command](https://www.baeldung.com/linux/read-command) From 850b02f07e04b3adebc27384ba8aad13c05945c6 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 16:48:21 +0800 Subject: [PATCH 041/194] Create README.md --- linux-bash/command-line-arguments/src/main/bash/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 linux-bash/command-line-arguments/src/main/bash/README.md diff --git a/linux-bash/command-line-arguments/src/main/bash/README.md b/linux-bash/command-line-arguments/src/main/bash/README.md new file mode 100644 index 0000000000..27d89fff99 --- /dev/null +++ b/linux-bash/command-line-arguments/src/main/bash/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [How to Use Command Line Arguments in a Bash Script](https://www.baeldung.com/linux/use-command-line-arguments-in-bash-script) From 1f6163f45cb9a0bf94cca287e5bfc0e4a765b779 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 16:49:44 +0800 Subject: [PATCH 042/194] Update README.md --- linux-bash/text/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-bash/text/README.md b/linux-bash/text/README.md index de99c1962a..20df2a33ec 100644 --- a/linux-bash/text/README.md +++ b/linux-bash/text/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Linux Commands – Remove All Text After X](https://www.baeldung.com/linux/tr-manipulate-strings) +- [Linux Commands for Appending Multiple Lines to a File](https://www.baeldung.com/linux/appending-multiple-lines-to-file2) From 83cf886628977eb17779e46eb2edcd3a13c367e4 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 16:56:28 +0800 Subject: [PATCH 043/194] Create README.md --- .../core-java-concurrency-collections-2/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 core-java-modules/core-java-concurrency-collections-2/README.md diff --git a/core-java-modules/core-java-concurrency-collections-2/README.md b/core-java-modules/core-java-concurrency-collections-2/README.md new file mode 100644 index 0000000000..91da6c623c --- /dev/null +++ b/core-java-modules/core-java-concurrency-collections-2/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Introduction to Lock Striping](https://www.baeldung.com/java-lock-stripping) From 073f9c9067e96c56fee2af7580174b56c9c95a8b Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 17:09:25 +0800 Subject: [PATCH 044/194] Create README.md --- core-scala/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 core-scala/README.md diff --git a/core-scala/README.md b/core-scala/README.md new file mode 100644 index 0000000000..72b583c22b --- /dev/null +++ b/core-scala/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Pattern Matching in Scala](https://www.baeldung.com/scala/pattern-matching) From 40825b6f1fd4896b868d08b95e86aed98109d3a7 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Tue, 7 Apr 2020 14:49:42 +0530 Subject: [PATCH 045/194] JAVA-1188: Moved modules to core-java-modules --- java-collections-maps-2/README.md | 16 - java-collections-maps-2/pom.xml | 79 ---- .../main/java/com/baeldung/map/Product.java | 133 ------- .../com/baeldung/map/convert/MapToString.java | 34 -- .../com/baeldung/map/convert/StringToMap.java | 21 -- .../baeldung/map/copyhashmap/CopyHashMap.java | 55 --- .../map/initialize/MapInitializer.java | 80 ----- .../baeldung/map/iteration/MapIteration.java | 74 ---- .../java/com/baeldung/map/mapmax/MapMax.java | 92 ----- .../com/baeldung/map/mergemaps/Employee.java | 60 ---- .../com/baeldung/map/mergemaps/MergeMaps.java | 105 ------ .../map/primitives/PrimitiveMaps.java | 69 ---- .../com/baeldung/map/sort/SortHashMap.java | 104 ------ .../com/baeldung/map/ProductUnitTest.java | 174 --------- .../map/convert/MapToStringUnitTest.java | 48 --- .../map/convert/StringToMapUnitTest.java | 23 -- .../map/copyhashmap/CopyHashMapUnitTest.java | 76 ---- .../baeldung/map/copyhashmap/Employee.java | 28 -- .../initialize/MapInitializerUnitTest.java | 27 -- .../baeldung/map/mapmax/MapMaxUnitTest.java | 58 --- .../map/weakhashmap/WeakHashMapUnitTest.java | 72 ---- java-collections-maps-3/README.md | 8 - java-collections-maps-3/pom.xml | 26 -- .../compare/HashMapComparisonUnitTest.java | 225 ------------ .../TreeMapVsHashMapUnitTest.java | 58 --- java-collections-maps/README.md | 16 - java-collections-maps/pom.xml | 35 -- .../main/java/com/baeldung/map/MapUtil.java | 44 --- .../src/main/java/com/baeldung/map/MyKey.java | 64 ---- .../com/baeldung/map/MyLinkedHashMap.java | 23 -- .../src/main/resources/logback.xml | 13 - .../baeldung/guava/GuavaBiMapUnitTest.java | 120 ------- .../baeldung/map/ImmutableMapUnitTest.java | 84 ----- .../com/baeldung/map/KeyCheckUnitTest.java | 27 -- .../map/MapMultipleValuesUnitTest.java | 119 ------- .../java/com/baeldung/map/MapUnitTest.java | 336 ------------------ .../com/baeldung/map/MapUtilUnitTest.java | 103 ------ .../baeldung/map/MultiValuedMapUnitTest.java | 227 ------------ 38 files changed, 2956 deletions(-) delete mode 100644 java-collections-maps-2/README.md delete mode 100644 java-collections-maps-2/pom.xml delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/Product.java delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java delete mode 100644 java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java delete mode 100644 java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java delete mode 100644 java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java delete mode 100644 java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java delete mode 100644 java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java delete mode 100644 java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java delete mode 100644 java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java delete mode 100644 java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java delete mode 100644 java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java delete mode 100644 java-collections-maps-3/README.md delete mode 100644 java-collections-maps-3/pom.xml delete mode 100644 java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java delete mode 100644 java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java delete mode 100644 java-collections-maps/README.md delete mode 100644 java-collections-maps/pom.xml delete mode 100644 java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java delete mode 100644 java-collections-maps/src/main/java/com/baeldung/map/MyKey.java delete mode 100644 java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java delete mode 100644 java-collections-maps/src/main/resources/logback.xml delete mode 100644 java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java delete mode 100644 java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java delete mode 100644 java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java delete mode 100644 java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java delete mode 100644 java-collections-maps/src/test/java/com/baeldung/map/MapUnitTest.java delete mode 100644 java-collections-maps/src/test/java/com/baeldung/map/MapUtilUnitTest.java delete mode 100644 java-collections-maps/src/test/java/com/baeldung/map/MultiValuedMapUnitTest.java diff --git a/java-collections-maps-2/README.md b/java-collections-maps-2/README.md deleted file mode 100644 index 2188960543..0000000000 --- a/java-collections-maps-2/README.md +++ /dev/null @@ -1,16 +0,0 @@ -## Java Collections Cookbooks and Examples - -This module contains articles about Map data structures in Java. - -### Relevant Articles: -- [Map of Primitives in Java](https://www.baeldung.com/java-map-primitives) -- [Copying a HashMap in Java](https://www.baeldung.com/java-copy-hashmap) -- [A Guide to Java HashMap](https://www.baeldung.com/java-hashmap) -- [Guide to WeakHashMap in Java](https://www.baeldung.com/java-weakhashmap) -- [Map to String Conversion in Java](https://www.baeldung.com/java-map-to-string-conversion) -- [Iterate over a Map in Java](https://www.baeldung.com/java-iterate-map) -- [Merging Two Maps with Java 8](https://www.baeldung.com/java-merge-maps) -- [Sort a HashMap in Java](https://www.baeldung.com/java-hashmap-sort) -- [Finding the Highest Value in a Java Map](https://www.baeldung.com/java-find-map-max) -- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) -- More articles: [[<-- prev]](/java-collections-maps) [[next -->]](/java-collections-maps-3) diff --git a/java-collections-maps-2/pom.xml b/java-collections-maps-2/pom.xml deleted file mode 100644 index a246559f61..0000000000 --- a/java-collections-maps-2/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - 4.0.0 - java-collections-maps-2 - 0.1.0-SNAPSHOT - java-collections-maps-2 - jar - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - - org.eclipse.collections - eclipse-collections - ${eclipse-collections.version} - - - net.sf.trove4j - trove4j - ${trove4j.version} - - - it.unimi.dsi - fastutil - ${fastutil.version} - - - colt - colt - ${colt.version} - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - org.apache.commons - commons-collections4 - ${commons-collections4.version} - - - one.util - streamex - ${streamex.version} - - - com.jayway.awaitility - awaitility - ${avaitility.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - - - - - 0.6.5 - 4.1 - 1.7.0 - 8.2.0 - 3.0.2 - 8.1.0 - 1.2.0 - 3.11.1 - - - \ No newline at end of file diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/Product.java b/java-collections-maps-2/src/main/java/com/baeldung/map/Product.java deleted file mode 100644 index 5559895730..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/Product.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.baeldung.map; - -import java.util.*; - -public class Product { - - private String name; - private String description; - private List tags; - - public Product(String name, String description) { - this.name = name; - this.description = description; - this.tags = new ArrayList<>(); - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - public List getTags() { - return tags; - } - - public Product addTagsOfOtherProdcut(Product product) { - this.tags.addAll(product.getTags()); - return this; - } - - @Override - public boolean equals(Object o) { - - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Product product = (Product) o; - return Objects.equals(name, product.name) && - Objects.equals(description, product.description); - } - - @Override - public int hashCode() { - return Objects.hash(name, description); - } - - public static void forEach() { - - HashMap productsByName = new HashMap<>(); - productsByName.forEach( (key, product) - -> System.out.println("Key: " + key + " Product:" + product.getDescription()) - //do something with the key and value - ); - - //Prior to Java 8: - for(Map.Entry entry : productsByName.entrySet()) { - Product product = entry.getValue(); - String key = entry.getKey(); - //do something with the key and value - } - } - - public static void getOrDefault() { - - HashMap productsByName = new HashMap<>(); - Product chocolate = new Product("chocolate", "something sweet"); - Product defaultProduct = productsByName.getOrDefault("horse carriage", chocolate); - Product bike = productsByName.getOrDefault("E-Bike", chocolate); - - //Prior to Java 8: - Product bike2 = productsByName.containsKey("E-Bike") - ? productsByName.get("E-Bike") - : chocolate; - Product defaultProduct2 = productsByName.containsKey("horse carriage") - ? productsByName.get("horse carriage") - : chocolate; - } - - public static void putIfAbsent() { - - HashMap productsByName = new HashMap<>(); - Product chocolate = new Product("chocolate", "something sweet"); - productsByName.putIfAbsent("E-Bike", chocolate); - - //Prior to Java 8: - if(productsByName.containsKey("E-Bike")) { - productsByName.put("E-Bike", chocolate); - } - } - - public static void merge() { - - HashMap productsByName = new HashMap<>(); - Product eBike2 = new Product("E-Bike", "A bike with a battery"); - eBike2.getTags().add("sport"); - productsByName.merge("E-Bike", eBike2, Product::addTagsOfOtherProdcut); - - //Prior to Java 8: - if(productsByName.containsKey("E-Bike")) { - productsByName.get("E-Bike").addTagsOfOtherProdcut(eBike2); - } else { - productsByName.put("E-Bike", eBike2); - } - } - - public static void compute() { - - HashMap productsByName = new HashMap<>(); - Product eBike2 = new Product("E-Bike", "A bike with a battery"); - - productsByName.compute("E-Bike", (k,v) -> { - if(v != null) { - return v.addTagsOfOtherProdcut(eBike2); - } else { - return eBike2; - } - }); - - //Prior to Java 8: - if(productsByName.containsKey("E-Bike")) { - productsByName.get("E-Bike").addTagsOfOtherProdcut(eBike2); - } else { - productsByName.put("E-Bike", eBike2); - } - } -} diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java b/java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java deleted file mode 100644 index d13be924ff..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.map.convert; - -import com.google.common.base.Joiner; -import org.apache.commons.lang3.StringUtils; - -import java.util.Map; -import java.util.stream.Collectors; - -public class MapToString { - - public static String convertWithIteration(Map map) { - StringBuilder mapAsString = new StringBuilder("{"); - for (Integer key : map.keySet()) { - mapAsString.append(key + "=" + map.get(key) + ", "); - } - mapAsString.delete(mapAsString.length()-2, mapAsString.length()).append("}"); - return mapAsString.toString(); - } - - public static String convertWithStream(Map map) { - String mapAsString = map.keySet().stream() - .map(key -> key + "=" + map.get(key)) - .collect(Collectors.joining(", ", "{", "}")); - return mapAsString; - } - - public static String convertWithGuava(Map map) { - return Joiner.on(",").withKeyValueSeparator("=").join(map); - } - - public static String convertWithApache(Map map) { - return StringUtils.join(map); - } -} diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java b/java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java deleted file mode 100644 index 416ba4dd9a..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.map.convert; - -import com.google.common.base.Splitter; - -import java.util.Arrays; -import java.util.Map; -import java.util.stream.Collectors; - -public class StringToMap { - - public static Map convertWithStream(String mapAsString) { - Map map = Arrays.stream(mapAsString.split(",")) - .map(entry -> entry.split("=")) - .collect(Collectors.toMap(entry -> entry[0], entry -> entry[1])); - return map; - } - - public static Map convertWithGuava(String mapAsString) { - return Splitter.on(',').withKeyValueSeparator('=').split(mapAsString); - } -} diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java b/java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java deleted file mode 100644 index cb18f3aa11..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.baeldung.map.copyhashmap; - -import org.apache.commons.lang3.SerializationUtils; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.stream.Collectors; - -public class CopyHashMap { - - public static HashMap copyUsingConstructor(HashMap originalMap) { - return new HashMap(originalMap); - } - - public static HashMap copyUsingClone(HashMap originalMap) { - return (HashMap) originalMap.clone(); - } - - public static HashMap copyUsingPut(HashMap originalMap) { - HashMap shallowCopy = new HashMap(); - Set> entries = originalMap.entrySet(); - for(Map.Entry mapEntry: entries) { - shallowCopy.put(mapEntry.getKey(), mapEntry.getValue()); - } - - return shallowCopy; - } - - public static HashMap copyUsingPutAll(HashMap originalMap) { - HashMap shallowCopy = new HashMap(); - shallowCopy.putAll(originalMap); - - return shallowCopy; - } - - public static HashMap copyUsingJava8Stream(HashMap originalMap) { - Set> entries = originalMap.entrySet(); - HashMap shallowCopy = (HashMap) entries - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - return shallowCopy; - } - - public static HashMap shallowCopy(HashMap originalMap) { - return (HashMap) originalMap.clone(); - } - - public static HashMap deepCopy(HashMap originalMap) { - return SerializationUtils.clone(originalMap); - } - -} diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java b/java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java deleted file mode 100644 index 4d63abcfd0..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.baeldung.map.initialize; - -import java.util.AbstractMap; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class MapInitializer { - - public static Map articleMapOne; - static { - articleMapOne = new HashMap<>(); - articleMapOne.put("ar01", "Intro to Map"); - articleMapOne.put("ar02", "Some article"); - } - - public static Map createSingletonMap() { - Map passwordMap = Collections.singletonMap("username1", "password1"); - return passwordMap; - - } - - public Map createEmptyMap() { - Map emptyMap = Collections.emptyMap(); - return emptyMap; - } - - public Map createUsingDoubleBrace() { - Map doubleBraceMap = new HashMap() { - - /** - * - */ - private static final long serialVersionUID = 1L; - - { - put("key1", "value1"); - put("key2", "value2"); - } - }; - return doubleBraceMap; - } - - public Map createMapUsingStreamStringArray() { - Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, }) - .collect(Collectors.toMap(data -> data[0], data -> data[1])); - - return map; - } - - public Map createMapUsingStreamObjectArray() { - Map map = Stream.of(new Object[][] { { "data1", 1 }, { "data2", 2 }, }) - .collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1])); - - return map; - } - - public Map createMapUsingStreamSimpleEntry() { - Map map = Stream.of(new AbstractMap.SimpleEntry<>("idea", 1), new AbstractMap.SimpleEntry<>("mobile", 2)) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - return map; - } - - public Map createMapUsingStreamSimpleImmutableEntry() { - Map map = Stream.of(new AbstractMap.SimpleImmutableEntry<>("idea", 1), new AbstractMap.SimpleImmutableEntry<>("mobile", 2)) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - return map; - } - - public Map createImmutableMapWithStreams() { - Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, }) - .collect(Collectors.collectingAndThen(Collectors.toMap(data -> data[0], data -> data[1]), Collections:: unmodifiableMap)); - return map; - - } -} diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java b/java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java deleted file mode 100644 index b0c32e1487..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.baeldung.map.iteration; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -public class MapIteration { - - public static void main(String[] args) { - MapIteration mapIteration = new MapIteration(); - Map map = new HashMap<>(); - - map.put("One", 1); - map.put("Three", 3); - map.put("Two", 2); - - System.out.println("Iterating Keys of Map Using KeySet"); - mapIteration.iterateKeys(map); - - System.out.println("Iterating Map Using Entry Set"); - mapIteration.iterateUsingEntrySet(map); - - System.out.println("Iterating Using Iterator and Map Entry"); - mapIteration.iterateUsingIteratorAndEntry(map); - - System.out.println("Iterating Using KeySet and For Each"); - mapIteration.iterateUsingKeySetAndForeach(map); - - System.out.println("Iterating Map Using Lambda Expression"); - mapIteration.iterateUsingLambda(map); - - System.out.println("Iterating Using Stream API"); - mapIteration.iterateUsingStreamAPI(map); - } - - public void iterateUsingEntrySet(Map map) { - for (Map.Entry entry : map.entrySet()) { - System.out.println(entry.getKey() + ":" + entry.getValue()); - } - } - - public void iterateUsingLambda(Map map) { - map.forEach((k, v) -> System.out.println((k + ":" + v))); - } - - public void iterateUsingIteratorAndEntry(Map map) { - Iterator> iterator = map.entrySet() - .iterator(); - while (iterator.hasNext()) { - Map.Entry pair = iterator.next(); - System.out.println(pair.getKey() + ":" + pair.getValue()); - } - } - - public void iterateUsingKeySetAndForeach(Map map) { - for (String key : map.keySet()) { - System.out.println(key + ":" + map.get(key)); - } - } - - public void iterateUsingStreamAPI(Map map) { - map.entrySet() - .stream() - .forEach(e -> System.out.println(e.getKey() + ":" + e.getValue())); - } - - public void iterateKeys(Map map) { - for (String key : map.keySet()) { - System.out.println(key); - } - - } - -} \ No newline at end of file diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java b/java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java deleted file mode 100644 index 8c33c857ee..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.baeldung.map.mapmax; - -import java.util.*; -import java.util.Map.Entry; - -public class MapMax { - - public > V maxUsingIteration(Map map) { - - Map.Entry maxEntry = null; - - for (Map.Entry entry : map.entrySet()) { - - if (maxEntry == null || entry.getValue() - .compareTo(maxEntry.getValue()) > 0) { - maxEntry = entry; - } - } - - return maxEntry.getValue(); - } - - public > V maxUsingCollectionsMax(Map map) { - - Entry maxEntry = Collections.max(map.entrySet(), new Comparator>() { - public int compare(Entry e1, Entry e2) { - return e1.getValue() - .compareTo(e2.getValue()); - } - }); - - return maxEntry.getValue(); - } - - public > V maxUsingCollectionsMaxAndLambda(Map map) { - - Entry maxEntry = Collections.max(map.entrySet(), (Entry e1, Entry e2) -> e1.getValue() - .compareTo(e2.getValue())); - - return maxEntry.getValue(); - } - - public > V maxUsingCollectionsMaxAndMethodReference(Map map) { - - Entry maxEntry = Collections.max(map.entrySet(), Comparator.comparing(Map.Entry::getValue)); - - return maxEntry.getValue(); - } - - public > V maxUsingStreamAndLambda(Map map) { - - Optional> maxEntry = map.entrySet() - .stream() - .max((Entry e1, Entry e2) -> e1.getValue() - .compareTo(e2.getValue())); - - return maxEntry.get() - .getValue(); - } - - public > V maxUsingStreamAndMethodReference(Map map) { - - Optional> maxEntry = map.entrySet() - .stream() - .max(Comparator.comparing(Map.Entry::getValue)); - - return maxEntry.get() - .getValue(); - } - - public static void main(String[] args) { - - Map map = new HashMap(); - - map.put(1, 3); - map.put(2, 4); - map.put(3, 5); - map.put(4, 6); - map.put(5, 7); - - MapMax mapMax = new MapMax(); - - System.out.println(mapMax.maxUsingIteration(map)); - System.out.println(mapMax.maxUsingCollectionsMax(map)); - System.out.println(mapMax.maxUsingCollectionsMaxAndLambda(map)); - System.out.println(mapMax.maxUsingCollectionsMaxAndMethodReference(map)); - System.out.println(mapMax.maxUsingStreamAndLambda(map)); - System.out.println(mapMax.maxUsingStreamAndMethodReference(map)); - - } - -} diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java b/java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java deleted file mode 100644 index d7fb0d1a1d..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.baeldung.map.mergemaps; - -public class Employee implements Comparable { - - private Long id; - private String name; - - public Employee(Long id, String name) { - this.name = name; - this.id = id; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Employee employee = (Employee) o; - - if (!id.equals(employee.id)) return false; - return name.equals(employee.name); - - } - - @Override - public int hashCode() { - int result = id.hashCode(); - result = 31 * result + name.hashCode(); - return result; - } - - @Override - public String toString() { - return "Employee{" + - "id=" + id + - ", name='" + name + '\'' + - '}'; - } - - @Override - public int compareTo(Employee employee) { - return (int)(this.id - employee.getId()); - } -} diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java b/java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java deleted file mode 100644 index 4f187bad90..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.baeldung.map.mergemaps; - -import one.util.streamex.EntryStream; - -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class MergeMaps { - - private static Map map1 = new HashMap<>(); - private static Map map2 = new HashMap<>(); - - public static void main(String[] args) { - - initialize(); - - mergeFunction(); - - streamConcat(); - - streamOf(); - - streamEx(); - - streamMerge(); - } - - private static void streamMerge() { - - Map map3 = map2.entrySet() - .stream() - .collect( - Collectors.toMap( - Map.Entry::getKey, - Map.Entry::getValue, - (v1, v2) -> new Employee(v1.getId(), v2.getName()), - () -> new HashMap<>(map1) - ) - ); - - System.out.println(map3); - } - - private static void streamEx() { - Map map3 = EntryStream.of(map1) - .append(EntryStream.of(map2)) - .toMap((e1, e2) -> e1); - - System.out.println(map3); - - } - - private static void streamOf() { - Map map3 = Stream.of(map1, map2) - .flatMap(map -> map.entrySet().stream()) - .collect( - Collectors.toMap( - Map.Entry::getKey, - Map.Entry::getValue, - (v1, v2) -> new Employee(v1.getId(), v2.getName()) - ) - ); - - map3.entrySet().forEach(System.out::println); - } - - private static void streamConcat() { - Map result = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream()).collect(Collectors.toMap( - Map.Entry::getKey, - Map.Entry::getValue, - (value1, value2) -> new Employee(value2.getId(), value1.getName()) - )); - - result.entrySet().forEach(System.out::println); - } - - private static void mergeFunction() { - Map map3 = new HashMap<>(map1); - - map2.forEach( - (key, value) -> map3.merge(key, value, (v1, v2) -> - new Employee(v1.getId(), v2.getName())) - ); - - map3.entrySet().forEach(System.out::println); - } - - - private static void initialize() { - Employee employee1 = new Employee(1L, "Henry"); - map1.put(employee1.getName(), employee1); - Employee employee2 = new Employee(22L, "Annie"); - map1.put(employee2.getName(), employee2); - Employee employee3 = new Employee(8L, "John"); - map1.put(employee3.getName(), employee3); - - Employee employee4 = new Employee(2L, "George"); - map2.put(employee4.getName(), employee4); - Employee employee5 = new Employee(3L, "Henry"); - map2.put(employee5.getName(), employee5); - } - -} diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java b/java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java deleted file mode 100644 index 30bec12ccc..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.baeldung.map.primitives; - -import cern.colt.map.AbstractIntDoubleMap; -import cern.colt.map.OpenIntDoubleHashMap; -import gnu.trove.map.TDoubleIntMap; -import gnu.trove.map.hash.TDoubleIntHashMap; -import it.unimi.dsi.fastutil.ints.Int2BooleanMap; -import it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap; -import it.unimi.dsi.fastutil.ints.Int2BooleanSortedMap; -import it.unimi.dsi.fastutil.ints.Int2BooleanSortedMaps; -import org.eclipse.collections.api.map.primitive.ImmutableIntIntMap; -import org.eclipse.collections.api.map.primitive.MutableIntIntMap; -import org.eclipse.collections.api.map.primitive.MutableObjectDoubleMap; -import org.eclipse.collections.impl.factory.primitive.IntIntMaps; -import org.eclipse.collections.impl.factory.primitive.ObjectDoubleMaps; - -public class PrimitiveMaps { - - public static void main(String[] args) { - - eclipseCollectionsMap(); - troveMap(); - coltMap(); - fastutilMap(); - } - - private static void fastutilMap() { - Int2BooleanMap int2BooleanMap = new Int2BooleanOpenHashMap(); - int2BooleanMap.put(1, true); - int2BooleanMap.put(7, false); - int2BooleanMap.put(4, true); - - boolean value = int2BooleanMap.get(1); - - Int2BooleanSortedMap int2BooleanSorted = Int2BooleanSortedMaps.EMPTY_MAP; - } - - private static void coltMap() { - AbstractIntDoubleMap map = new OpenIntDoubleHashMap(); - map.put(1, 4.5); - double value = map.get(1); - } - - private static void eclipseCollectionsMap() { - MutableIntIntMap mutableIntIntMap = IntIntMaps.mutable.empty(); - mutableIntIntMap.addToValue(1, 1); - - ImmutableIntIntMap immutableIntIntMap = IntIntMaps.immutable.empty(); - - MutableObjectDoubleMap dObject = ObjectDoubleMaps.mutable.empty(); - dObject.addToValue("price", 150.5); - dObject.addToValue("quality", 4.4); - dObject.addToValue("stability", 0.8); - } - - private static void troveMap() { - double[] doubles = new double[] {1.2, 4.5, 0.3}; - int[] ints = new int[] {1, 4, 0}; - - TDoubleIntMap doubleIntMap = new TDoubleIntHashMap(doubles, ints); - - doubleIntMap.put(1.2, 22); - doubleIntMap.put(4.5, 16); - - doubleIntMap.adjustValue(1.2, 1); - doubleIntMap.adjustValue(4.5, 4); - doubleIntMap.adjustValue(0.3, 7); - } -} diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java b/java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java deleted file mode 100644 index 14610ffb00..0000000000 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.baeldung.map.sort; - -import com.baeldung.map.mergemaps.Employee; -import com.google.common.base.Functions; -import com.google.common.collect.ImmutableSortedMap; -import com.google.common.collect.Ordering; - -import java.util.*; -import java.util.stream.Collectors; - -public class SortHashMap { - - private static Map map = new HashMap<>(); - - public static void main(String[] args) { - - initialize(); - - treeMapSortByKey(); - - arrayListSortByValue(); - arrayListSortByKey(); - - sortStream(); - - sortGuava(); - - addDuplicates(); - - treeSetByKey(); - treeSetByValue(); - - } - - private static void sortGuava() { - final Ordering naturalOrdering = - Ordering.natural().onResultOf(Functions.forMap(map, null)); - - System.out.println(ImmutableSortedMap.copyOf(map, naturalOrdering)); - } - - private static void sortStream() { - map.entrySet().stream() - .sorted(Map.Entry.comparingByKey().reversed()) - .forEach(System.out::println); - - Map result = map.entrySet().stream() - .sorted(Map.Entry.comparingByValue()) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, - (oldValue, newValue) -> oldValue, LinkedHashMap::new)); - - result.entrySet().forEach(System.out::println); - } - - private static void treeSetByValue() { - SortedSet values = new TreeSet<>(map.values()); - System.out.println(values); - } - - private static void treeSetByKey() { - SortedSet keysSet = new TreeSet<>(map.keySet()); - System.out.println(keysSet); - } - - private static void treeMapSortByKey() { - TreeMap sorted = new TreeMap<>(map); - sorted.putAll(map); - - sorted.entrySet().forEach(System.out::println); - - } - - private static void arrayListSortByValue() { - List employeeById = new ArrayList<>(map.values()); - - Collections.sort(employeeById); - - System.out.println(employeeById); - } - - private static void arrayListSortByKey() { - List employeeByKey = new ArrayList<>(map.keySet()); - Collections.sort(employeeByKey); - System.out.println(employeeByKey); - } - - private static void initialize() { - Employee employee1 = new Employee(1L, "Mher"); - map.put(employee1.getName(), employee1); - Employee employee2 = new Employee(22L, "Annie"); - map.put(employee2.getName(), employee2); - Employee employee3 = new Employee(8L, "John"); - map.put(employee3.getName(), employee3); - Employee employee4 = new Employee(2L, "George"); - map.put(employee4.getName(), employee4); - } - - private static void addDuplicates() { - Employee employee5 = new Employee(1L, "Mher"); - map.put(employee5.getName(), employee5); - Employee employee6 = new Employee(22L, "Annie"); - map.put(employee6.getName(), employee6); - } -} diff --git a/java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java b/java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java deleted file mode 100644 index ba29d5c454..0000000000 --- a/java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java +++ /dev/null @@ -1,174 +0,0 @@ -package com.baeldung.map; - -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -import static org.junit.jupiter.api.Assertions.*; - -class ProductUnitTest { - - - @Test - public void getExistingValue() { - HashMap productsByName = new HashMap<>(); - - Product eBike = new Product("E-Bike", "A bike with a battery"); - Product roadBike = new Product("Road bike", "A bike for competition"); - - productsByName.put(eBike.getName(), eBike); - productsByName.put(roadBike.getName(), roadBike); - - Product nextPurchase = productsByName.get("E-Bike"); - - assertEquals("A bike with a battery", nextPurchase.getDescription()); - } - - @Test - public void getNonExistingValue() { - HashMap productsByName = new HashMap<>(); - - Product eBike = new Product("E-Bike", "A bike with a battery"); - Product roadBike = new Product("Road bike", "A bike for competition"); - - productsByName.put(eBike.getName(), eBike); - productsByName.put(roadBike.getName(), roadBike); - - Product nextPurchase = productsByName.get("Car"); - - assertNull(nextPurchase); - } - - @Test - public void getExistingValueAfterSameKeyInsertedTwice() { - HashMap productsByName = new HashMap<>(); - - Product eBike = new Product("E-Bike", "A bike with a battery"); - Product roadBike = new Product("Road bike", "A bike for competition"); - Product newEBike = new Product("E-Bike", "A bike with a better battery"); - - productsByName.put(eBike.getName(), eBike); - productsByName.put(roadBike.getName(), roadBike); - productsByName.put(newEBike.getName(), newEBike); - - Product nextPurchase = productsByName.get("E-Bike"); - - assertEquals("A bike with a better battery", nextPurchase.getDescription()); - } - - @Test - public void getExistingValueWithNullKey() { - HashMap productsByName = new HashMap<>(); - - Product defaultProduct = new Product("Chocolate", "At least buy chocolate"); - - productsByName.put(null, defaultProduct); - productsByName.put(defaultProduct.getName(), defaultProduct); - - Product nextPurchase = productsByName.get(null); - assertEquals("At least buy chocolate", nextPurchase.getDescription()); - - nextPurchase = productsByName.get("Chocolate"); - assertEquals("At least buy chocolate", nextPurchase.getDescription()); - } - - @Test - public void insertSameObjectWithDifferentKey() { - HashMap productsByName = new HashMap<>(); - - Product defaultProduct = new Product("Chocolate", "At least buy chocolate"); - - productsByName.put(null, defaultProduct); - productsByName.put(defaultProduct.getName(), defaultProduct); - - assertSame(productsByName.get(null), productsByName.get("Chocolate")); - } - - @Test - public void checkIfKeyExists() { - HashMap productsByName = new HashMap<>(); - - Product eBike = new Product("E-Bike", "A bike with a battery"); - - productsByName.put(eBike.getName(), eBike); - - assertTrue(productsByName.containsKey("E-Bike")); - } - - @Test - public void checkIfValueExists() { - HashMap productsByName = new HashMap<>(); - - Product eBike = new Product("E-Bike", "A bike with a battery"); - - productsByName.put(eBike.getName(), eBike); - - assertTrue(productsByName.containsValue(eBike)); - } - - @Test - public void removeExistingKey() { - HashMap productsByName = new HashMap<>(); - - Product eBike = new Product("E-Bike", "A bike with a battery"); - Product roadBike = new Product("Road bike", "A bike for competition"); - - productsByName.put(eBike.getName(), eBike); - productsByName.put(roadBike.getName(), roadBike); - - productsByName.remove("E-Bike"); - - assertNull(productsByName.get("E-Bike")); - } - - @Test - public void givenMutableKeyWhenKeyChangeThenValueNotFound() { - // Given - MutableKey key = new MutableKey("initial"); - - Map items = new HashMap<>(); - items.put(key, "success"); - - // When - key.setName("changed"); - - // Then - assertNull(items.get(key)); - } - - static class MutableKey { - private String name; - - public MutableKey(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MutableKey that = (MutableKey) o; - return Objects.equals(name, that.name); - } - - @Override - public int hashCode() { - return Objects.hash(name); - } - } - -} diff --git a/java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java b/java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java deleted file mode 100644 index 4517dea328..0000000000 --- a/java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.map.convert; - -import org.apache.commons.collections4.MapUtils; -import org.junit.Assert; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.Map; - -public class MapToStringUnitTest { - - private Map wordsByKey = new HashMap<>(); - - @BeforeEach - public void setup() { - wordsByKey.clear(); - wordsByKey.put(1, "one"); - wordsByKey.put(2, "two"); - wordsByKey.put(3, "three"); - wordsByKey.put(4, "four"); - } - - @Test - public void givenMap_WhenUsingIteration_ThenResultingMapIsCorrect() { - String mapAsString = MapToString.convertWithIteration(wordsByKey); - Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); - } - - @Test - public void givenMap_WhenUsingStream_ThenResultingMapIsCorrect() { - String mapAsString = MapToString.convertWithStream(wordsByKey); - Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); - } - - @Test - public void givenMap_WhenUsingGuava_ThenResultingMapIsCorrect() { - String mapAsString = MapToString.convertWithGuava(wordsByKey); - Assert.assertEquals("1=one,2=two,3=three,4=four", mapAsString); - } - - @Test - public void givenMap_WhenUsingApache_ThenResultingMapIsCorrect() { - String mapAsString = MapToString.convertWithApache(wordsByKey); - Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); - MapUtils.debugPrint(System.out, "Map as String", wordsByKey); - } -} \ No newline at end of file diff --git a/java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java b/java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java deleted file mode 100644 index 2f80b30871..0000000000 --- a/java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.map.convert; - -import org.junit.Assert; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -public class StringToMapUnitTest { - - @Test - public void givenString_WhenUsingStream_ThenResultingStringIsCorrect() { - Map wordsByKey = StringToMap.convertWithStream("1=one,2=two,3=three,4=four"); - Assert.assertEquals(4, wordsByKey.size()); - Assert.assertEquals("one", wordsByKey.get("1")); - } - - @Test - void givenString_WhenUsingGuava_ThenResultingStringIsCorrect() { - Map wordsByKey = StringToMap.convertWithGuava("1=one,2=two,3=three,4=four"); - Assert.assertEquals(4, wordsByKey.size()); - Assert.assertEquals("one", wordsByKey.get("1")); - } -} \ No newline at end of file diff --git a/java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java b/java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java deleted file mode 100644 index e2d5e327e1..0000000000 --- a/java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.baeldung.map.copyhashmap; - -import com.google.common.collect.ImmutableMap; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - -public class CopyHashMapUnitTest { - - @Test - public void givenHashMap_whenShallowCopy_thenCopyisNotSameAsOriginal() { - - HashMap map = new HashMap<>(); - Employee emp1 = new Employee("John"); - Employee emp2 = new Employee("Norman"); - map.put("emp1",emp1); - map.put("emp2",emp2); - - HashMap shallowCopy = CopyHashMap.shallowCopy(map); - - assertThat(shallowCopy).isNotSameAs(map); - - } - - @Test - public void givenHashMap_whenShallowCopyModifyingOriginalObject_thenCopyShouldChange() { - - HashMap map = new HashMap<>(); - Employee emp1 = new Employee("John"); - Employee emp2 = new Employee("Norman"); - map.put("emp1",emp1); - map.put("emp2",emp2); - - HashMap shallowCopy = CopyHashMap.shallowCopy(map); - - emp1.setName("Johny"); - - assertThat(shallowCopy.get("emp1")).isEqualTo(map.get("emp1")); - - } - - @Test - public void givenHashMap_whenDeepCopyModifyingOriginalObject_thenCopyShouldNotChange() { - - HashMap map = new HashMap<>(); - Employee emp1 = new Employee("John"); - Employee emp2 = new Employee("Norman"); - map.put("emp1",emp1); - map.put("emp2",emp2); - HashMap deepCopy = CopyHashMap.deepCopy(map); - - emp1.setName("Johny"); - - assertThat(deepCopy.get("emp1")).isNotEqualTo(map.get("emp1")); - - } - - @Test - public void givenImmutableMap_whenCopyUsingGuava_thenCopyShouldNotChange() { - Employee emp1 = new Employee("John"); - Employee emp2 = new Employee("Norman"); - - Map map = ImmutableMap. builder() - .put("emp1",emp1) - .put("emp2",emp2) - .build(); - Map shallowCopy = ImmutableMap.copyOf(map); - - assertThat(shallowCopy).isSameAs(map); - - } - -} diff --git a/java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java b/java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java deleted file mode 100644 index 5db55c26ea..0000000000 --- a/java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.map.copyhashmap; - -import java.io.Serializable; - -public class Employee implements Serializable{ - - private String name; - - public Employee(String name) { - super(); - this.name = name; - } - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String toString() { - return this.name; - } - -} - - diff --git a/java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java b/java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java deleted file mode 100644 index 7c6dffe787..0000000000 --- a/java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.map.initialize; - -import org.junit.Test; - -import java.util.Map; - -import static org.junit.Assert.assertEquals; - -public class MapInitializerUnitTest { - - @Test - public void givenStaticMap_whenUpdated_thenCorrect() { - - MapInitializer.articleMapOne.put("NewArticle1", "Convert array to List"); - - assertEquals(MapInitializer.articleMapOne.get("NewArticle1"), "Convert array to List"); - - } - - @Test(expected=UnsupportedOperationException.class) - public void givenSingleTonMap_whenEntriesAdded_throwsException() { - - Map map = MapInitializer.createSingletonMap(); - map.put("username2", "password2"); - } - -} diff --git a/java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java b/java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java deleted file mode 100644 index 30b945bfc8..0000000000 --- a/java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.baeldung.map.mapmax; - - -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertEquals; - -public class MapMaxUnitTest { - - Map map = null; - MapMax mapMax = null; - - - @Before - public void setupTestData() { - map = new HashMap(); - map.put(23, 12); - map.put(46, 24); - map.put(27, 38); - mapMax = new MapMax(); - } - - @Test - public void givenMap_whenIterated_thenReturnMaxValue() { - assertEquals(new Integer(38), mapMax.maxUsingIteration(map)); - } - - @Test - public void givenMap_whenUsingCollectionsMax_thenReturnMaxValue() { - assertEquals(new Integer(38), mapMax.maxUsingCollectionsMax(map)); - } - - @Test - public void givenMap_whenUsingCollectionsMaxAndLambda_thenReturnMaxValue() { - assertEquals(new Integer(38), mapMax.maxUsingCollectionsMaxAndLambda(map)); - } - - @Test - public void givenMap_whenUsingCollectionsMaxAndMethodReference_thenReturnMaxValue() { - assertEquals(new Integer(38), mapMax.maxUsingCollectionsMaxAndMethodReference(map)); - } - - @Test - public void givenMap_whenUsingStreamAndLambda_thenReturnMaxValue() { - assertEquals(new Integer(38), mapMax.maxUsingStreamAndLambda(map)); - } - - @Test - public void givenMap_whenUsingStreamAndMethodReference_thenReturnMaxValue() { - assertEquals(new Integer(38), mapMax.maxUsingStreamAndMethodReference (map)); - } - - -} diff --git a/java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java b/java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java deleted file mode 100644 index 293f24c378..0000000000 --- a/java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.baeldung.map.weakhashmap; - - -import org.junit.Test; - -import java.util.WeakHashMap; -import java.util.concurrent.TimeUnit; - -import static com.jayway.awaitility.Awaitility.await; -import static org.junit.Assert.assertTrue; - -public class WeakHashMapUnitTest { - - @Test - public void givenWeakHashMap_whenCacheValueThatHasNoReferenceToIt_GCShouldReclaimThatObject() { - //given - WeakHashMap map = new WeakHashMap<>(); - BigImage bigImage = new BigImage("image_id"); - UniqueImageName imageName = new UniqueImageName("name_of_big_image"); - - map.put(imageName, bigImage); - assertTrue(map.containsKey(imageName)); - - //when big image key is not reference anywhere - imageName = null; - System.gc(); - - //then GC will finally reclaim that object - await().atMost(10, TimeUnit.SECONDS).until(map::isEmpty); - } - - @Test - public void givenWeakHashMap_whenCacheValueThatHasNoReferenceToIt_GCShouldReclaimThatObjectButLeaveReferencedObject() { - //given - WeakHashMap map = new WeakHashMap<>(); - BigImage bigImageFirst = new BigImage("foo"); - UniqueImageName imageNameFirst = new UniqueImageName("name_of_big_image"); - - BigImage bigImageSecond = new BigImage("foo_2"); - UniqueImageName imageNameSecond = new UniqueImageName("name_of_big_image_2"); - - map.put(imageNameFirst, bigImageFirst); - map.put(imageNameSecond, bigImageSecond); - assertTrue(map.containsKey(imageNameFirst)); - assertTrue(map.containsKey(imageNameSecond)); - - //when - imageNameFirst = null; - System.gc(); - - //then - await().atMost(10, TimeUnit.SECONDS).until(() -> map.size() == 1); - await().atMost(10, TimeUnit.SECONDS).until(() -> map.containsKey(imageNameSecond)); - } - - - class BigImage { - public final String imageId; - - BigImage(String imageId) { - this.imageId = imageId; - } - } - - class UniqueImageName { - public final String imageName; - - UniqueImageName(String imageName) { - this.imageName = imageName; - } - } -} diff --git a/java-collections-maps-3/README.md b/java-collections-maps-3/README.md deleted file mode 100644 index 886461a35c..0000000000 --- a/java-collections-maps-3/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## Java Collections Cookbooks and Examples - -This module contains articles about Map data structures in Java. - -### Relevant Articles: -- [Java TreeMap vs HashMap](https://www.baeldung.com/java-treemap-vs-hashmap) -- [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps) -- More articles: [[<-- prev]](/java-collections-maps-2) diff --git a/java-collections-maps-3/pom.xml b/java-collections-maps-3/pom.xml deleted file mode 100644 index 30b0d01528..0000000000 --- a/java-collections-maps-3/pom.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - 4.0.0 - java-collections-maps-3 - 0.1.0-SNAPSHOT - java-collections-maps-3 - jar - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - - - - - - - - \ No newline at end of file diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java deleted file mode 100644 index 0edd0cd87b..0000000000 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java +++ /dev/null @@ -1,225 +0,0 @@ -package com.baeldung.map.compare; - -import com.google.common.base.Equivalence; -import com.google.common.collect.MapDifference; -import com.google.common.collect.MapDifference.ValueDifference; -import com.google.common.collect.Maps; -import org.junit.Before; -import org.junit.Test; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.collection.IsMapContaining.hasEntry; -import static org.hamcrest.collection.IsMapContaining.hasKey; -import static org.junit.Assert.*; - -public class HashMapComparisonUnitTest { - - Map asiaCapital1; - Map asiaCapital2; - Map asiaCapital3; - - Map asiaCity1; - Map asiaCity2; - Map asiaCity3; - - @Before - public void setup(){ - asiaCapital1 = new HashMap(); - asiaCapital1.put("Japan", "Tokyo"); - asiaCapital1.put("South Korea", "Seoul"); - - asiaCapital2 = new HashMap(); - asiaCapital2.put("South Korea", "Seoul"); - asiaCapital2.put("Japan", "Tokyo"); - - asiaCapital3 = new HashMap(); - asiaCapital3.put("Japan", "Tokyo"); - asiaCapital3.put("China", "Beijing"); - - asiaCity1 = new HashMap(); - asiaCity1.put("Japan", new String[] { "Tokyo", "Osaka" }); - asiaCity1.put("South Korea", new String[] { "Seoul", "Busan" }); - - asiaCity2 = new HashMap(); - asiaCity2.put("South Korea", new String[] { "Seoul", "Busan" }); - asiaCity2.put("Japan", new String[] { "Tokyo", "Osaka" }); - - asiaCity3 = new HashMap(); - asiaCity3.put("Japan", new String[] { "Tokyo", "Osaka" }); - asiaCity3.put("China", new String[] { "Beijing", "Hong Kong" }); - } - - @Test - public void whenCompareTwoHashMapsUsingEquals_thenSuccess() { - assertTrue(asiaCapital1.equals(asiaCapital2)); - assertFalse(asiaCapital1.equals(asiaCapital3)); - } - - @Test - public void whenCompareTwoHashMapsWithArrayValuesUsingEquals_thenFail() { - assertFalse(asiaCity1.equals(asiaCity2)); - } - - @Test - public void whenCompareTwoHashMapsUsingStreamAPI_thenSuccess() { - assertTrue(areEqual(asiaCapital1, asiaCapital2)); - assertFalse(areEqual(asiaCapital1, asiaCapital3)); - } - - @Test - public void whenCompareTwoHashMapsWithArrayValuesUsingStreamAPI_thenSuccess() { - assertTrue(areEqualWithArrayValue(asiaCity1, asiaCity2)); - assertFalse(areEqualWithArrayValue(asiaCity1, asiaCity3)); - } - - @Test - public void whenCompareTwoHashMapKeys_thenSuccess() { - assertTrue(asiaCapital1.keySet().equals(asiaCapital2.keySet())); - assertFalse(asiaCapital1.keySet().equals(asiaCapital3.keySet())); - } - - @Test - public void whenCompareTwoHashMapKeyValuesUsingStreamAPI_thenSuccess() { - Map asiaCapital3 = new HashMap(); - asiaCapital3.put("Japan", "Tokyo"); - asiaCapital3.put("South Korea", "Seoul"); - asiaCapital3.put("China", "Beijing"); - - Map asiaCapital4 = new HashMap(); - asiaCapital4.put("South Korea", "Seoul"); - asiaCapital4.put("Japan", "Osaka"); - asiaCapital4.put("China", "Beijing"); - - Map result = areEqualKeyValues(asiaCapital3, asiaCapital4); - - assertEquals(3, result.size()); - assertThat(result, hasEntry("Japan", false)); - assertThat(result, hasEntry("South Korea", true)); - assertThat(result, hasEntry("China", true)); - } - - @Test - public void givenDifferentMaps_whenGetDiffUsingGuava_thenSuccess() { - Map asia1 = new HashMap(); - asia1.put("Japan", "Tokyo"); - asia1.put("South Korea", "Seoul"); - asia1.put("India", "New Delhi"); - - Map asia2 = new HashMap(); - asia2.put("Japan", "Tokyo"); - asia2.put("China", "Beijing"); - asia2.put("India", "Delhi"); - - MapDifference diff = Maps.difference(asia1, asia2); - Map> entriesDiffering = diff.entriesDiffering(); - - assertFalse(diff.areEqual()); - assertEquals(1, entriesDiffering.size()); - assertThat(entriesDiffering, hasKey("India")); - assertEquals("New Delhi", entriesDiffering.get("India").leftValue()); - assertEquals("Delhi", entriesDiffering.get("India").rightValue()); - } - - @Test - public void givenDifferentMaps_whenGetEntriesOnOneSideUsingGuava_thenSuccess() { - Map asia1 = new HashMap(); - asia1.put("Japan", "Tokyo"); - asia1.put("South Korea", "Seoul"); - asia1.put("India", "New Delhi"); - - Map asia2 = new HashMap(); - asia2.put("Japan", "Tokyo"); - asia2.put("China", "Beijing"); - asia2.put("India", "Delhi"); - - MapDifference diff = Maps.difference(asia1, asia2); - Map entriesOnlyOnRight = diff.entriesOnlyOnRight(); - Map entriesOnlyOnLeft = diff.entriesOnlyOnLeft(); - - assertEquals(1, entriesOnlyOnRight.size()); - assertThat(entriesOnlyOnRight, hasEntry("China", "Beijing")); - assertEquals(1, entriesOnlyOnLeft.size()); - assertThat(entriesOnlyOnLeft, hasEntry("South Korea", "Seoul")); - } - - @Test - public void givenDifferentMaps_whenGetCommonEntriesUsingGuava_thenSuccess() { - Map asia1 = new HashMap(); - asia1.put("Japan", "Tokyo"); - asia1.put("South Korea", "Seoul"); - asia1.put("India", "New Delhi"); - - Map asia2 = new HashMap(); - asia2.put("Japan", "Tokyo"); - asia2.put("China", "Beijing"); - asia2.put("India", "Delhi"); - - MapDifference diff = Maps.difference(asia1, asia2); - Map entriesInCommon = diff.entriesInCommon(); - - assertEquals(1, entriesInCommon.size()); - assertThat(entriesInCommon, hasEntry("Japan", "Tokyo")); - } - - @Test - public void givenSimilarMapsWithArrayValue_whenCompareUsingGuava_thenFail() { - MapDifference diff = Maps.difference(asiaCity1, asiaCity2); - assertFalse(diff.areEqual()); - } - - @Test - public void givenSimilarMapsWithArrayValue_whenCompareUsingGuavaEquivalence_thenSuccess() { - Equivalence eq = new Equivalence() { - @Override - protected boolean doEquivalent(String[] a, String[] b) { - return Arrays.equals(a, b); - } - - @Override - protected int doHash(String[] value) { - return value.hashCode(); - } - }; - - MapDifference diff = Maps.difference(asiaCity1, asiaCity2, eq); - assertTrue(diff.areEqual()); - - diff = Maps.difference(asiaCity1, asiaCity3, eq); - assertFalse(diff.areEqual()); - } - - // =========================================================================== - - private boolean areEqual(Map first, Map second) { - if (first.size() != second.size()) { - return false; - } - - return first.entrySet() - .stream() - .allMatch(e -> e.getValue() - .equals(second.get(e.getKey()))); - } - - private boolean areEqualWithArrayValue(Map first, Map second) { - if (first.size() != second.size()) { - return false; - } - - return first.entrySet() - .stream() - .allMatch(e -> Arrays.equals(e.getValue(), second.get(e.getKey()))); - } - - private Map areEqualKeyValues(Map first, Map second) { - return first.entrySet() - .stream() - .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().equals(second.get(e.getKey())))); - } - -} diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java deleted file mode 100644 index 1057e3b9f0..0000000000 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.baeldung.map.treemaphashmap; - -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -public class TreeMapVsHashMapUnitTest { - - @Test - public void whenInsertObjectsTreeMap_thenNaturalOrder() { - Map treemap = new TreeMap<>(); - treemap.put(3, "TreeMap"); - treemap.put(2, "vs"); - treemap.put(1, "HashMap"); - Assert.assertThat(treemap.keySet(), Matchers.contains(1, 2, 3)); - } - - @Test(expected = NullPointerException.class) - public void whenInsertNullInTreeMap_thenException() { - Map treemap = new TreeMap<>(); - treemap.put(null, "NullPointerException"); - } - - @Test - public void whenInsertObjectsHashMap_thenRandomOrder() { - Map hashmap = new HashMap<>(); - hashmap.put(3, "TreeMap"); - hashmap.put(2, "vs"); - hashmap.put(1, "HashMap"); - Assert.assertThat(hashmap.keySet(), Matchers.containsInAnyOrder(1, 2, 3)); - } - - @Test - public void whenInsertNullInHashMap_thenInsertsNull() { - Map hashmap = new HashMap<>(); - hashmap.put(null, null); - Assert.assertNull(hashmap.get(null)); - } - - @Test - public void givenHashMapAndTreeMap_whenputDuplicates_thenOnlyUnique() { - Map treeMap = new HashMap<>(); - treeMap.put(1, "Baeldung"); - treeMap.put(1, "Baeldung"); - - Assert.assertTrue(treeMap.size() == 1); - - Map treeMap2 = new TreeMap<>(); - treeMap2.put(1, "Baeldung"); - treeMap2.put(1, "Baeldung"); - - Assert.assertTrue(treeMap2.size() == 1); - } -} \ No newline at end of file diff --git a/java-collections-maps/README.md b/java-collections-maps/README.md deleted file mode 100644 index 8fa6fa32fa..0000000000 --- a/java-collections-maps/README.md +++ /dev/null @@ -1,16 +0,0 @@ -## Java Collections Cookbooks and Examples - -This module contains articles about Map data structures in Java. - -### Relevant Articles: -- [Guide to the Guava BiMap](https://www.baeldung.com/guava-bimap) -- [A Guide to Java HashMap](https://www.baeldung.com/java-hashmap) -- [A Guide to LinkedHashMap in Java](https://www.baeldung.com/java-linked-hashmap) -- [A Guide to TreeMap in Java](https://www.baeldung.com/java-treemap) -- [How to Store Duplicate Keys in a Map in Java?](https://www.baeldung.com/java-map-duplicate-keys) -- [Get the Key for a Value from a Java Map](https://www.baeldung.com/java-map-key-from-value) -- [How to Check If a Key Exists in a Map](https://www.baeldung.com/java-map-key-exists) -- [Immutable Map Implementations in Java](https://www.baeldung.com/java-immutable-maps) -- [Guide to Apache Commons MultiValuedMap](https://www.baeldung.com/apache-commons-multi-valued-map) -- [The Java HashMap Under the Hood](https://www.baeldung.com/java-hashmap-advanced) -- More articles: [[next -->]](/java-collections-maps-2) diff --git a/java-collections-maps/pom.xml b/java-collections-maps/pom.xml deleted file mode 100644 index 38cf1c38ad..0000000000 --- a/java-collections-maps/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - 4.0.0 - java-collections-maps - 0.1.0-SNAPSHOT - java-collections-maps - jar - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - - org.apache.commons - commons-collections4 - ${commons-collections4.version} - - - org.assertj - assertj-core - ${assertj.version} - test - - - - - 4.1 - 3.6.1 - - diff --git a/java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java b/java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java deleted file mode 100644 index 91b7197a92..0000000000 --- a/java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * - */ -package com.baeldung.map; - -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.stream.Stream; - -/** - * @author swpraman - * - */ -public class MapUtil { - - public static Stream keys(Map map, V value) { - return map.entrySet() - .stream() - .filter(entry -> value.equals(entry.getValue())) - .map(Map.Entry::getKey); - } - - public static Set getKeys(Map map, V value) { - Set keys = new HashSet<>(); - for (Entry entry : map.entrySet()) { - if (entry.getValue().equals(value)) { - keys.add(entry.getKey()); - } - } - return keys; - } - - public static K getKey(Map map, V value) { - for (Entry entry : map.entrySet()) { - if (entry.getValue().equals(value)) { - return entry.getKey(); - } - } - return null; - } - -} diff --git a/java-collections-maps/src/main/java/com/baeldung/map/MyKey.java b/java-collections-maps/src/main/java/com/baeldung/map/MyKey.java deleted file mode 100644 index 9993d7862c..0000000000 --- a/java-collections-maps/src/main/java/com/baeldung/map/MyKey.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.baeldung.map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MyKey { - private static final Logger LOG = LoggerFactory.getLogger(MyKey.class); - - private String name; - private int id; - - public MyKey(int id, String name) { - this.id = id; - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - @Override - public int hashCode() { - LOG.debug("Calling hashCode()"); - return id; - } - - @Override - public String toString() { - return "MyKey [name=" + name + ", id=" + id + "]"; - } - - @Override - public boolean equals(Object obj) { - LOG.debug("Calling equals() for key: " + obj); - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - MyKey other = (MyKey) obj; - if (id != other.id) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } - -} diff --git a/java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java b/java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java deleted file mode 100644 index b687e57d85..0000000000 --- a/java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.map; - -import java.util.LinkedHashMap; -import java.util.Map; - -public class MyLinkedHashMap extends LinkedHashMap { - - /** - * - */ - private static final long serialVersionUID = 1L; - private static final int MAX_ENTRIES = 5; - - public MyLinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { - super(initialCapacity, loadFactor, accessOrder); - } - - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - return size() > MAX_ENTRIES; - } - -} diff --git a/java-collections-maps/src/main/resources/logback.xml b/java-collections-maps/src/main/resources/logback.xml deleted file mode 100644 index 7d900d8ea8..0000000000 --- a/java-collections-maps/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java deleted file mode 100644 index b44d2db1aa..0000000000 --- a/java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.baeldung.guava; - -import static org.junit.Assert.*; -import java.util.HashMap; -import java.util.Map; -import org.junit.Test; -import com.google.common.collect.BiMap; -import com.google.common.collect.EnumHashBiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.ImmutableBiMap; - -public class GuavaBiMapUnitTest { - @Test - public void whenQueryByValue_returnsKey() { - final BiMap capitalCountryBiMap = HashBiMap.create(); - capitalCountryBiMap.put("New Delhi", "India"); - capitalCountryBiMap.put("Washingon, D.C.", "USA"); - capitalCountryBiMap.put("Moscow", "Russia"); - - final String countryCapitalName = capitalCountryBiMap.inverse().get("India"); - - assertEquals("New Delhi", countryCapitalName); - } - - @Test - public void whenCreateBiMapFromExistingMap_returnsKey() { - final Map capitalCountryMap = new HashMap<>(); - capitalCountryMap.put("New Delhi", "India"); - capitalCountryMap.put("Washingon, D.C.", "USA"); - capitalCountryMap.put("Moscow", "Russia"); - final BiMap capitalCountryBiMap = HashBiMap.create(capitalCountryMap); - - final String countryCapitalName = capitalCountryBiMap.inverse().get("India"); - - assertEquals("New Delhi", countryCapitalName); - } - - @Test - public void whenQueryByKey_returnsValue() { - final BiMap capitalCountryBiMap = HashBiMap.create(); - - capitalCountryBiMap.put("New Delhi", "India"); - capitalCountryBiMap.put("Washingon, D.C.", "USA"); - capitalCountryBiMap.put("Moscow", "Russia"); - - assertEquals("USA", capitalCountryBiMap.get("Washingon, D.C.")); - } - - @Test(expected = IllegalArgumentException.class) - public void whenSameValueIsPresent_throwsException() { - final BiMap capitalCountryBiMap = HashBiMap.create(); - - capitalCountryBiMap.put("New Delhi", "India"); - capitalCountryBiMap.put("Washingon, D.C.", "USA"); - capitalCountryBiMap.put("Moscow", "Russia"); - capitalCountryBiMap.put("Trump", "USA"); - } - - @Test - public void givenSameValueIsPresent_whenForcePut_completesSuccessfully() { - final BiMap capitalCountryBiMap = HashBiMap.create(); - - capitalCountryBiMap.put("New Delhi", "India"); - capitalCountryBiMap.put("Washingon, D.C.", "USA"); - capitalCountryBiMap.put("Moscow", "Russia"); - capitalCountryBiMap.forcePut("Trump", "USA"); - - assertEquals("USA", capitalCountryBiMap.get("Trump")); - assertEquals("Trump", capitalCountryBiMap.inverse().get("USA")); - } - - @Test - public void whenSameKeyIsPresent_replacesAlreadyPresent() { - final BiMap capitalCountryBiMap = HashBiMap.create(); - - capitalCountryBiMap.put("New Delhi", "India"); - capitalCountryBiMap.put("Washingon, D.C.", "USA"); - capitalCountryBiMap.put("Moscow", "Russia"); - capitalCountryBiMap.put("Washingon, D.C.", "HongKong"); - - assertEquals("HongKong", capitalCountryBiMap.get("Washingon, D.C.")); - } - - @Test - public void whenUsingImmutableBiMap_allowsPutSuccessfully() { - final BiMap capitalCountryBiMap = new ImmutableBiMap.Builder().put("New Delhi", "India").put("Washingon, D.C.", "USA").put("Moscow", "Russia").build(); - - assertEquals("USA", capitalCountryBiMap.get("Washingon, D.C.")); - } - - @Test(expected = UnsupportedOperationException.class) - public void whenUsingImmutableBiMap_doesntAllowRemove() { - final BiMap capitalCountryBiMap = new ImmutableBiMap.Builder().put("New Delhi", "India").put("Washingon, D.C.", "USA").put("Moscow", "Russia").build(); - - capitalCountryBiMap.remove("New Delhi"); - } - - @Test(expected = UnsupportedOperationException.class) - public void whenUsingImmutableBiMap_doesntAllowPut() { - final BiMap capitalCountryBiMap = new ImmutableBiMap.Builder().put("New Delhi", "India").put("Washingon, D.C.", "USA").put("Moscow", "Russia").build(); - - capitalCountryBiMap.put("New York", "USA"); - } - - private enum Operation { - ADD, SUBTRACT, MULTIPLY, DIVIDE - } - - @Test - public void whenUsingEnumAsKeyInMap_replacesAlreadyPresent() { - final BiMap operationStringBiMap = EnumHashBiMap.create(Operation.class); - - operationStringBiMap.put(Operation.ADD, "Add"); - operationStringBiMap.put(Operation.SUBTRACT, "Subtract"); - operationStringBiMap.put(Operation.MULTIPLY, "Multiply"); - operationStringBiMap.put(Operation.DIVIDE, "Divide"); - - assertEquals("Divide", operationStringBiMap.get(Operation.DIVIDE)); - } -} \ No newline at end of file diff --git a/java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java deleted file mode 100644 index d308aac7eb..0000000000 --- a/java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.baeldung.map; - -import com.google.common.collect.ImmutableMap; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; - - -public class ImmutableMapUnitTest { - - @Test - public void whenCollectionsUnModifiableMapMethod_thenOriginalCollectionChangesReflectInUnmodifiableMap() { - - Map mutableMap = new HashMap<>(); - mutableMap.put("USA", "North America"); - - Map unmodifiableMap = Collections.unmodifiableMap(mutableMap); - assertThrows(UnsupportedOperationException.class, () -> unmodifiableMap.put("Canada", "North America")); - - mutableMap.remove("USA"); - assertFalse(unmodifiableMap.containsKey("USA")); - - mutableMap.put("Mexico", "North America"); - assertTrue(unmodifiableMap.containsKey("Mexico")); - } - - @Test - @SuppressWarnings("deprecation") - public void whenGuavaImmutableMapFromCopyOfMethod_thenOriginalCollectionChangesDoNotReflectInImmutableMap() { - - Map mutableMap = new HashMap<>(); - mutableMap.put("USA", "North America"); - - ImmutableMap immutableMap = ImmutableMap.copyOf(mutableMap); - assertTrue(immutableMap.containsKey("USA")); - - assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America")); - - mutableMap.remove("USA"); - assertTrue(immutableMap.containsKey("USA")); - - mutableMap.put("Mexico", "North America"); - assertFalse(immutableMap.containsKey("Mexico")); - } - - @Test - @SuppressWarnings("deprecation") - public void whenGuavaImmutableMapFromBuilderMethod_thenOriginalCollectionChangesDoNotReflectInImmutableMap() { - - Map mutableMap = new HashMap<>(); - mutableMap.put("USA", "North America"); - - ImmutableMap immutableMap = ImmutableMap.builder() - .putAll(mutableMap) - .put("Costa Rica", "North America") - .build(); - assertTrue(immutableMap.containsKey("USA")); - assertTrue(immutableMap.containsKey("Costa Rica")); - - assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America")); - - mutableMap.remove("USA"); - assertTrue(immutableMap.containsKey("USA")); - - mutableMap.put("Mexico", "North America"); - assertFalse(immutableMap.containsKey("Mexico")); - } - - @Test - @SuppressWarnings("deprecation") - public void whenGuavaImmutableMapFromOfMethod_thenOriginalCollectionChangesDoNotReflectInImmutableMap() { - - ImmutableMap immutableMap = ImmutableMap.of("USA", "North America", "Costa Rica", "North America"); - assertTrue(immutableMap.containsKey("USA")); - assertTrue(immutableMap.containsKey("Costa Rica")); - - assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America")); - } - -} diff --git a/java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java deleted file mode 100644 index dbad2e5b5e..0000000000 --- a/java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.map; - -import org.junit.Test; - -import java.util.Collections; -import java.util.Map; - -import static org.junit.Assert.*; - -public class KeyCheckUnitTest { - - @Test - public void whenKeyIsPresent_thenContainsKeyReturnsTrue() { - Map map = Collections.singletonMap("key", "value"); - - assertTrue(map.containsKey("key")); - assertFalse(map.containsKey("missing")); - } - - @Test - public void whenKeyHasNullValue_thenGetStillWorks() { - Map map = Collections.singletonMap("nothing", null); - - assertTrue(map.containsKey("nothing")); - assertNull(map.get("nothing")); - } -} \ No newline at end of file diff --git a/java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java deleted file mode 100644 index 721b48ea7b..0000000000 --- a/java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.baeldung.map; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.LinkedHashMultimap; -import com.google.common.collect.Multimap; -import com.google.common.collect.TreeMultimap; -import org.apache.commons.collections4.MultiMap; -import org.apache.commons.collections4.MultiMapUtils; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.map.MultiValueMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; -import org.apache.commons.collections4.multimap.HashSetValuedHashMap; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; - -import static org.assertj.core.api.Assertions.assertThat; - -public class MapMultipleValuesUnitTest { - private static final Logger LOG = LoggerFactory.getLogger(MapMultipleValuesUnitTest.class); - - @Test - public void givenHashMap_whenPuttingTwice_thenReturningFirstValue() { - Map map = new HashMap<>(); - assertThat(map.put("key1", "value1")).isEqualTo(null); - assertThat(map.put("key1", "value2")).isEqualTo("value1"); - assertThat(map.get("key1")).isEqualTo("value2"); - } - - @Test - public void givenCollectionAsValue_whenPuttingTwice_thenReturningCollection() { - Map> map = new HashMap<>(); - List list = new ArrayList<>(); - map.put("key1", list); - map.get("key1").add("value1"); - map.get("key1").add("value2"); - assertThat(map.get("key1").get(0)).isEqualTo("value1"); - assertThat(map.get("key1").get(1)).isEqualTo("value2"); - } - - @Test - public void givenCollectionAsValueAndJava8_whenPuttingTwice_thenReturningCollection() { - Map> map = new HashMap<>(); - map.computeIfAbsent("key1", k -> new ArrayList<>()).add("value1"); - map.computeIfAbsent("key1", k -> new ArrayList<>()).add("value2"); - assertThat(map.get("key1").get(0)).isEqualTo("value1"); - assertThat(map.get("key1").get(1)).isEqualTo("value2"); - } - - @Test - public void givenMultiValueMap_whenPuttingTwice_thenReturningValues() { - MultiMap map = new MultiValueMap<>(); - map.put("key1", "value1"); - map.put("key1", "value2"); - assertThat((Collection) map.get("key1")) - .contains("value1", "value2"); - } - - @Test - public void givenArrayListValuedHashMap_whenPuttingDoubleValues_thenReturningAllValues() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("key1", "value1"); - map.put("key1", "value2"); - map.put("key1", "value2"); - assertThat((Collection) map.get("key1")) - .containsExactly("value1", "value2", "value2"); - } - - @Test - public void givenHashSetValuedHashMap_whenPuttingTwiceTheSame_thenReturningOneValue() { - MultiValuedMap map = new HashSetValuedHashMap<>(); - map.put("key1", "value1"); - map.put("key1", "value1"); - assertThat((Collection) map.get("key1")) - .containsExactly("value1"); - } - - @Test(expected = UnsupportedOperationException.class) - public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("key1", "value1"); - map.put("key1", "value2"); - MultiValuedMap immutableMap = - MultiMapUtils.unmodifiableMultiValuedMap(map); - immutableMap.put("key1", "value3"); - } - - @Test - public void givenArrayListMultiMap_whenInserting_thenCorrectOutput() { - Multimap map = ArrayListMultimap.create(); - map.put("key1", "value2"); - map.put("key1", "value1"); - assertThat((Collection) map.get("key1")) - .containsExactly("value2", "value1"); - } - - @Test - public void givenLinkedHashMultiMap_whenInserting_thenReturningValuesInInsertionOrder() { - Multimap map = LinkedHashMultimap.create(); - map.put("key1", "value3"); - map.put("key1", "value1"); - map.put("key1", "value2"); - assertThat((Collection) map.get("key1")) - .containsExactly("value3", "value1", "value2"); - } - - @Test - public void givenTreeMultimap_whenInserting_thenReturningValuesInNaturalOrder() { - Multimap map = TreeMultimap.create(); - map.put("key1", "value3"); - map.put("key1", "value1"); - map.put("key1", "value2"); - assertThat((Collection) map.get("key1")) - .containsExactly("value1", "value2", "value3"); - } - -} \ No newline at end of file diff --git a/java-collections-maps/src/test/java/com/baeldung/map/MapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/map/MapUnitTest.java deleted file mode 100644 index eaf68ccba5..0000000000 --- a/java-collections-maps/src/test/java/com/baeldung/map/MapUnitTest.java +++ /dev/null @@ -1,336 +0,0 @@ -package com.baeldung.map; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; -import java.util.Map.Entry; - -import static org.junit.Assert.*; - -public class MapUnitTest { - private static final Logger LOG = LoggerFactory.getLogger(MapUnitTest.class); - - - @Test - public void givenHashMap_whenRetrievesKeyset_thenCorrect() { - Map map = new HashMap<>(); - map.put("name", "baeldung"); - map.put("type", "blog"); - - Set keys = map.keySet(); - - assertEquals(2, keys.size()); - assertTrue(keys.contains("name")); - assertTrue(keys.contains("type")); - } - - @Test - public void givenHashMap_whenRetrievesValues_thenCorrect() { - Map map = new HashMap<>(); - map.put("name", "baeldung"); - map.put("type", "blog"); - - Collection values = map.values(); - - assertEquals(2, values.size()); - assertTrue(values.contains("baeldung")); - assertTrue(values.contains("blog")); - } - - @Test - public void givenHashMap_whenRetrievesEntries_thenCorrect() { - Map map = new HashMap<>(); - map.put("name", "baeldung"); - map.put("type", "blog"); - - Set> entries = map.entrySet(); - - assertEquals(2, entries.size()); - for (Entry e : entries) { - String key = e.getKey(); - String val = e.getValue(); - assertTrue(key.equals("name") || key.equals("type")); - assertTrue(val.equals("baeldung") || val.equals("blog")); - } - } - - @Test - public void givenKeySet_whenChangeReflectsInMap_thenCorrect() { - Map map = new HashMap<>(); - map.put("name", "baeldung"); - map.put("type", "blog"); - - assertEquals(2, map.size()); - - Set keys = map.keySet(); - - keys.remove("name"); - assertEquals(1, map.size()); - } - - @Test(expected = ConcurrentModificationException.class) - public void givenIterator_whenFailsFastOnModification_thenCorrect() { - Map map = new HashMap<>(); - map.put("name", "baeldung"); - map.put("type", "blog"); - - Set keys = map.keySet(); - Iterator it = keys.iterator(); - map.remove("type"); - while (it.hasNext()) { - String key = it.next(); - } - } - - public void givenIterator_whenRemoveWorks_thenCorrect() { - Map map = new HashMap<>(); - map.put("name", "baeldung"); - map.put("type", "blog"); - - Set keys = map.keySet(); - Iterator it = keys.iterator(); - while (it.hasNext()) { - it.next(); - it.remove(); - } - assertEquals(0, map.size()); - } - - @Test - public void whenHashCodeIsCalledOnPut_thenCorrect() { - MyKey key = new MyKey(1, "name"); - Map map = new HashMap<>(); - map.put(key, "val"); - } - - @Test - public void whenHashCodeIsCalledOnGet_thenCorrect() { - MyKey key = new MyKey(1, "name"); - Map map = new HashMap<>(); - map.put(key, "val"); - map.get(key); - } - - @Test - public void whenGetWorks_thenCorrect() { - Map map = new HashMap<>(); - map.put("key", "val"); - - String val = map.get("key"); - - assertEquals("val", val); - } - - @Test - public void givenNewKey_whenPutReturnsNull_thenCorrect() { - Map map = new HashMap<>(); - - String rtnVal = map.put("key1", "val1"); - - assertNull(rtnVal); - } - - @Test - public void givenUnmappedKey_whenGetReturnsNull_thenCorrect() { - Map map = new HashMap<>(); - - String rtnVal = map.get("key1"); - - assertNull(rtnVal); - } - - @Test - public void givenNullVal_whenPutReturnsNull_thenCorrect() { - Map map = new HashMap<>(); - - String rtnVal = map.put("key1", null); - - assertNull(rtnVal); - } - - @Test - public void givenNullKeyAndVal_whenAccepts_thenCorrect() { - Map map = new HashMap<>(); - - map.put(null, null); - } - - @Test - public void givenNullVal_whenRetrieves_thenCorrect() { - Map map = new HashMap<>(); - map.put("key", null); - - String val = map.get("key"); - - assertNull(val); - } - - @Test - public void whenContainsDistinguishesNullValues_thenCorrect() { - Map map = new HashMap<>(); - - String val1 = map.get("key"); - boolean valPresent = map.containsKey("key"); - - assertNull(val1); - assertFalse(valPresent); - - map.put("key", null); - String val = map.get("key"); - valPresent = map.containsKey("key"); - - assertNull(val); - assertTrue(valPresent); - - } - - @Test - public void whenPutReturnsPrevValue_thenCorrect() { - Map map = new HashMap<>(); - map.put("key1", "val1"); - String rtnVal = map.put("key1", "val2"); - - assertEquals("val1", rtnVal); - } - - @Test - public void whenCallsEqualsOnCollision_thenCorrect() { - HashMap map = new HashMap<>(); - MyKey k1 = new MyKey(1, "firstKey"); - MyKey k2 = new MyKey(2, "secondKey"); - MyKey k3 = new MyKey(2, "thirdKey"); - - LOG.debug("storing value for k1"); - map.put(k1, "firstValue"); - - LOG.debug("storing value for k2"); - map.put(k2, "secondValue"); - - LOG.debug("storing value for k3"); - map.put(k3, "thirdValue"); - - LOG.debug("retrieving value for k1"); - String v1 = map.get(k1); - - LOG.debug("retrieving value for k2"); - String v2 = map.get(k2); - - LOG.debug("retrieving value for k3"); - String v3 = map.get(k3); - - assertEquals("firstValue", v1); - assertEquals("secondValue", v2); - assertEquals("thirdValue", v3); - - } - - @Test - public void givenLinkedHashMap_whenGetsOrderedKeyset_thenCorrect() { - LinkedHashMap map = new LinkedHashMap<>(); - map.put(1, null); - map.put(2, null); - map.put(3, null); - map.put(4, null); - map.put(5, null); - Set keys = map.keySet(); - Integer[] arr = keys.toArray(new Integer[0]); - for (int i = 0; i < arr.length; i++) { - assertEquals(new Integer(i + 1), arr[i]); - - } - } - - @Test - public void givenLinkedHashMap_whenAccessOrderWorks_thenCorrect() { - LinkedHashMap map = new LinkedHashMap<>(16, .75f, true); - map.put(1, null); - map.put(2, null); - map.put(3, null); - map.put(4, null); - map.put(5, null); - Set keys = map.keySet(); - assertEquals("[1, 2, 3, 4, 5]", keys.toString()); - map.get(4); - assertEquals("[1, 2, 3, 5, 4]", keys.toString()); - map.get(1); - assertEquals("[2, 3, 5, 4, 1]", keys.toString()); - map.get(3); - assertEquals("[2, 5, 4, 1, 3]", keys.toString()); - } - - @Test - public void givenLinkedHashMap_whenRemovesEldestEntry_thenCorrect() { - LinkedHashMap map = new MyLinkedHashMap<>(16, .75f, true); - map.put(1, null); - map.put(2, null); - map.put(3, null); - map.put(4, null); - map.put(5, null); - Set keys = map.keySet(); - assertEquals("[1, 2, 3, 4, 5]", keys.toString()); - map.put(6, null); - assertEquals("[2, 3, 4, 5, 6]", keys.toString()); - map.put(7, null); - assertEquals("[3, 4, 5, 6, 7]", keys.toString()); - map.put(8, null); - assertEquals("[4, 5, 6, 7, 8]", keys.toString()); - } - - @Test - public void givenTreeMap_whenOrdersEntriesNaturally_thenCorrect() { - TreeMap map = new TreeMap<>(); - map.put(3, "val"); - map.put(2, "val"); - map.put(1, "val"); - map.put(5, "val"); - map.put(4, "val"); - assertEquals("[1, 2, 3, 4, 5]", map.keySet().toString()); - } - - @Test - public void givenTreeMap_whenOrdersEntriesNaturally_thenCorrect2() { - TreeMap map = new TreeMap<>(); - map.put("c", "val"); - map.put("b", "val"); - map.put("a", "val"); - map.put("e", "val"); - map.put("d", "val"); - - assertEquals("[a, b, c, d, e]", map.keySet().toString()); - } - - @Test - public void givenTreeMap_whenOrdersEntriesByComparator_thenCorrect() { - TreeMap map = new TreeMap<>(Comparator.reverseOrder()); - map.put(3, "val"); - map.put(2, "val"); - map.put(1, "val"); - map.put(5, "val"); - map.put(4, "val"); - - assertEquals("[5, 4, 3, 2, 1]", map.keySet().toString()); - } - - @Test - public void givenTreeMap_whenPerformsQueries_thenCorrect() { - TreeMap map = new TreeMap<>(); - map.put(3, "val"); - map.put(2, "val"); - map.put(1, "val"); - map.put(5, "val"); - map.put(4, "val"); - - Integer highestKey = map.lastKey(); - Integer lowestKey = map.firstKey(); - Set keysLessThan3 = map.headMap(3).keySet(); - Set keysGreaterThanEqTo3 = map.tailMap(3).keySet(); - - assertEquals(new Integer(5), highestKey); - assertEquals(new Integer(1), lowestKey); - assertEquals("[1, 2]", keysLessThan3.toString()); - assertEquals("[3, 4, 5]", keysGreaterThanEqTo3.toString()); - } - -} diff --git a/java-collections-maps/src/test/java/com/baeldung/map/MapUtilUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/map/MapUtilUnitTest.java deleted file mode 100644 index f8e4c8fd8a..0000000000 --- a/java-collections-maps/src/test/java/com/baeldung/map/MapUtilUnitTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * - */ -package com.baeldung.map; - -import com.google.common.collect.HashBiMap; -import org.apache.commons.collections4.BidiMap; -import org.apache.commons.collections4.bidimap.DualHashBidiMap; -import org.junit.Test; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.junit.Assert.assertEquals; - -/** - * @author swpraman - * - */ -public class MapUtilUnitTest { - - - @Test - public void whenUsingImperativeWayForSingleKey_shouldReturnSingleKey() { - Map capitalCountryMap = new HashMap<>(); - capitalCountryMap.put("Tokyo", "Japan"); - capitalCountryMap.put("New Delhi", "India"); - assertEquals("New Delhi", MapUtil.getKey(capitalCountryMap, "India")); - } - - @Test - public void whenUsingImperativeWayForAllKeys_shouldReturnAllKeys() { - Map capitalCountryMap = new HashMap<>(); - capitalCountryMap.put("Tokyo", "Japan"); - capitalCountryMap.put("Berlin", "Germany"); - capitalCountryMap.put("Cape Town", "South Africa"); - capitalCountryMap.put("Pretoria", "South Africa"); - capitalCountryMap.put("Bloemfontein", "South Africa"); - - assertEquals(new HashSet(Arrays.asList( - new String[] {"Cape Town", "Pretoria", "Bloemfontein"})), - MapUtil.getKeys(capitalCountryMap, "South Africa")); - } - - @Test - public void whenUsingFunctionalWayForSingleKey_shouldReturnSingleKey() { - Map capitalCountryMap = new HashMap<>(); - capitalCountryMap.put("Tokyo", "Japan"); - capitalCountryMap.put("Berlin", "Germany"); - assertEquals("Berlin", MapUtil.keys(capitalCountryMap, "Germany").findFirst().get()); - } - - @Test - public void whenUsingFunctionalWayForAllKeys_shouldReturnAllKeys() { - Map capitalCountryMap = new HashMap<>(); - capitalCountryMap.put("Tokyo", "Japan"); - capitalCountryMap.put("Berlin", "Germany"); - capitalCountryMap.put("Cape Town", "South Africa"); - capitalCountryMap.put("Pretoria", "South Africa"); - capitalCountryMap.put("Bloemfontein", "South Africa"); - assertEquals(new HashSet(Arrays.asList( - new String[] {"Cape Town", "Pretoria", "Bloemfontein"})), - MapUtil.keys(capitalCountryMap, "South Africa").collect(Collectors.toSet())); - } - - @Test - public void whenUsingBidiMap_shouldReturnKey() { - BidiMap capitalCountryMap = new DualHashBidiMap(); - capitalCountryMap.put("Berlin", "Germany"); - capitalCountryMap.put("Cape Town", "South Africa"); - assertEquals("Berlin", capitalCountryMap.getKey("Germany")); - } - - @Test - public void whenUsingBidiMapAddDuplicateValue_shouldRemoveOldEntry() { - BidiMap capitalCountryMap = new DualHashBidiMap(); - capitalCountryMap.put("Berlin", "Germany"); - capitalCountryMap.put("Cape Town", "South Africa"); - capitalCountryMap.put("Pretoria", "South Africa"); - assertEquals("Pretoria", capitalCountryMap.getKey("South Africa")); - } - - @Test - public void whenUsingBiMap_shouldReturnKey() { - HashBiMap capitalCountryMap = HashBiMap.create(); - capitalCountryMap.put("Berlin", "Germany"); - capitalCountryMap.put("Cape Town", "South Africa"); - assertEquals("Berlin", capitalCountryMap.inverse().get("Germany")); - } - - @Test(expected=IllegalArgumentException.class) - public void whenUsingBiMapAddDuplicateValue_shouldThrowException() { - HashBiMap capitalCountryMap = HashBiMap.create(); - capitalCountryMap.put("Berlin", "Germany"); - capitalCountryMap.put("Cape Town", "South Africa"); - capitalCountryMap.put("Pretoria", "South Africa"); - assertEquals("Berlin", capitalCountryMap.inverse().get("Germany")); - } - -} diff --git a/java-collections-maps/src/test/java/com/baeldung/map/MultiValuedMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/map/MultiValuedMapUnitTest.java deleted file mode 100644 index 686c1cef87..0000000000 --- a/java-collections-maps/src/test/java/com/baeldung/map/MultiValuedMapUnitTest.java +++ /dev/null @@ -1,227 +0,0 @@ -package com.baeldung.map; - -import org.apache.commons.collections4.MultiMapUtils; -import org.apache.commons.collections4.MultiSet; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; -import org.apache.commons.collections4.multimap.HashSetValuedHashMap; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; - -public class MultiValuedMapUnitTest { - - @Test - public void givenMultiValuesMap_whenPuttingMultipleValuesUsingPutMethod_thenReturningAllValues() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - - map.put("fruits", "apple"); - map.put("fruits", "orange"); - - assertThat((Collection) map.get("fruits")).containsExactly("apple", "orange"); - - } - - @Test - public void givenMultiValuesMap_whenPuttingMultipleValuesUsingPutAllMethod_thenReturningAllValues() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - - map.putAll("vehicles", Arrays.asList("car", "bike")); - - assertThat((Collection) map.get("vehicles")).containsExactly("car", "bike"); - - } - - @Test - public void givenMultiValuesMap_whenGettingValueUsingGetMethod_thenReturningValue() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - - map.put("fruits", "apple"); - - assertThat((Collection) map.get("fruits")).containsExactly("apple"); - } - - @Test - public void givenMultiValuesMap_whenUsingEntriesMethod_thenReturningMappings() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "orange"); - - Collection> entries = (Collection>) map.entries(); - - for(Map.Entry entry : entries) { - assertThat(entry.getKey()).contains("fruits"); - assertTrue(entry.getValue().equals("apple") || entry.getValue().equals("orange") ); - } - } - - @Test - public void givenMultiValuesMap_whenUsingKeysMethod_thenReturningAllKeys() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("vehicles", "car"); - map.put("vehicles", "bike"); - - MultiSet keys = map.keys(); - - assertThat((keys)).contains("fruits", "vehicles"); - - } - - @Test - public void givenMultiValuesMap_whenUsingKeySetMethod_thenReturningAllKeys() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("vehicles", "car"); - map.put("vehicles", "bike"); - - Set keys = map.keySet(); - - assertThat(keys).contains("fruits", "vehicles"); - - } - - @Test - public void givenMultiValuesMap_whenUsingValuesMethod_thenReturningAllValues() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("vehicles", "car"); - map.put("vehicles", "bike"); - - assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); - } - - @Test - public void givenMultiValuesMap_whenUsingRemoveMethod_thenReturningUpdatedMap() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("vehicles", "car"); - map.put("vehicles", "bike"); - assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); - - map.remove("fruits"); - - assertThat(((Collection) map.values())).contains("car", "bike"); - - } - - @Test - public void givenMultiValuesMap_whenUsingRemoveMappingMethod_thenReturningUpdatedMapAfterMappingRemoved() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("vehicles", "car"); - map.put("vehicles", "bike"); - assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); - - map.removeMapping("fruits", "apple"); - - assertThat(((Collection) map.values())).contains("orange", "car", "bike"); - } - - @Test - public void givenMultiValuesMap_whenUsingClearMethod_thenReturningEmptyMap() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("vehicles", "car"); - map.put("vehicles", "bike"); - assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); - - map.clear(); - - assertTrue(map.isEmpty()); - } - - @Test - public void givenMultiValuesMap_whenUsingContainsKeyMethod_thenReturningTrue() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("vehicles", "car"); - map.put("vehicles", "bike"); - - assertTrue(map.containsKey("fruits")); - } - - @Test - public void givenMultiValuesMap_whenUsingContainsValueMethod_thenReturningTrue() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("vehicles", "car"); - map.put("vehicles", "bike"); - - assertTrue(map.containsValue("orange")); - } - - @Test - public void givenMultiValuesMap_whenUsingIsEmptyMethod_thenReturningFalse() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("vehicles", "car"); - map.put("vehicles", "bike"); - - assertFalse(map.isEmpty()); - } - - @Test - public void givenMultiValuesMap_whenUsingSizeMethod_thenReturningElementCount() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("vehicles", "car"); - map.put("vehicles", "bike"); - - assertEquals(4, map.size()); - } - - @Test - public void givenArrayListValuedHashMap_whenPuttingDoubleValues_thenReturningAllValues() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "orange"); - map.put("fruits", "orange"); - - assertThat((Collection) map.get("fruits")).containsExactly("apple", "orange", "orange"); - } - - @Test - public void givenHashSetValuedHashMap_whenPuttingTwiceTheSame_thenReturningOneValue() { - MultiValuedMap map = new HashSetValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "apple"); - - assertThat((Collection) map.get("fruits")).containsExactly("apple"); - } - - @Test(expected = UnsupportedOperationException.class) - public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() { - MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); - map.put("fruits", "orange"); - MultiValuedMap immutableMap = MultiMapUtils.unmodifiableMultiValuedMap(map); - - immutableMap.put("fruits", "banana"); - - } - - -} From cb7bd8d2f2d6e94ad5d8846886c041edbd8bbdcb Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Tue, 7 Apr 2020 14:50:03 +0530 Subject: [PATCH 046/194] JAVA-1188: Moved modules to core-java-modules --- .../core-java-collections-maps-2/README.md | 16 + .../core-java-collections-maps-2/pom.xml | 79 ++++ .../main/java/com/baeldung/map/Product.java | 133 +++++++ .../com/baeldung/map/convert/MapToString.java | 34 ++ .../com/baeldung/map/convert/StringToMap.java | 21 ++ .../baeldung/map/copyhashmap/CopyHashMap.java | 55 +++ .../map/initialize/MapInitializer.java | 80 +++++ .../baeldung/map/iteration/MapIteration.java | 74 ++++ .../java/com/baeldung/map/mapmax/MapMax.java | 92 +++++ .../com/baeldung/map/mergemaps/Employee.java | 60 ++++ .../com/baeldung/map/mergemaps/MergeMaps.java | 105 ++++++ .../map/primitives/PrimitiveMaps.java | 69 ++++ .../com/baeldung/map/sort/SortHashMap.java | 104 ++++++ .../com/baeldung/map/ProductUnitTest.java | 174 +++++++++ .../map/convert/MapToStringUnitTest.java | 48 +++ .../map/convert/StringToMapUnitTest.java | 23 ++ .../map/copyhashmap/CopyHashMapUnitTest.java | 76 ++++ .../baeldung/map/copyhashmap/Employee.java | 28 ++ .../initialize/MapInitializerUnitTest.java | 27 ++ .../baeldung/map/mapmax/MapMaxUnitTest.java | 58 +++ .../map/weakhashmap/WeakHashMapUnitTest.java | 72 ++++ .../core-java-collections-maps-3/README.md | 8 + .../core-java-collections-maps-3/pom.xml | 26 ++ .../compare/HashMapComparisonUnitTest.java | 225 ++++++++++++ .../TreeMapVsHashMapUnitTest.java | 58 +++ .../core-java-collections-maps/README.md | 16 + .../core-java-collections-maps/pom.xml | 35 ++ .../main/java/com/baeldung/map/MapUtil.java | 44 +++ .../src/main/java/com/baeldung/map/MyKey.java | 64 ++++ .../com/baeldung/map/MyLinkedHashMap.java | 23 ++ .../src/main/resources/logback.xml | 13 + .../baeldung/guava/GuavaBiMapUnitTest.java | 120 +++++++ .../baeldung/map/ImmutableMapUnitTest.java | 84 +++++ .../com/baeldung/map/KeyCheckUnitTest.java | 27 ++ .../map/MapMultipleValuesUnitTest.java | 119 +++++++ .../java/com/baeldung/map/MapUnitTest.java | 336 ++++++++++++++++++ .../com/baeldung/map/MapUtilUnitTest.java | 103 ++++++ .../baeldung/map/MultiValuedMapUnitTest.java | 227 ++++++++++++ core-java-modules/pom.xml | 3 + 39 files changed, 2959 insertions(+) create mode 100644 core-java-modules/core-java-collections-maps-2/README.md create mode 100644 core-java-modules/core-java-collections-maps-2/pom.xml create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/Product.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps-3/README.md create mode 100644 core-java-modules/core-java-collections-maps-3/pom.xml create mode 100644 core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps/README.md create mode 100644 core-java-modules/core-java-collections-maps/pom.xml create mode 100644 core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java create mode 100644 core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyKey.java create mode 100644 core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java create mode 100644 core-java-modules/core-java-collections-maps/src/main/resources/logback.xml create mode 100644 core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapUtilUnitTest.java create mode 100644 core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MultiValuedMapUnitTest.java diff --git a/core-java-modules/core-java-collections-maps-2/README.md b/core-java-modules/core-java-collections-maps-2/README.md new file mode 100644 index 0000000000..da9279b191 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/README.md @@ -0,0 +1,16 @@ +## Java Collections Cookbooks and Examples + +This module contains articles about Map data structures in Java. + +### Relevant Articles: +- [Map of Primitives in Java](https://www.baeldung.com/java-map-primitives) +- [Copying a HashMap in Java](https://www.baeldung.com/java-copy-hashmap) +- [A Guide to Java HashMap](https://www.baeldung.com/java-hashmap) +- [Guide to WeakHashMap in Java](https://www.baeldung.com/java-weakhashmap) +- [Map to String Conversion in Java](https://www.baeldung.com/java-map-to-string-conversion) +- [Iterate over a Map in Java](https://www.baeldung.com/java-iterate-map) +- [Merging Two Maps with Java 8](https://www.baeldung.com/java-merge-maps) +- [Sort a HashMap in Java](https://www.baeldung.com/java-hashmap-sort) +- [Finding the Highest Value in a Java Map](https://www.baeldung.com/java-find-map-max) +- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) +- More articles: [[<-- prev]](/core-java-collections-maps) [[next -->]](/core-java-collections-maps-3) diff --git a/core-java-modules/core-java-collections-maps-2/pom.xml b/core-java-modules/core-java-collections-maps-2/pom.xml new file mode 100644 index 0000000000..a08a4ac072 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + core-java-collections-maps-2 + 0.1.0-SNAPSHOT + core-java-collections-maps-2 + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.eclipse.collections + eclipse-collections + ${eclipse-collections.version} + + + net.sf.trove4j + trove4j + ${trove4j.version} + + + it.unimi.dsi + fastutil + ${fastutil.version} + + + colt + colt + ${colt.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + one.util + streamex + ${streamex.version} + + + com.jayway.awaitility + awaitility + ${avaitility.version} + test + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + 0.6.5 + 4.1 + 1.7.0 + 8.2.0 + 3.0.2 + 8.1.0 + 1.2.0 + 3.11.1 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/Product.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/Product.java new file mode 100644 index 0000000000..5559895730 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/Product.java @@ -0,0 +1,133 @@ +package com.baeldung.map; + +import java.util.*; + +public class Product { + + private String name; + private String description; + private List tags; + + public Product(String name, String description) { + this.name = name; + this.description = description; + this.tags = new ArrayList<>(); + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public List getTags() { + return tags; + } + + public Product addTagsOfOtherProdcut(Product product) { + this.tags.addAll(product.getTags()); + return this; + } + + @Override + public boolean equals(Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Product product = (Product) o; + return Objects.equals(name, product.name) && + Objects.equals(description, product.description); + } + + @Override + public int hashCode() { + return Objects.hash(name, description); + } + + public static void forEach() { + + HashMap productsByName = new HashMap<>(); + productsByName.forEach( (key, product) + -> System.out.println("Key: " + key + " Product:" + product.getDescription()) + //do something with the key and value + ); + + //Prior to Java 8: + for(Map.Entry entry : productsByName.entrySet()) { + Product product = entry.getValue(); + String key = entry.getKey(); + //do something with the key and value + } + } + + public static void getOrDefault() { + + HashMap productsByName = new HashMap<>(); + Product chocolate = new Product("chocolate", "something sweet"); + Product defaultProduct = productsByName.getOrDefault("horse carriage", chocolate); + Product bike = productsByName.getOrDefault("E-Bike", chocolate); + + //Prior to Java 8: + Product bike2 = productsByName.containsKey("E-Bike") + ? productsByName.get("E-Bike") + : chocolate; + Product defaultProduct2 = productsByName.containsKey("horse carriage") + ? productsByName.get("horse carriage") + : chocolate; + } + + public static void putIfAbsent() { + + HashMap productsByName = new HashMap<>(); + Product chocolate = new Product("chocolate", "something sweet"); + productsByName.putIfAbsent("E-Bike", chocolate); + + //Prior to Java 8: + if(productsByName.containsKey("E-Bike")) { + productsByName.put("E-Bike", chocolate); + } + } + + public static void merge() { + + HashMap productsByName = new HashMap<>(); + Product eBike2 = new Product("E-Bike", "A bike with a battery"); + eBike2.getTags().add("sport"); + productsByName.merge("E-Bike", eBike2, Product::addTagsOfOtherProdcut); + + //Prior to Java 8: + if(productsByName.containsKey("E-Bike")) { + productsByName.get("E-Bike").addTagsOfOtherProdcut(eBike2); + } else { + productsByName.put("E-Bike", eBike2); + } + } + + public static void compute() { + + HashMap productsByName = new HashMap<>(); + Product eBike2 = new Product("E-Bike", "A bike with a battery"); + + productsByName.compute("E-Bike", (k,v) -> { + if(v != null) { + return v.addTagsOfOtherProdcut(eBike2); + } else { + return eBike2; + } + }); + + //Prior to Java 8: + if(productsByName.containsKey("E-Bike")) { + productsByName.get("E-Bike").addTagsOfOtherProdcut(eBike2); + } else { + productsByName.put("E-Bike", eBike2); + } + } +} diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java new file mode 100644 index 0000000000..d13be924ff --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/MapToString.java @@ -0,0 +1,34 @@ +package com.baeldung.map.convert; + +import com.google.common.base.Joiner; +import org.apache.commons.lang3.StringUtils; + +import java.util.Map; +import java.util.stream.Collectors; + +public class MapToString { + + public static String convertWithIteration(Map map) { + StringBuilder mapAsString = new StringBuilder("{"); + for (Integer key : map.keySet()) { + mapAsString.append(key + "=" + map.get(key) + ", "); + } + mapAsString.delete(mapAsString.length()-2, mapAsString.length()).append("}"); + return mapAsString.toString(); + } + + public static String convertWithStream(Map map) { + String mapAsString = map.keySet().stream() + .map(key -> key + "=" + map.get(key)) + .collect(Collectors.joining(", ", "{", "}")); + return mapAsString; + } + + public static String convertWithGuava(Map map) { + return Joiner.on(",").withKeyValueSeparator("=").join(map); + } + + public static String convertWithApache(Map map) { + return StringUtils.join(map); + } +} diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java new file mode 100644 index 0000000000..416ba4dd9a --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/convert/StringToMap.java @@ -0,0 +1,21 @@ +package com.baeldung.map.convert; + +import com.google.common.base.Splitter; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +public class StringToMap { + + public static Map convertWithStream(String mapAsString) { + Map map = Arrays.stream(mapAsString.split(",")) + .map(entry -> entry.split("=")) + .collect(Collectors.toMap(entry -> entry[0], entry -> entry[1])); + return map; + } + + public static Map convertWithGuava(String mapAsString) { + return Splitter.on(',').withKeyValueSeparator('=').split(mapAsString); + } +} diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java new file mode 100644 index 0000000000..cb18f3aa11 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/copyhashmap/CopyHashMap.java @@ -0,0 +1,55 @@ +package com.baeldung.map.copyhashmap; + +import org.apache.commons.lang3.SerializationUtils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; + +public class CopyHashMap { + + public static HashMap copyUsingConstructor(HashMap originalMap) { + return new HashMap(originalMap); + } + + public static HashMap copyUsingClone(HashMap originalMap) { + return (HashMap) originalMap.clone(); + } + + public static HashMap copyUsingPut(HashMap originalMap) { + HashMap shallowCopy = new HashMap(); + Set> entries = originalMap.entrySet(); + for(Map.Entry mapEntry: entries) { + shallowCopy.put(mapEntry.getKey(), mapEntry.getValue()); + } + + return shallowCopy; + } + + public static HashMap copyUsingPutAll(HashMap originalMap) { + HashMap shallowCopy = new HashMap(); + shallowCopy.putAll(originalMap); + + return shallowCopy; + } + + public static HashMap copyUsingJava8Stream(HashMap originalMap) { + Set> entries = originalMap.entrySet(); + HashMap shallowCopy = (HashMap) entries + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + return shallowCopy; + } + + public static HashMap shallowCopy(HashMap originalMap) { + return (HashMap) originalMap.clone(); + } + + public static HashMap deepCopy(HashMap originalMap) { + return SerializationUtils.clone(originalMap); + } + +} diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java new file mode 100644 index 0000000000..4d63abcfd0 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/initialize/MapInitializer.java @@ -0,0 +1,80 @@ +package com.baeldung.map.initialize; + +import java.util.AbstractMap; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class MapInitializer { + + public static Map articleMapOne; + static { + articleMapOne = new HashMap<>(); + articleMapOne.put("ar01", "Intro to Map"); + articleMapOne.put("ar02", "Some article"); + } + + public static Map createSingletonMap() { + Map passwordMap = Collections.singletonMap("username1", "password1"); + return passwordMap; + + } + + public Map createEmptyMap() { + Map emptyMap = Collections.emptyMap(); + return emptyMap; + } + + public Map createUsingDoubleBrace() { + Map doubleBraceMap = new HashMap() { + + /** + * + */ + private static final long serialVersionUID = 1L; + + { + put("key1", "value1"); + put("key2", "value2"); + } + }; + return doubleBraceMap; + } + + public Map createMapUsingStreamStringArray() { + Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, }) + .collect(Collectors.toMap(data -> data[0], data -> data[1])); + + return map; + } + + public Map createMapUsingStreamObjectArray() { + Map map = Stream.of(new Object[][] { { "data1", 1 }, { "data2", 2 }, }) + .collect(Collectors.toMap(data -> (String) data[0], data -> (Integer) data[1])); + + return map; + } + + public Map createMapUsingStreamSimpleEntry() { + Map map = Stream.of(new AbstractMap.SimpleEntry<>("idea", 1), new AbstractMap.SimpleEntry<>("mobile", 2)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + return map; + } + + public Map createMapUsingStreamSimpleImmutableEntry() { + Map map = Stream.of(new AbstractMap.SimpleImmutableEntry<>("idea", 1), new AbstractMap.SimpleImmutableEntry<>("mobile", 2)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + return map; + } + + public Map createImmutableMapWithStreams() { + Map map = Stream.of(new String[][] { { "Hello", "World" }, { "John", "Doe" }, }) + .collect(Collectors.collectingAndThen(Collectors.toMap(data -> data[0], data -> data[1]), Collections:: unmodifiableMap)); + return map; + + } +} diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java new file mode 100644 index 0000000000..b0c32e1487 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/iteration/MapIteration.java @@ -0,0 +1,74 @@ +package com.baeldung.map.iteration; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class MapIteration { + + public static void main(String[] args) { + MapIteration mapIteration = new MapIteration(); + Map map = new HashMap<>(); + + map.put("One", 1); + map.put("Three", 3); + map.put("Two", 2); + + System.out.println("Iterating Keys of Map Using KeySet"); + mapIteration.iterateKeys(map); + + System.out.println("Iterating Map Using Entry Set"); + mapIteration.iterateUsingEntrySet(map); + + System.out.println("Iterating Using Iterator and Map Entry"); + mapIteration.iterateUsingIteratorAndEntry(map); + + System.out.println("Iterating Using KeySet and For Each"); + mapIteration.iterateUsingKeySetAndForeach(map); + + System.out.println("Iterating Map Using Lambda Expression"); + mapIteration.iterateUsingLambda(map); + + System.out.println("Iterating Using Stream API"); + mapIteration.iterateUsingStreamAPI(map); + } + + public void iterateUsingEntrySet(Map map) { + for (Map.Entry entry : map.entrySet()) { + System.out.println(entry.getKey() + ":" + entry.getValue()); + } + } + + public void iterateUsingLambda(Map map) { + map.forEach((k, v) -> System.out.println((k + ":" + v))); + } + + public void iterateUsingIteratorAndEntry(Map map) { + Iterator> iterator = map.entrySet() + .iterator(); + while (iterator.hasNext()) { + Map.Entry pair = iterator.next(); + System.out.println(pair.getKey() + ":" + pair.getValue()); + } + } + + public void iterateUsingKeySetAndForeach(Map map) { + for (String key : map.keySet()) { + System.out.println(key + ":" + map.get(key)); + } + } + + public void iterateUsingStreamAPI(Map map) { + map.entrySet() + .stream() + .forEach(e -> System.out.println(e.getKey() + ":" + e.getValue())); + } + + public void iterateKeys(Map map) { + for (String key : map.keySet()) { + System.out.println(key); + } + + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java new file mode 100644 index 0000000000..8c33c857ee --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mapmax/MapMax.java @@ -0,0 +1,92 @@ +package com.baeldung.map.mapmax; + +import java.util.*; +import java.util.Map.Entry; + +public class MapMax { + + public > V maxUsingIteration(Map map) { + + Map.Entry maxEntry = null; + + for (Map.Entry entry : map.entrySet()) { + + if (maxEntry == null || entry.getValue() + .compareTo(maxEntry.getValue()) > 0) { + maxEntry = entry; + } + } + + return maxEntry.getValue(); + } + + public > V maxUsingCollectionsMax(Map map) { + + Entry maxEntry = Collections.max(map.entrySet(), new Comparator>() { + public int compare(Entry e1, Entry e2) { + return e1.getValue() + .compareTo(e2.getValue()); + } + }); + + return maxEntry.getValue(); + } + + public > V maxUsingCollectionsMaxAndLambda(Map map) { + + Entry maxEntry = Collections.max(map.entrySet(), (Entry e1, Entry e2) -> e1.getValue() + .compareTo(e2.getValue())); + + return maxEntry.getValue(); + } + + public > V maxUsingCollectionsMaxAndMethodReference(Map map) { + + Entry maxEntry = Collections.max(map.entrySet(), Comparator.comparing(Map.Entry::getValue)); + + return maxEntry.getValue(); + } + + public > V maxUsingStreamAndLambda(Map map) { + + Optional> maxEntry = map.entrySet() + .stream() + .max((Entry e1, Entry e2) -> e1.getValue() + .compareTo(e2.getValue())); + + return maxEntry.get() + .getValue(); + } + + public > V maxUsingStreamAndMethodReference(Map map) { + + Optional> maxEntry = map.entrySet() + .stream() + .max(Comparator.comparing(Map.Entry::getValue)); + + return maxEntry.get() + .getValue(); + } + + public static void main(String[] args) { + + Map map = new HashMap(); + + map.put(1, 3); + map.put(2, 4); + map.put(3, 5); + map.put(4, 6); + map.put(5, 7); + + MapMax mapMax = new MapMax(); + + System.out.println(mapMax.maxUsingIteration(map)); + System.out.println(mapMax.maxUsingCollectionsMax(map)); + System.out.println(mapMax.maxUsingCollectionsMaxAndLambda(map)); + System.out.println(mapMax.maxUsingCollectionsMaxAndMethodReference(map)); + System.out.println(mapMax.maxUsingStreamAndLambda(map)); + System.out.println(mapMax.maxUsingStreamAndMethodReference(map)); + + } + +} diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java new file mode 100644 index 0000000000..d7fb0d1a1d --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/Employee.java @@ -0,0 +1,60 @@ +package com.baeldung.map.mergemaps; + +public class Employee implements Comparable { + + private Long id; + private String name; + + public Employee(Long id, String name) { + this.name = name; + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Employee employee = (Employee) o; + + if (!id.equals(employee.id)) return false; + return name.equals(employee.name); + + } + + @Override + public int hashCode() { + int result = id.hashCode(); + result = 31 * result + name.hashCode(); + return result; + } + + @Override + public String toString() { + return "Employee{" + + "id=" + id + + ", name='" + name + '\'' + + '}'; + } + + @Override + public int compareTo(Employee employee) { + return (int)(this.id - employee.getId()); + } +} diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java new file mode 100644 index 0000000000..4f187bad90 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/mergemaps/MergeMaps.java @@ -0,0 +1,105 @@ +package com.baeldung.map.mergemaps; + +import one.util.streamex.EntryStream; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class MergeMaps { + + private static Map map1 = new HashMap<>(); + private static Map map2 = new HashMap<>(); + + public static void main(String[] args) { + + initialize(); + + mergeFunction(); + + streamConcat(); + + streamOf(); + + streamEx(); + + streamMerge(); + } + + private static void streamMerge() { + + Map map3 = map2.entrySet() + .stream() + .collect( + Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (v1, v2) -> new Employee(v1.getId(), v2.getName()), + () -> new HashMap<>(map1) + ) + ); + + System.out.println(map3); + } + + private static void streamEx() { + Map map3 = EntryStream.of(map1) + .append(EntryStream.of(map2)) + .toMap((e1, e2) -> e1); + + System.out.println(map3); + + } + + private static void streamOf() { + Map map3 = Stream.of(map1, map2) + .flatMap(map -> map.entrySet().stream()) + .collect( + Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (v1, v2) -> new Employee(v1.getId(), v2.getName()) + ) + ); + + map3.entrySet().forEach(System.out::println); + } + + private static void streamConcat() { + Map result = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream()).collect(Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (value1, value2) -> new Employee(value2.getId(), value1.getName()) + )); + + result.entrySet().forEach(System.out::println); + } + + private static void mergeFunction() { + Map map3 = new HashMap<>(map1); + + map2.forEach( + (key, value) -> map3.merge(key, value, (v1, v2) -> + new Employee(v1.getId(), v2.getName())) + ); + + map3.entrySet().forEach(System.out::println); + } + + + private static void initialize() { + Employee employee1 = new Employee(1L, "Henry"); + map1.put(employee1.getName(), employee1); + Employee employee2 = new Employee(22L, "Annie"); + map1.put(employee2.getName(), employee2); + Employee employee3 = new Employee(8L, "John"); + map1.put(employee3.getName(), employee3); + + Employee employee4 = new Employee(2L, "George"); + map2.put(employee4.getName(), employee4); + Employee employee5 = new Employee(3L, "Henry"); + map2.put(employee5.getName(), employee5); + } + +} diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java new file mode 100644 index 0000000000..30bec12ccc --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/primitives/PrimitiveMaps.java @@ -0,0 +1,69 @@ +package com.baeldung.map.primitives; + +import cern.colt.map.AbstractIntDoubleMap; +import cern.colt.map.OpenIntDoubleHashMap; +import gnu.trove.map.TDoubleIntMap; +import gnu.trove.map.hash.TDoubleIntHashMap; +import it.unimi.dsi.fastutil.ints.Int2BooleanMap; +import it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2BooleanSortedMap; +import it.unimi.dsi.fastutil.ints.Int2BooleanSortedMaps; +import org.eclipse.collections.api.map.primitive.ImmutableIntIntMap; +import org.eclipse.collections.api.map.primitive.MutableIntIntMap; +import org.eclipse.collections.api.map.primitive.MutableObjectDoubleMap; +import org.eclipse.collections.impl.factory.primitive.IntIntMaps; +import org.eclipse.collections.impl.factory.primitive.ObjectDoubleMaps; + +public class PrimitiveMaps { + + public static void main(String[] args) { + + eclipseCollectionsMap(); + troveMap(); + coltMap(); + fastutilMap(); + } + + private static void fastutilMap() { + Int2BooleanMap int2BooleanMap = new Int2BooleanOpenHashMap(); + int2BooleanMap.put(1, true); + int2BooleanMap.put(7, false); + int2BooleanMap.put(4, true); + + boolean value = int2BooleanMap.get(1); + + Int2BooleanSortedMap int2BooleanSorted = Int2BooleanSortedMaps.EMPTY_MAP; + } + + private static void coltMap() { + AbstractIntDoubleMap map = new OpenIntDoubleHashMap(); + map.put(1, 4.5); + double value = map.get(1); + } + + private static void eclipseCollectionsMap() { + MutableIntIntMap mutableIntIntMap = IntIntMaps.mutable.empty(); + mutableIntIntMap.addToValue(1, 1); + + ImmutableIntIntMap immutableIntIntMap = IntIntMaps.immutable.empty(); + + MutableObjectDoubleMap dObject = ObjectDoubleMaps.mutable.empty(); + dObject.addToValue("price", 150.5); + dObject.addToValue("quality", 4.4); + dObject.addToValue("stability", 0.8); + } + + private static void troveMap() { + double[] doubles = new double[] {1.2, 4.5, 0.3}; + int[] ints = new int[] {1, 4, 0}; + + TDoubleIntMap doubleIntMap = new TDoubleIntHashMap(doubles, ints); + + doubleIntMap.put(1.2, 22); + doubleIntMap.put(4.5, 16); + + doubleIntMap.adjustValue(1.2, 1); + doubleIntMap.adjustValue(4.5, 4); + doubleIntMap.adjustValue(0.3, 7); + } +} diff --git a/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java new file mode 100644 index 0000000000..14610ffb00 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/main/java/com/baeldung/map/sort/SortHashMap.java @@ -0,0 +1,104 @@ +package com.baeldung.map.sort; + +import com.baeldung.map.mergemaps.Employee; +import com.google.common.base.Functions; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Ordering; + +import java.util.*; +import java.util.stream.Collectors; + +public class SortHashMap { + + private static Map map = new HashMap<>(); + + public static void main(String[] args) { + + initialize(); + + treeMapSortByKey(); + + arrayListSortByValue(); + arrayListSortByKey(); + + sortStream(); + + sortGuava(); + + addDuplicates(); + + treeSetByKey(); + treeSetByValue(); + + } + + private static void sortGuava() { + final Ordering naturalOrdering = + Ordering.natural().onResultOf(Functions.forMap(map, null)); + + System.out.println(ImmutableSortedMap.copyOf(map, naturalOrdering)); + } + + private static void sortStream() { + map.entrySet().stream() + .sorted(Map.Entry.comparingByKey().reversed()) + .forEach(System.out::println); + + Map result = map.entrySet().stream() + .sorted(Map.Entry.comparingByValue()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, + (oldValue, newValue) -> oldValue, LinkedHashMap::new)); + + result.entrySet().forEach(System.out::println); + } + + private static void treeSetByValue() { + SortedSet values = new TreeSet<>(map.values()); + System.out.println(values); + } + + private static void treeSetByKey() { + SortedSet keysSet = new TreeSet<>(map.keySet()); + System.out.println(keysSet); + } + + private static void treeMapSortByKey() { + TreeMap sorted = new TreeMap<>(map); + sorted.putAll(map); + + sorted.entrySet().forEach(System.out::println); + + } + + private static void arrayListSortByValue() { + List employeeById = new ArrayList<>(map.values()); + + Collections.sort(employeeById); + + System.out.println(employeeById); + } + + private static void arrayListSortByKey() { + List employeeByKey = new ArrayList<>(map.keySet()); + Collections.sort(employeeByKey); + System.out.println(employeeByKey); + } + + private static void initialize() { + Employee employee1 = new Employee(1L, "Mher"); + map.put(employee1.getName(), employee1); + Employee employee2 = new Employee(22L, "Annie"); + map.put(employee2.getName(), employee2); + Employee employee3 = new Employee(8L, "John"); + map.put(employee3.getName(), employee3); + Employee employee4 = new Employee(2L, "George"); + map.put(employee4.getName(), employee4); + } + + private static void addDuplicates() { + Employee employee5 = new Employee(1L, "Mher"); + map.put(employee5.getName(), employee5); + Employee employee6 = new Employee(22L, "Annie"); + map.put(employee6.getName(), employee6); + } +} diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java new file mode 100644 index 0000000000..ba29d5c454 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/ProductUnitTest.java @@ -0,0 +1,174 @@ +package com.baeldung.map; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import static org.junit.jupiter.api.Assertions.*; + +class ProductUnitTest { + + + @Test + public void getExistingValue() { + HashMap productsByName = new HashMap<>(); + + Product eBike = new Product("E-Bike", "A bike with a battery"); + Product roadBike = new Product("Road bike", "A bike for competition"); + + productsByName.put(eBike.getName(), eBike); + productsByName.put(roadBike.getName(), roadBike); + + Product nextPurchase = productsByName.get("E-Bike"); + + assertEquals("A bike with a battery", nextPurchase.getDescription()); + } + + @Test + public void getNonExistingValue() { + HashMap productsByName = new HashMap<>(); + + Product eBike = new Product("E-Bike", "A bike with a battery"); + Product roadBike = new Product("Road bike", "A bike for competition"); + + productsByName.put(eBike.getName(), eBike); + productsByName.put(roadBike.getName(), roadBike); + + Product nextPurchase = productsByName.get("Car"); + + assertNull(nextPurchase); + } + + @Test + public void getExistingValueAfterSameKeyInsertedTwice() { + HashMap productsByName = new HashMap<>(); + + Product eBike = new Product("E-Bike", "A bike with a battery"); + Product roadBike = new Product("Road bike", "A bike for competition"); + Product newEBike = new Product("E-Bike", "A bike with a better battery"); + + productsByName.put(eBike.getName(), eBike); + productsByName.put(roadBike.getName(), roadBike); + productsByName.put(newEBike.getName(), newEBike); + + Product nextPurchase = productsByName.get("E-Bike"); + + assertEquals("A bike with a better battery", nextPurchase.getDescription()); + } + + @Test + public void getExistingValueWithNullKey() { + HashMap productsByName = new HashMap<>(); + + Product defaultProduct = new Product("Chocolate", "At least buy chocolate"); + + productsByName.put(null, defaultProduct); + productsByName.put(defaultProduct.getName(), defaultProduct); + + Product nextPurchase = productsByName.get(null); + assertEquals("At least buy chocolate", nextPurchase.getDescription()); + + nextPurchase = productsByName.get("Chocolate"); + assertEquals("At least buy chocolate", nextPurchase.getDescription()); + } + + @Test + public void insertSameObjectWithDifferentKey() { + HashMap productsByName = new HashMap<>(); + + Product defaultProduct = new Product("Chocolate", "At least buy chocolate"); + + productsByName.put(null, defaultProduct); + productsByName.put(defaultProduct.getName(), defaultProduct); + + assertSame(productsByName.get(null), productsByName.get("Chocolate")); + } + + @Test + public void checkIfKeyExists() { + HashMap productsByName = new HashMap<>(); + + Product eBike = new Product("E-Bike", "A bike with a battery"); + + productsByName.put(eBike.getName(), eBike); + + assertTrue(productsByName.containsKey("E-Bike")); + } + + @Test + public void checkIfValueExists() { + HashMap productsByName = new HashMap<>(); + + Product eBike = new Product("E-Bike", "A bike with a battery"); + + productsByName.put(eBike.getName(), eBike); + + assertTrue(productsByName.containsValue(eBike)); + } + + @Test + public void removeExistingKey() { + HashMap productsByName = new HashMap<>(); + + Product eBike = new Product("E-Bike", "A bike with a battery"); + Product roadBike = new Product("Road bike", "A bike for competition"); + + productsByName.put(eBike.getName(), eBike); + productsByName.put(roadBike.getName(), roadBike); + + productsByName.remove("E-Bike"); + + assertNull(productsByName.get("E-Bike")); + } + + @Test + public void givenMutableKeyWhenKeyChangeThenValueNotFound() { + // Given + MutableKey key = new MutableKey("initial"); + + Map items = new HashMap<>(); + items.put(key, "success"); + + // When + key.setName("changed"); + + // Then + assertNull(items.get(key)); + } + + static class MutableKey { + private String name; + + public MutableKey(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MutableKey that = (MutableKey) o; + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + } + +} diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java new file mode 100644 index 0000000000..4517dea328 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/MapToStringUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.map.convert; + +import org.apache.commons.collections4.MapUtils; +import org.junit.Assert; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class MapToStringUnitTest { + + private Map wordsByKey = new HashMap<>(); + + @BeforeEach + public void setup() { + wordsByKey.clear(); + wordsByKey.put(1, "one"); + wordsByKey.put(2, "two"); + wordsByKey.put(3, "three"); + wordsByKey.put(4, "four"); + } + + @Test + public void givenMap_WhenUsingIteration_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithIteration(wordsByKey); + Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); + } + + @Test + public void givenMap_WhenUsingStream_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithStream(wordsByKey); + Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); + } + + @Test + public void givenMap_WhenUsingGuava_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithGuava(wordsByKey); + Assert.assertEquals("1=one,2=two,3=three,4=four", mapAsString); + } + + @Test + public void givenMap_WhenUsingApache_ThenResultingMapIsCorrect() { + String mapAsString = MapToString.convertWithApache(wordsByKey); + Assert.assertEquals("{1=one, 2=two, 3=three, 4=four}", mapAsString); + MapUtils.debugPrint(System.out, "Map as String", wordsByKey); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java new file mode 100644 index 0000000000..2f80b30871 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/convert/StringToMapUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.map.convert; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +public class StringToMapUnitTest { + + @Test + public void givenString_WhenUsingStream_ThenResultingStringIsCorrect() { + Map wordsByKey = StringToMap.convertWithStream("1=one,2=two,3=three,4=four"); + Assert.assertEquals(4, wordsByKey.size()); + Assert.assertEquals("one", wordsByKey.get("1")); + } + + @Test + void givenString_WhenUsingGuava_ThenResultingStringIsCorrect() { + Map wordsByKey = StringToMap.convertWithGuava("1=one,2=two,3=three,4=four"); + Assert.assertEquals(4, wordsByKey.size()); + Assert.assertEquals("one", wordsByKey.get("1")); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java new file mode 100644 index 0000000000..e2d5e327e1 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/CopyHashMapUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.map.copyhashmap; + +import com.google.common.collect.ImmutableMap; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CopyHashMapUnitTest { + + @Test + public void givenHashMap_whenShallowCopy_thenCopyisNotSameAsOriginal() { + + HashMap map = new HashMap<>(); + Employee emp1 = new Employee("John"); + Employee emp2 = new Employee("Norman"); + map.put("emp1",emp1); + map.put("emp2",emp2); + + HashMap shallowCopy = CopyHashMap.shallowCopy(map); + + assertThat(shallowCopy).isNotSameAs(map); + + } + + @Test + public void givenHashMap_whenShallowCopyModifyingOriginalObject_thenCopyShouldChange() { + + HashMap map = new HashMap<>(); + Employee emp1 = new Employee("John"); + Employee emp2 = new Employee("Norman"); + map.put("emp1",emp1); + map.put("emp2",emp2); + + HashMap shallowCopy = CopyHashMap.shallowCopy(map); + + emp1.setName("Johny"); + + assertThat(shallowCopy.get("emp1")).isEqualTo(map.get("emp1")); + + } + + @Test + public void givenHashMap_whenDeepCopyModifyingOriginalObject_thenCopyShouldNotChange() { + + HashMap map = new HashMap<>(); + Employee emp1 = new Employee("John"); + Employee emp2 = new Employee("Norman"); + map.put("emp1",emp1); + map.put("emp2",emp2); + HashMap deepCopy = CopyHashMap.deepCopy(map); + + emp1.setName("Johny"); + + assertThat(deepCopy.get("emp1")).isNotEqualTo(map.get("emp1")); + + } + + @Test + public void givenImmutableMap_whenCopyUsingGuava_thenCopyShouldNotChange() { + Employee emp1 = new Employee("John"); + Employee emp2 = new Employee("Norman"); + + Map map = ImmutableMap. builder() + .put("emp1",emp1) + .put("emp2",emp2) + .build(); + Map shallowCopy = ImmutableMap.copyOf(map); + + assertThat(shallowCopy).isSameAs(map); + + } + +} diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java new file mode 100644 index 0000000000..5db55c26ea --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/copyhashmap/Employee.java @@ -0,0 +1,28 @@ +package com.baeldung.map.copyhashmap; + +import java.io.Serializable; + +public class Employee implements Serializable{ + + private String name; + + public Employee(String name) { + super(); + this.name = name; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return this.name; + } + +} + + diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java new file mode 100644 index 0000000000..7c6dffe787 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/initialize/MapInitializerUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.map.initialize; + +import org.junit.Test; + +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +public class MapInitializerUnitTest { + + @Test + public void givenStaticMap_whenUpdated_thenCorrect() { + + MapInitializer.articleMapOne.put("NewArticle1", "Convert array to List"); + + assertEquals(MapInitializer.articleMapOne.get("NewArticle1"), "Convert array to List"); + + } + + @Test(expected=UnsupportedOperationException.class) + public void givenSingleTonMap_whenEntriesAdded_throwsException() { + + Map map = MapInitializer.createSingletonMap(); + map.put("username2", "password2"); + } + +} diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java new file mode 100644 index 0000000000..30b945bfc8 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/mapmax/MapMaxUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.map.mapmax; + + +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +public class MapMaxUnitTest { + + Map map = null; + MapMax mapMax = null; + + + @Before + public void setupTestData() { + map = new HashMap(); + map.put(23, 12); + map.put(46, 24); + map.put(27, 38); + mapMax = new MapMax(); + } + + @Test + public void givenMap_whenIterated_thenReturnMaxValue() { + assertEquals(new Integer(38), mapMax.maxUsingIteration(map)); + } + + @Test + public void givenMap_whenUsingCollectionsMax_thenReturnMaxValue() { + assertEquals(new Integer(38), mapMax.maxUsingCollectionsMax(map)); + } + + @Test + public void givenMap_whenUsingCollectionsMaxAndLambda_thenReturnMaxValue() { + assertEquals(new Integer(38), mapMax.maxUsingCollectionsMaxAndLambda(map)); + } + + @Test + public void givenMap_whenUsingCollectionsMaxAndMethodReference_thenReturnMaxValue() { + assertEquals(new Integer(38), mapMax.maxUsingCollectionsMaxAndMethodReference(map)); + } + + @Test + public void givenMap_whenUsingStreamAndLambda_thenReturnMaxValue() { + assertEquals(new Integer(38), mapMax.maxUsingStreamAndLambda(map)); + } + + @Test + public void givenMap_whenUsingStreamAndMethodReference_thenReturnMaxValue() { + assertEquals(new Integer(38), mapMax.maxUsingStreamAndMethodReference (map)); + } + + +} diff --git a/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java new file mode 100644 index 0000000000..293f24c378 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-2/src/test/java/com/baeldung/map/weakhashmap/WeakHashMapUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.map.weakhashmap; + + +import org.junit.Test; + +import java.util.WeakHashMap; +import java.util.concurrent.TimeUnit; + +import static com.jayway.awaitility.Awaitility.await; +import static org.junit.Assert.assertTrue; + +public class WeakHashMapUnitTest { + + @Test + public void givenWeakHashMap_whenCacheValueThatHasNoReferenceToIt_GCShouldReclaimThatObject() { + //given + WeakHashMap map = new WeakHashMap<>(); + BigImage bigImage = new BigImage("image_id"); + UniqueImageName imageName = new UniqueImageName("name_of_big_image"); + + map.put(imageName, bigImage); + assertTrue(map.containsKey(imageName)); + + //when big image key is not reference anywhere + imageName = null; + System.gc(); + + //then GC will finally reclaim that object + await().atMost(10, TimeUnit.SECONDS).until(map::isEmpty); + } + + @Test + public void givenWeakHashMap_whenCacheValueThatHasNoReferenceToIt_GCShouldReclaimThatObjectButLeaveReferencedObject() { + //given + WeakHashMap map = new WeakHashMap<>(); + BigImage bigImageFirst = new BigImage("foo"); + UniqueImageName imageNameFirst = new UniqueImageName("name_of_big_image"); + + BigImage bigImageSecond = new BigImage("foo_2"); + UniqueImageName imageNameSecond = new UniqueImageName("name_of_big_image_2"); + + map.put(imageNameFirst, bigImageFirst); + map.put(imageNameSecond, bigImageSecond); + assertTrue(map.containsKey(imageNameFirst)); + assertTrue(map.containsKey(imageNameSecond)); + + //when + imageNameFirst = null; + System.gc(); + + //then + await().atMost(10, TimeUnit.SECONDS).until(() -> map.size() == 1); + await().atMost(10, TimeUnit.SECONDS).until(() -> map.containsKey(imageNameSecond)); + } + + + class BigImage { + public final String imageId; + + BigImage(String imageId) { + this.imageId = imageId; + } + } + + class UniqueImageName { + public final String imageName; + + UniqueImageName(String imageName) { + this.imageName = imageName; + } + } +} diff --git a/core-java-modules/core-java-collections-maps-3/README.md b/core-java-modules/core-java-collections-maps-3/README.md new file mode 100644 index 0000000000..142aa34800 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/README.md @@ -0,0 +1,8 @@ +## Java Collections Cookbooks and Examples + +This module contains articles about Map data structures in Java. + +### Relevant Articles: +- [Java TreeMap vs HashMap](https://www.baeldung.com/java-treemap-vs-hashmap) +- [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps) +- More articles: [[<-- prev]](/core-java-collections-maps-2) diff --git a/core-java-modules/core-java-collections-maps-3/pom.xml b/core-java-modules/core-java-collections-maps-3/pom.xml new file mode 100644 index 0000000000..95414c12c2 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + core-java-collections-maps-3 + 0.1.0-SNAPSHOT + core-java-collections-maps-3 + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java new file mode 100644 index 0000000000..0edd0cd87b --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/compare/HashMapComparisonUnitTest.java @@ -0,0 +1,225 @@ +package com.baeldung.map.compare; + +import com.google.common.base.Equivalence; +import com.google.common.collect.MapDifference; +import com.google.common.collect.MapDifference.ValueDifference; +import com.google.common.collect.Maps; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsMapContaining.hasEntry; +import static org.hamcrest.collection.IsMapContaining.hasKey; +import static org.junit.Assert.*; + +public class HashMapComparisonUnitTest { + + Map asiaCapital1; + Map asiaCapital2; + Map asiaCapital3; + + Map asiaCity1; + Map asiaCity2; + Map asiaCity3; + + @Before + public void setup(){ + asiaCapital1 = new HashMap(); + asiaCapital1.put("Japan", "Tokyo"); + asiaCapital1.put("South Korea", "Seoul"); + + asiaCapital2 = new HashMap(); + asiaCapital2.put("South Korea", "Seoul"); + asiaCapital2.put("Japan", "Tokyo"); + + asiaCapital3 = new HashMap(); + asiaCapital3.put("Japan", "Tokyo"); + asiaCapital3.put("China", "Beijing"); + + asiaCity1 = new HashMap(); + asiaCity1.put("Japan", new String[] { "Tokyo", "Osaka" }); + asiaCity1.put("South Korea", new String[] { "Seoul", "Busan" }); + + asiaCity2 = new HashMap(); + asiaCity2.put("South Korea", new String[] { "Seoul", "Busan" }); + asiaCity2.put("Japan", new String[] { "Tokyo", "Osaka" }); + + asiaCity3 = new HashMap(); + asiaCity3.put("Japan", new String[] { "Tokyo", "Osaka" }); + asiaCity3.put("China", new String[] { "Beijing", "Hong Kong" }); + } + + @Test + public void whenCompareTwoHashMapsUsingEquals_thenSuccess() { + assertTrue(asiaCapital1.equals(asiaCapital2)); + assertFalse(asiaCapital1.equals(asiaCapital3)); + } + + @Test + public void whenCompareTwoHashMapsWithArrayValuesUsingEquals_thenFail() { + assertFalse(asiaCity1.equals(asiaCity2)); + } + + @Test + public void whenCompareTwoHashMapsUsingStreamAPI_thenSuccess() { + assertTrue(areEqual(asiaCapital1, asiaCapital2)); + assertFalse(areEqual(asiaCapital1, asiaCapital3)); + } + + @Test + public void whenCompareTwoHashMapsWithArrayValuesUsingStreamAPI_thenSuccess() { + assertTrue(areEqualWithArrayValue(asiaCity1, asiaCity2)); + assertFalse(areEqualWithArrayValue(asiaCity1, asiaCity3)); + } + + @Test + public void whenCompareTwoHashMapKeys_thenSuccess() { + assertTrue(asiaCapital1.keySet().equals(asiaCapital2.keySet())); + assertFalse(asiaCapital1.keySet().equals(asiaCapital3.keySet())); + } + + @Test + public void whenCompareTwoHashMapKeyValuesUsingStreamAPI_thenSuccess() { + Map asiaCapital3 = new HashMap(); + asiaCapital3.put("Japan", "Tokyo"); + asiaCapital3.put("South Korea", "Seoul"); + asiaCapital3.put("China", "Beijing"); + + Map asiaCapital4 = new HashMap(); + asiaCapital4.put("South Korea", "Seoul"); + asiaCapital4.put("Japan", "Osaka"); + asiaCapital4.put("China", "Beijing"); + + Map result = areEqualKeyValues(asiaCapital3, asiaCapital4); + + assertEquals(3, result.size()); + assertThat(result, hasEntry("Japan", false)); + assertThat(result, hasEntry("South Korea", true)); + assertThat(result, hasEntry("China", true)); + } + + @Test + public void givenDifferentMaps_whenGetDiffUsingGuava_thenSuccess() { + Map asia1 = new HashMap(); + asia1.put("Japan", "Tokyo"); + asia1.put("South Korea", "Seoul"); + asia1.put("India", "New Delhi"); + + Map asia2 = new HashMap(); + asia2.put("Japan", "Tokyo"); + asia2.put("China", "Beijing"); + asia2.put("India", "Delhi"); + + MapDifference diff = Maps.difference(asia1, asia2); + Map> entriesDiffering = diff.entriesDiffering(); + + assertFalse(diff.areEqual()); + assertEquals(1, entriesDiffering.size()); + assertThat(entriesDiffering, hasKey("India")); + assertEquals("New Delhi", entriesDiffering.get("India").leftValue()); + assertEquals("Delhi", entriesDiffering.get("India").rightValue()); + } + + @Test + public void givenDifferentMaps_whenGetEntriesOnOneSideUsingGuava_thenSuccess() { + Map asia1 = new HashMap(); + asia1.put("Japan", "Tokyo"); + asia1.put("South Korea", "Seoul"); + asia1.put("India", "New Delhi"); + + Map asia2 = new HashMap(); + asia2.put("Japan", "Tokyo"); + asia2.put("China", "Beijing"); + asia2.put("India", "Delhi"); + + MapDifference diff = Maps.difference(asia1, asia2); + Map entriesOnlyOnRight = diff.entriesOnlyOnRight(); + Map entriesOnlyOnLeft = diff.entriesOnlyOnLeft(); + + assertEquals(1, entriesOnlyOnRight.size()); + assertThat(entriesOnlyOnRight, hasEntry("China", "Beijing")); + assertEquals(1, entriesOnlyOnLeft.size()); + assertThat(entriesOnlyOnLeft, hasEntry("South Korea", "Seoul")); + } + + @Test + public void givenDifferentMaps_whenGetCommonEntriesUsingGuava_thenSuccess() { + Map asia1 = new HashMap(); + asia1.put("Japan", "Tokyo"); + asia1.put("South Korea", "Seoul"); + asia1.put("India", "New Delhi"); + + Map asia2 = new HashMap(); + asia2.put("Japan", "Tokyo"); + asia2.put("China", "Beijing"); + asia2.put("India", "Delhi"); + + MapDifference diff = Maps.difference(asia1, asia2); + Map entriesInCommon = diff.entriesInCommon(); + + assertEquals(1, entriesInCommon.size()); + assertThat(entriesInCommon, hasEntry("Japan", "Tokyo")); + } + + @Test + public void givenSimilarMapsWithArrayValue_whenCompareUsingGuava_thenFail() { + MapDifference diff = Maps.difference(asiaCity1, asiaCity2); + assertFalse(diff.areEqual()); + } + + @Test + public void givenSimilarMapsWithArrayValue_whenCompareUsingGuavaEquivalence_thenSuccess() { + Equivalence eq = new Equivalence() { + @Override + protected boolean doEquivalent(String[] a, String[] b) { + return Arrays.equals(a, b); + } + + @Override + protected int doHash(String[] value) { + return value.hashCode(); + } + }; + + MapDifference diff = Maps.difference(asiaCity1, asiaCity2, eq); + assertTrue(diff.areEqual()); + + diff = Maps.difference(asiaCity1, asiaCity3, eq); + assertFalse(diff.areEqual()); + } + + // =========================================================================== + + private boolean areEqual(Map first, Map second) { + if (first.size() != second.size()) { + return false; + } + + return first.entrySet() + .stream() + .allMatch(e -> e.getValue() + .equals(second.get(e.getKey()))); + } + + private boolean areEqualWithArrayValue(Map first, Map second) { + if (first.size() != second.size()) { + return false; + } + + return first.entrySet() + .stream() + .allMatch(e -> Arrays.equals(e.getValue(), second.get(e.getKey()))); + } + + private Map areEqualKeyValues(Map first, Map second) { + return first.entrySet() + .stream() + .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().equals(second.get(e.getKey())))); + } + +} diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java new file mode 100644 index 0000000000..1057e3b9f0 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/treemaphashmap/TreeMapVsHashMapUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.map.treemaphashmap; + +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +public class TreeMapVsHashMapUnitTest { + + @Test + public void whenInsertObjectsTreeMap_thenNaturalOrder() { + Map treemap = new TreeMap<>(); + treemap.put(3, "TreeMap"); + treemap.put(2, "vs"); + treemap.put(1, "HashMap"); + Assert.assertThat(treemap.keySet(), Matchers.contains(1, 2, 3)); + } + + @Test(expected = NullPointerException.class) + public void whenInsertNullInTreeMap_thenException() { + Map treemap = new TreeMap<>(); + treemap.put(null, "NullPointerException"); + } + + @Test + public void whenInsertObjectsHashMap_thenRandomOrder() { + Map hashmap = new HashMap<>(); + hashmap.put(3, "TreeMap"); + hashmap.put(2, "vs"); + hashmap.put(1, "HashMap"); + Assert.assertThat(hashmap.keySet(), Matchers.containsInAnyOrder(1, 2, 3)); + } + + @Test + public void whenInsertNullInHashMap_thenInsertsNull() { + Map hashmap = new HashMap<>(); + hashmap.put(null, null); + Assert.assertNull(hashmap.get(null)); + } + + @Test + public void givenHashMapAndTreeMap_whenputDuplicates_thenOnlyUnique() { + Map treeMap = new HashMap<>(); + treeMap.put(1, "Baeldung"); + treeMap.put(1, "Baeldung"); + + Assert.assertTrue(treeMap.size() == 1); + + Map treeMap2 = new TreeMap<>(); + treeMap2.put(1, "Baeldung"); + treeMap2.put(1, "Baeldung"); + + Assert.assertTrue(treeMap2.size() == 1); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps/README.md b/core-java-modules/core-java-collections-maps/README.md new file mode 100644 index 0000000000..1323fb97cd --- /dev/null +++ b/core-java-modules/core-java-collections-maps/README.md @@ -0,0 +1,16 @@ +## Java Collections Cookbooks and Examples + +This module contains articles about Map data structures in Java. + +### Relevant Articles: +- [Guide to the Guava BiMap](https://www.baeldung.com/guava-bimap) +- [A Guide to Java HashMap](https://www.baeldung.com/java-hashmap) +- [A Guide to LinkedHashMap in Java](https://www.baeldung.com/java-linked-hashmap) +- [A Guide to TreeMap in Java](https://www.baeldung.com/java-treemap) +- [How to Store Duplicate Keys in a Map in Java?](https://www.baeldung.com/java-map-duplicate-keys) +- [Get the Key for a Value from a Java Map](https://www.baeldung.com/java-map-key-from-value) +- [How to Check If a Key Exists in a Map](https://www.baeldung.com/java-map-key-exists) +- [Immutable Map Implementations in Java](https://www.baeldung.com/java-immutable-maps) +- [Guide to Apache Commons MultiValuedMap](https://www.baeldung.com/apache-commons-multi-valued-map) +- [The Java HashMap Under the Hood](https://www.baeldung.com/java-hashmap-advanced) +- More articles: [[next -->]](/core-java-collections-maps-2) diff --git a/core-java-modules/core-java-collections-maps/pom.xml b/core-java-modules/core-java-collections-maps/pom.xml new file mode 100644 index 0000000000..c0dd705c1c --- /dev/null +++ b/core-java-modules/core-java-collections-maps/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + core-java-collections-maps + 0.1.0-SNAPSHOT + core-java-collections-maps + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + 4.1 + 3.6.1 + + diff --git a/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java new file mode 100644 index 0000000000..91b7197a92 --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MapUtil.java @@ -0,0 +1,44 @@ +/** + * + */ +package com.baeldung.map; + +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Stream; + +/** + * @author swpraman + * + */ +public class MapUtil { + + public static Stream keys(Map map, V value) { + return map.entrySet() + .stream() + .filter(entry -> value.equals(entry.getValue())) + .map(Map.Entry::getKey); + } + + public static Set getKeys(Map map, V value) { + Set keys = new HashSet<>(); + for (Entry entry : map.entrySet()) { + if (entry.getValue().equals(value)) { + keys.add(entry.getKey()); + } + } + return keys; + } + + public static K getKey(Map map, V value) { + for (Entry entry : map.entrySet()) { + if (entry.getValue().equals(value)) { + return entry.getKey(); + } + } + return null; + } + +} diff --git a/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyKey.java b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyKey.java new file mode 100644 index 0000000000..9993d7862c --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyKey.java @@ -0,0 +1,64 @@ +package com.baeldung.map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MyKey { + private static final Logger LOG = LoggerFactory.getLogger(MyKey.class); + + private String name; + private int id; + + public MyKey(int id, String name) { + this.id = id; + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public int hashCode() { + LOG.debug("Calling hashCode()"); + return id; + } + + @Override + public String toString() { + return "MyKey [name=" + name + ", id=" + id + "]"; + } + + @Override + public boolean equals(Object obj) { + LOG.debug("Calling equals() for key: " + obj); + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + MyKey other = (MyKey) obj; + if (id != other.id) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + +} diff --git a/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java new file mode 100644 index 0000000000..b687e57d85 --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/main/java/com/baeldung/map/MyLinkedHashMap.java @@ -0,0 +1,23 @@ +package com.baeldung.map; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class MyLinkedHashMap extends LinkedHashMap { + + /** + * + */ + private static final long serialVersionUID = 1L; + private static final int MAX_ENTRIES = 5; + + public MyLinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { + super(initialCapacity, loadFactor, accessOrder); + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > MAX_ENTRIES; + } + +} diff --git a/core-java-modules/core-java-collections-maps/src/main/resources/logback.xml b/core-java-modules/core-java-collections-maps/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java new file mode 100644 index 0000000000..b44d2db1aa --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/guava/GuavaBiMapUnitTest.java @@ -0,0 +1,120 @@ +package com.baeldung.guava; + +import static org.junit.Assert.*; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import com.google.common.collect.BiMap; +import com.google.common.collect.EnumHashBiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableBiMap; + +public class GuavaBiMapUnitTest { + @Test + public void whenQueryByValue_returnsKey() { + final BiMap capitalCountryBiMap = HashBiMap.create(); + capitalCountryBiMap.put("New Delhi", "India"); + capitalCountryBiMap.put("Washingon, D.C.", "USA"); + capitalCountryBiMap.put("Moscow", "Russia"); + + final String countryCapitalName = capitalCountryBiMap.inverse().get("India"); + + assertEquals("New Delhi", countryCapitalName); + } + + @Test + public void whenCreateBiMapFromExistingMap_returnsKey() { + final Map capitalCountryMap = new HashMap<>(); + capitalCountryMap.put("New Delhi", "India"); + capitalCountryMap.put("Washingon, D.C.", "USA"); + capitalCountryMap.put("Moscow", "Russia"); + final BiMap capitalCountryBiMap = HashBiMap.create(capitalCountryMap); + + final String countryCapitalName = capitalCountryBiMap.inverse().get("India"); + + assertEquals("New Delhi", countryCapitalName); + } + + @Test + public void whenQueryByKey_returnsValue() { + final BiMap capitalCountryBiMap = HashBiMap.create(); + + capitalCountryBiMap.put("New Delhi", "India"); + capitalCountryBiMap.put("Washingon, D.C.", "USA"); + capitalCountryBiMap.put("Moscow", "Russia"); + + assertEquals("USA", capitalCountryBiMap.get("Washingon, D.C.")); + } + + @Test(expected = IllegalArgumentException.class) + public void whenSameValueIsPresent_throwsException() { + final BiMap capitalCountryBiMap = HashBiMap.create(); + + capitalCountryBiMap.put("New Delhi", "India"); + capitalCountryBiMap.put("Washingon, D.C.", "USA"); + capitalCountryBiMap.put("Moscow", "Russia"); + capitalCountryBiMap.put("Trump", "USA"); + } + + @Test + public void givenSameValueIsPresent_whenForcePut_completesSuccessfully() { + final BiMap capitalCountryBiMap = HashBiMap.create(); + + capitalCountryBiMap.put("New Delhi", "India"); + capitalCountryBiMap.put("Washingon, D.C.", "USA"); + capitalCountryBiMap.put("Moscow", "Russia"); + capitalCountryBiMap.forcePut("Trump", "USA"); + + assertEquals("USA", capitalCountryBiMap.get("Trump")); + assertEquals("Trump", capitalCountryBiMap.inverse().get("USA")); + } + + @Test + public void whenSameKeyIsPresent_replacesAlreadyPresent() { + final BiMap capitalCountryBiMap = HashBiMap.create(); + + capitalCountryBiMap.put("New Delhi", "India"); + capitalCountryBiMap.put("Washingon, D.C.", "USA"); + capitalCountryBiMap.put("Moscow", "Russia"); + capitalCountryBiMap.put("Washingon, D.C.", "HongKong"); + + assertEquals("HongKong", capitalCountryBiMap.get("Washingon, D.C.")); + } + + @Test + public void whenUsingImmutableBiMap_allowsPutSuccessfully() { + final BiMap capitalCountryBiMap = new ImmutableBiMap.Builder().put("New Delhi", "India").put("Washingon, D.C.", "USA").put("Moscow", "Russia").build(); + + assertEquals("USA", capitalCountryBiMap.get("Washingon, D.C.")); + } + + @Test(expected = UnsupportedOperationException.class) + public void whenUsingImmutableBiMap_doesntAllowRemove() { + final BiMap capitalCountryBiMap = new ImmutableBiMap.Builder().put("New Delhi", "India").put("Washingon, D.C.", "USA").put("Moscow", "Russia").build(); + + capitalCountryBiMap.remove("New Delhi"); + } + + @Test(expected = UnsupportedOperationException.class) + public void whenUsingImmutableBiMap_doesntAllowPut() { + final BiMap capitalCountryBiMap = new ImmutableBiMap.Builder().put("New Delhi", "India").put("Washingon, D.C.", "USA").put("Moscow", "Russia").build(); + + capitalCountryBiMap.put("New York", "USA"); + } + + private enum Operation { + ADD, SUBTRACT, MULTIPLY, DIVIDE + } + + @Test + public void whenUsingEnumAsKeyInMap_replacesAlreadyPresent() { + final BiMap operationStringBiMap = EnumHashBiMap.create(Operation.class); + + operationStringBiMap.put(Operation.ADD, "Add"); + operationStringBiMap.put(Operation.SUBTRACT, "Subtract"); + operationStringBiMap.put(Operation.MULTIPLY, "Multiply"); + operationStringBiMap.put(Operation.DIVIDE, "Divide"); + + assertEquals("Divide", operationStringBiMap.get(Operation.DIVIDE)); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java new file mode 100644 index 0000000000..d308aac7eb --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/ImmutableMapUnitTest.java @@ -0,0 +1,84 @@ +package com.baeldung.map; + +import com.google.common.collect.ImmutableMap; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + + +public class ImmutableMapUnitTest { + + @Test + public void whenCollectionsUnModifiableMapMethod_thenOriginalCollectionChangesReflectInUnmodifiableMap() { + + Map mutableMap = new HashMap<>(); + mutableMap.put("USA", "North America"); + + Map unmodifiableMap = Collections.unmodifiableMap(mutableMap); + assertThrows(UnsupportedOperationException.class, () -> unmodifiableMap.put("Canada", "North America")); + + mutableMap.remove("USA"); + assertFalse(unmodifiableMap.containsKey("USA")); + + mutableMap.put("Mexico", "North America"); + assertTrue(unmodifiableMap.containsKey("Mexico")); + } + + @Test + @SuppressWarnings("deprecation") + public void whenGuavaImmutableMapFromCopyOfMethod_thenOriginalCollectionChangesDoNotReflectInImmutableMap() { + + Map mutableMap = new HashMap<>(); + mutableMap.put("USA", "North America"); + + ImmutableMap immutableMap = ImmutableMap.copyOf(mutableMap); + assertTrue(immutableMap.containsKey("USA")); + + assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America")); + + mutableMap.remove("USA"); + assertTrue(immutableMap.containsKey("USA")); + + mutableMap.put("Mexico", "North America"); + assertFalse(immutableMap.containsKey("Mexico")); + } + + @Test + @SuppressWarnings("deprecation") + public void whenGuavaImmutableMapFromBuilderMethod_thenOriginalCollectionChangesDoNotReflectInImmutableMap() { + + Map mutableMap = new HashMap<>(); + mutableMap.put("USA", "North America"); + + ImmutableMap immutableMap = ImmutableMap.builder() + .putAll(mutableMap) + .put("Costa Rica", "North America") + .build(); + assertTrue(immutableMap.containsKey("USA")); + assertTrue(immutableMap.containsKey("Costa Rica")); + + assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America")); + + mutableMap.remove("USA"); + assertTrue(immutableMap.containsKey("USA")); + + mutableMap.put("Mexico", "North America"); + assertFalse(immutableMap.containsKey("Mexico")); + } + + @Test + @SuppressWarnings("deprecation") + public void whenGuavaImmutableMapFromOfMethod_thenOriginalCollectionChangesDoNotReflectInImmutableMap() { + + ImmutableMap immutableMap = ImmutableMap.of("USA", "North America", "Costa Rica", "North America"); + assertTrue(immutableMap.containsKey("USA")); + assertTrue(immutableMap.containsKey("Costa Rica")); + + assertThrows(UnsupportedOperationException.class, () -> immutableMap.put("Canada", "North America")); + } + +} diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java new file mode 100644 index 0000000000..dbad2e5b5e --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/KeyCheckUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.map; + +import org.junit.Test; + +import java.util.Collections; +import java.util.Map; + +import static org.junit.Assert.*; + +public class KeyCheckUnitTest { + + @Test + public void whenKeyIsPresent_thenContainsKeyReturnsTrue() { + Map map = Collections.singletonMap("key", "value"); + + assertTrue(map.containsKey("key")); + assertFalse(map.containsKey("missing")); + } + + @Test + public void whenKeyHasNullValue_thenGetStillWorks() { + Map map = Collections.singletonMap("nothing", null); + + assertTrue(map.containsKey("nothing")); + assertNull(map.get("nothing")); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java new file mode 100644 index 0000000000..721b48ea7b --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapMultipleValuesUnitTest.java @@ -0,0 +1,119 @@ +package com.baeldung.map; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.TreeMultimap; +import org.apache.commons.collections4.MultiMap; +import org.apache.commons.collections4.MultiMapUtils; +import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.map.MultiValueMap; +import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; +import org.apache.commons.collections4.multimap.HashSetValuedHashMap; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MapMultipleValuesUnitTest { + private static final Logger LOG = LoggerFactory.getLogger(MapMultipleValuesUnitTest.class); + + @Test + public void givenHashMap_whenPuttingTwice_thenReturningFirstValue() { + Map map = new HashMap<>(); + assertThat(map.put("key1", "value1")).isEqualTo(null); + assertThat(map.put("key1", "value2")).isEqualTo("value1"); + assertThat(map.get("key1")).isEqualTo("value2"); + } + + @Test + public void givenCollectionAsValue_whenPuttingTwice_thenReturningCollection() { + Map> map = new HashMap<>(); + List list = new ArrayList<>(); + map.put("key1", list); + map.get("key1").add("value1"); + map.get("key1").add("value2"); + assertThat(map.get("key1").get(0)).isEqualTo("value1"); + assertThat(map.get("key1").get(1)).isEqualTo("value2"); + } + + @Test + public void givenCollectionAsValueAndJava8_whenPuttingTwice_thenReturningCollection() { + Map> map = new HashMap<>(); + map.computeIfAbsent("key1", k -> new ArrayList<>()).add("value1"); + map.computeIfAbsent("key1", k -> new ArrayList<>()).add("value2"); + assertThat(map.get("key1").get(0)).isEqualTo("value1"); + assertThat(map.get("key1").get(1)).isEqualTo("value2"); + } + + @Test + public void givenMultiValueMap_whenPuttingTwice_thenReturningValues() { + MultiMap map = new MultiValueMap<>(); + map.put("key1", "value1"); + map.put("key1", "value2"); + assertThat((Collection) map.get("key1")) + .contains("value1", "value2"); + } + + @Test + public void givenArrayListValuedHashMap_whenPuttingDoubleValues_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key1", "value1"); + map.put("key1", "value2"); + map.put("key1", "value2"); + assertThat((Collection) map.get("key1")) + .containsExactly("value1", "value2", "value2"); + } + + @Test + public void givenHashSetValuedHashMap_whenPuttingTwiceTheSame_thenReturningOneValue() { + MultiValuedMap map = new HashSetValuedHashMap<>(); + map.put("key1", "value1"); + map.put("key1", "value1"); + assertThat((Collection) map.get("key1")) + .containsExactly("value1"); + } + + @Test(expected = UnsupportedOperationException.class) + public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("key1", "value1"); + map.put("key1", "value2"); + MultiValuedMap immutableMap = + MultiMapUtils.unmodifiableMultiValuedMap(map); + immutableMap.put("key1", "value3"); + } + + @Test + public void givenArrayListMultiMap_whenInserting_thenCorrectOutput() { + Multimap map = ArrayListMultimap.create(); + map.put("key1", "value2"); + map.put("key1", "value1"); + assertThat((Collection) map.get("key1")) + .containsExactly("value2", "value1"); + } + + @Test + public void givenLinkedHashMultiMap_whenInserting_thenReturningValuesInInsertionOrder() { + Multimap map = LinkedHashMultimap.create(); + map.put("key1", "value3"); + map.put("key1", "value1"); + map.put("key1", "value2"); + assertThat((Collection) map.get("key1")) + .containsExactly("value3", "value1", "value2"); + } + + @Test + public void givenTreeMultimap_whenInserting_thenReturningValuesInNaturalOrder() { + Multimap map = TreeMultimap.create(); + map.put("key1", "value3"); + map.put("key1", "value1"); + map.put("key1", "value2"); + assertThat((Collection) map.get("key1")) + .containsExactly("value1", "value2", "value3"); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapUnitTest.java new file mode 100644 index 0000000000..eaf68ccba5 --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapUnitTest.java @@ -0,0 +1,336 @@ +package com.baeldung.map; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.Map.Entry; + +import static org.junit.Assert.*; + +public class MapUnitTest { + private static final Logger LOG = LoggerFactory.getLogger(MapUnitTest.class); + + + @Test + public void givenHashMap_whenRetrievesKeyset_thenCorrect() { + Map map = new HashMap<>(); + map.put("name", "baeldung"); + map.put("type", "blog"); + + Set keys = map.keySet(); + + assertEquals(2, keys.size()); + assertTrue(keys.contains("name")); + assertTrue(keys.contains("type")); + } + + @Test + public void givenHashMap_whenRetrievesValues_thenCorrect() { + Map map = new HashMap<>(); + map.put("name", "baeldung"); + map.put("type", "blog"); + + Collection values = map.values(); + + assertEquals(2, values.size()); + assertTrue(values.contains("baeldung")); + assertTrue(values.contains("blog")); + } + + @Test + public void givenHashMap_whenRetrievesEntries_thenCorrect() { + Map map = new HashMap<>(); + map.put("name", "baeldung"); + map.put("type", "blog"); + + Set> entries = map.entrySet(); + + assertEquals(2, entries.size()); + for (Entry e : entries) { + String key = e.getKey(); + String val = e.getValue(); + assertTrue(key.equals("name") || key.equals("type")); + assertTrue(val.equals("baeldung") || val.equals("blog")); + } + } + + @Test + public void givenKeySet_whenChangeReflectsInMap_thenCorrect() { + Map map = new HashMap<>(); + map.put("name", "baeldung"); + map.put("type", "blog"); + + assertEquals(2, map.size()); + + Set keys = map.keySet(); + + keys.remove("name"); + assertEquals(1, map.size()); + } + + @Test(expected = ConcurrentModificationException.class) + public void givenIterator_whenFailsFastOnModification_thenCorrect() { + Map map = new HashMap<>(); + map.put("name", "baeldung"); + map.put("type", "blog"); + + Set keys = map.keySet(); + Iterator it = keys.iterator(); + map.remove("type"); + while (it.hasNext()) { + String key = it.next(); + } + } + + public void givenIterator_whenRemoveWorks_thenCorrect() { + Map map = new HashMap<>(); + map.put("name", "baeldung"); + map.put("type", "blog"); + + Set keys = map.keySet(); + Iterator it = keys.iterator(); + while (it.hasNext()) { + it.next(); + it.remove(); + } + assertEquals(0, map.size()); + } + + @Test + public void whenHashCodeIsCalledOnPut_thenCorrect() { + MyKey key = new MyKey(1, "name"); + Map map = new HashMap<>(); + map.put(key, "val"); + } + + @Test + public void whenHashCodeIsCalledOnGet_thenCorrect() { + MyKey key = new MyKey(1, "name"); + Map map = new HashMap<>(); + map.put(key, "val"); + map.get(key); + } + + @Test + public void whenGetWorks_thenCorrect() { + Map map = new HashMap<>(); + map.put("key", "val"); + + String val = map.get("key"); + + assertEquals("val", val); + } + + @Test + public void givenNewKey_whenPutReturnsNull_thenCorrect() { + Map map = new HashMap<>(); + + String rtnVal = map.put("key1", "val1"); + + assertNull(rtnVal); + } + + @Test + public void givenUnmappedKey_whenGetReturnsNull_thenCorrect() { + Map map = new HashMap<>(); + + String rtnVal = map.get("key1"); + + assertNull(rtnVal); + } + + @Test + public void givenNullVal_whenPutReturnsNull_thenCorrect() { + Map map = new HashMap<>(); + + String rtnVal = map.put("key1", null); + + assertNull(rtnVal); + } + + @Test + public void givenNullKeyAndVal_whenAccepts_thenCorrect() { + Map map = new HashMap<>(); + + map.put(null, null); + } + + @Test + public void givenNullVal_whenRetrieves_thenCorrect() { + Map map = new HashMap<>(); + map.put("key", null); + + String val = map.get("key"); + + assertNull(val); + } + + @Test + public void whenContainsDistinguishesNullValues_thenCorrect() { + Map map = new HashMap<>(); + + String val1 = map.get("key"); + boolean valPresent = map.containsKey("key"); + + assertNull(val1); + assertFalse(valPresent); + + map.put("key", null); + String val = map.get("key"); + valPresent = map.containsKey("key"); + + assertNull(val); + assertTrue(valPresent); + + } + + @Test + public void whenPutReturnsPrevValue_thenCorrect() { + Map map = new HashMap<>(); + map.put("key1", "val1"); + String rtnVal = map.put("key1", "val2"); + + assertEquals("val1", rtnVal); + } + + @Test + public void whenCallsEqualsOnCollision_thenCorrect() { + HashMap map = new HashMap<>(); + MyKey k1 = new MyKey(1, "firstKey"); + MyKey k2 = new MyKey(2, "secondKey"); + MyKey k3 = new MyKey(2, "thirdKey"); + + LOG.debug("storing value for k1"); + map.put(k1, "firstValue"); + + LOG.debug("storing value for k2"); + map.put(k2, "secondValue"); + + LOG.debug("storing value for k3"); + map.put(k3, "thirdValue"); + + LOG.debug("retrieving value for k1"); + String v1 = map.get(k1); + + LOG.debug("retrieving value for k2"); + String v2 = map.get(k2); + + LOG.debug("retrieving value for k3"); + String v3 = map.get(k3); + + assertEquals("firstValue", v1); + assertEquals("secondValue", v2); + assertEquals("thirdValue", v3); + + } + + @Test + public void givenLinkedHashMap_whenGetsOrderedKeyset_thenCorrect() { + LinkedHashMap map = new LinkedHashMap<>(); + map.put(1, null); + map.put(2, null); + map.put(3, null); + map.put(4, null); + map.put(5, null); + Set keys = map.keySet(); + Integer[] arr = keys.toArray(new Integer[0]); + for (int i = 0; i < arr.length; i++) { + assertEquals(new Integer(i + 1), arr[i]); + + } + } + + @Test + public void givenLinkedHashMap_whenAccessOrderWorks_thenCorrect() { + LinkedHashMap map = new LinkedHashMap<>(16, .75f, true); + map.put(1, null); + map.put(2, null); + map.put(3, null); + map.put(4, null); + map.put(5, null); + Set keys = map.keySet(); + assertEquals("[1, 2, 3, 4, 5]", keys.toString()); + map.get(4); + assertEquals("[1, 2, 3, 5, 4]", keys.toString()); + map.get(1); + assertEquals("[2, 3, 5, 4, 1]", keys.toString()); + map.get(3); + assertEquals("[2, 5, 4, 1, 3]", keys.toString()); + } + + @Test + public void givenLinkedHashMap_whenRemovesEldestEntry_thenCorrect() { + LinkedHashMap map = new MyLinkedHashMap<>(16, .75f, true); + map.put(1, null); + map.put(2, null); + map.put(3, null); + map.put(4, null); + map.put(5, null); + Set keys = map.keySet(); + assertEquals("[1, 2, 3, 4, 5]", keys.toString()); + map.put(6, null); + assertEquals("[2, 3, 4, 5, 6]", keys.toString()); + map.put(7, null); + assertEquals("[3, 4, 5, 6, 7]", keys.toString()); + map.put(8, null); + assertEquals("[4, 5, 6, 7, 8]", keys.toString()); + } + + @Test + public void givenTreeMap_whenOrdersEntriesNaturally_thenCorrect() { + TreeMap map = new TreeMap<>(); + map.put(3, "val"); + map.put(2, "val"); + map.put(1, "val"); + map.put(5, "val"); + map.put(4, "val"); + assertEquals("[1, 2, 3, 4, 5]", map.keySet().toString()); + } + + @Test + public void givenTreeMap_whenOrdersEntriesNaturally_thenCorrect2() { + TreeMap map = new TreeMap<>(); + map.put("c", "val"); + map.put("b", "val"); + map.put("a", "val"); + map.put("e", "val"); + map.put("d", "val"); + + assertEquals("[a, b, c, d, e]", map.keySet().toString()); + } + + @Test + public void givenTreeMap_whenOrdersEntriesByComparator_thenCorrect() { + TreeMap map = new TreeMap<>(Comparator.reverseOrder()); + map.put(3, "val"); + map.put(2, "val"); + map.put(1, "val"); + map.put(5, "val"); + map.put(4, "val"); + + assertEquals("[5, 4, 3, 2, 1]", map.keySet().toString()); + } + + @Test + public void givenTreeMap_whenPerformsQueries_thenCorrect() { + TreeMap map = new TreeMap<>(); + map.put(3, "val"); + map.put(2, "val"); + map.put(1, "val"); + map.put(5, "val"); + map.put(4, "val"); + + Integer highestKey = map.lastKey(); + Integer lowestKey = map.firstKey(); + Set keysLessThan3 = map.headMap(3).keySet(); + Set keysGreaterThanEqTo3 = map.tailMap(3).keySet(); + + assertEquals(new Integer(5), highestKey); + assertEquals(new Integer(1), lowestKey); + assertEquals("[1, 2]", keysLessThan3.toString()); + assertEquals("[3, 4, 5]", keysGreaterThanEqTo3.toString()); + } + +} diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapUtilUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapUtilUnitTest.java new file mode 100644 index 0000000000..f8e4c8fd8a --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MapUtilUnitTest.java @@ -0,0 +1,103 @@ +/** + * + */ +package com.baeldung.map; + +import com.google.common.collect.HashBiMap; +import org.apache.commons.collections4.BidiMap; +import org.apache.commons.collections4.bidimap.DualHashBidiMap; +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; + +/** + * @author swpraman + * + */ +public class MapUtilUnitTest { + + + @Test + public void whenUsingImperativeWayForSingleKey_shouldReturnSingleKey() { + Map capitalCountryMap = new HashMap<>(); + capitalCountryMap.put("Tokyo", "Japan"); + capitalCountryMap.put("New Delhi", "India"); + assertEquals("New Delhi", MapUtil.getKey(capitalCountryMap, "India")); + } + + @Test + public void whenUsingImperativeWayForAllKeys_shouldReturnAllKeys() { + Map capitalCountryMap = new HashMap<>(); + capitalCountryMap.put("Tokyo", "Japan"); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + capitalCountryMap.put("Pretoria", "South Africa"); + capitalCountryMap.put("Bloemfontein", "South Africa"); + + assertEquals(new HashSet(Arrays.asList( + new String[] {"Cape Town", "Pretoria", "Bloemfontein"})), + MapUtil.getKeys(capitalCountryMap, "South Africa")); + } + + @Test + public void whenUsingFunctionalWayForSingleKey_shouldReturnSingleKey() { + Map capitalCountryMap = new HashMap<>(); + capitalCountryMap.put("Tokyo", "Japan"); + capitalCountryMap.put("Berlin", "Germany"); + assertEquals("Berlin", MapUtil.keys(capitalCountryMap, "Germany").findFirst().get()); + } + + @Test + public void whenUsingFunctionalWayForAllKeys_shouldReturnAllKeys() { + Map capitalCountryMap = new HashMap<>(); + capitalCountryMap.put("Tokyo", "Japan"); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + capitalCountryMap.put("Pretoria", "South Africa"); + capitalCountryMap.put("Bloemfontein", "South Africa"); + assertEquals(new HashSet(Arrays.asList( + new String[] {"Cape Town", "Pretoria", "Bloemfontein"})), + MapUtil.keys(capitalCountryMap, "South Africa").collect(Collectors.toSet())); + } + + @Test + public void whenUsingBidiMap_shouldReturnKey() { + BidiMap capitalCountryMap = new DualHashBidiMap(); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + assertEquals("Berlin", capitalCountryMap.getKey("Germany")); + } + + @Test + public void whenUsingBidiMapAddDuplicateValue_shouldRemoveOldEntry() { + BidiMap capitalCountryMap = new DualHashBidiMap(); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + capitalCountryMap.put("Pretoria", "South Africa"); + assertEquals("Pretoria", capitalCountryMap.getKey("South Africa")); + } + + @Test + public void whenUsingBiMap_shouldReturnKey() { + HashBiMap capitalCountryMap = HashBiMap.create(); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + assertEquals("Berlin", capitalCountryMap.inverse().get("Germany")); + } + + @Test(expected=IllegalArgumentException.class) + public void whenUsingBiMapAddDuplicateValue_shouldThrowException() { + HashBiMap capitalCountryMap = HashBiMap.create(); + capitalCountryMap.put("Berlin", "Germany"); + capitalCountryMap.put("Cape Town", "South Africa"); + capitalCountryMap.put("Pretoria", "South Africa"); + assertEquals("Berlin", capitalCountryMap.inverse().get("Germany")); + } + +} diff --git a/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MultiValuedMapUnitTest.java b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MultiValuedMapUnitTest.java new file mode 100644 index 0000000000..686c1cef87 --- /dev/null +++ b/core-java-modules/core-java-collections-maps/src/test/java/com/baeldung/map/MultiValuedMapUnitTest.java @@ -0,0 +1,227 @@ +package com.baeldung.map; + +import org.apache.commons.collections4.MultiMapUtils; +import org.apache.commons.collections4.MultiSet; +import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; +import org.apache.commons.collections4.multimap.HashSetValuedHashMap; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class MultiValuedMapUnitTest { + + @Test + public void givenMultiValuesMap_whenPuttingMultipleValuesUsingPutMethod_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("fruits", "apple"); + map.put("fruits", "orange"); + + assertThat((Collection) map.get("fruits")).containsExactly("apple", "orange"); + + } + + @Test + public void givenMultiValuesMap_whenPuttingMultipleValuesUsingPutAllMethod_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.putAll("vehicles", Arrays.asList("car", "bike")); + + assertThat((Collection) map.get("vehicles")).containsExactly("car", "bike"); + + } + + @Test + public void givenMultiValuesMap_whenGettingValueUsingGetMethod_thenReturningValue() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("fruits", "apple"); + + assertThat((Collection) map.get("fruits")).containsExactly("apple"); + } + + @Test + public void givenMultiValuesMap_whenUsingEntriesMethod_thenReturningMappings() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + + Collection> entries = (Collection>) map.entries(); + + for(Map.Entry entry : entries) { + assertThat(entry.getKey()).contains("fruits"); + assertTrue(entry.getValue().equals("apple") || entry.getValue().equals("orange") ); + } + } + + @Test + public void givenMultiValuesMap_whenUsingKeysMethod_thenReturningAllKeys() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + MultiSet keys = map.keys(); + + assertThat((keys)).contains("fruits", "vehicles"); + + } + + @Test + public void givenMultiValuesMap_whenUsingKeySetMethod_thenReturningAllKeys() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + Set keys = map.keySet(); + + assertThat(keys).contains("fruits", "vehicles"); + + } + + @Test + public void givenMultiValuesMap_whenUsingValuesMethod_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); + } + + @Test + public void givenMultiValuesMap_whenUsingRemoveMethod_thenReturningUpdatedMap() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); + + map.remove("fruits"); + + assertThat(((Collection) map.values())).contains("car", "bike"); + + } + + @Test + public void givenMultiValuesMap_whenUsingRemoveMappingMethod_thenReturningUpdatedMapAfterMappingRemoved() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); + + map.removeMapping("fruits", "apple"); + + assertThat(((Collection) map.values())).contains("orange", "car", "bike"); + } + + @Test + public void givenMultiValuesMap_whenUsingClearMethod_thenReturningEmptyMap() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + assertThat(((Collection) map.values())).contains("apple", "orange", "car", "bike"); + + map.clear(); + + assertTrue(map.isEmpty()); + } + + @Test + public void givenMultiValuesMap_whenUsingContainsKeyMethod_thenReturningTrue() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + assertTrue(map.containsKey("fruits")); + } + + @Test + public void givenMultiValuesMap_whenUsingContainsValueMethod_thenReturningTrue() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + assertTrue(map.containsValue("orange")); + } + + @Test + public void givenMultiValuesMap_whenUsingIsEmptyMethod_thenReturningFalse() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + assertFalse(map.isEmpty()); + } + + @Test + public void givenMultiValuesMap_whenUsingSizeMethod_thenReturningElementCount() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("vehicles", "car"); + map.put("vehicles", "bike"); + + assertEquals(4, map.size()); + } + + @Test + public void givenArrayListValuedHashMap_whenPuttingDoubleValues_thenReturningAllValues() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + map.put("fruits", "orange"); + + assertThat((Collection) map.get("fruits")).containsExactly("apple", "orange", "orange"); + } + + @Test + public void givenHashSetValuedHashMap_whenPuttingTwiceTheSame_thenReturningOneValue() { + MultiValuedMap map = new HashSetValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "apple"); + + assertThat((Collection) map.get("fruits")).containsExactly("apple"); + } + + @Test(expected = UnsupportedOperationException.class) + public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() { + MultiValuedMap map = new ArrayListValuedHashMap<>(); + map.put("fruits", "apple"); + map.put("fruits", "orange"); + MultiValuedMap immutableMap = MultiMapUtils.unmodifiableMultiValuedMap(map); + + immutableMap.put("fruits", "banana"); + + } + + +} diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index ebdb11925b..3fc978a68c 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -42,6 +42,9 @@ core-java-collections-list core-java-collections-list-2 core-java-collections-list-3 + core-java-collections-maps + core-java-collections-maps-2 + core-java-collections-maps-3 core-java-concurrency-2 From 39abe6bfd14ee2f8f7f248f3c4e7d9feb0f86b01 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Tue, 7 Apr 2020 14:53:59 +0530 Subject: [PATCH 047/194] JAVA-1188: README changes --- core-java-modules/core-java-collections-maps-2/README.md | 2 +- core-java-modules/core-java-collections-maps-3/README.md | 2 +- core-java-modules/core-java-collections-maps/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core-java-modules/core-java-collections-maps-2/README.md b/core-java-modules/core-java-collections-maps-2/README.md index da9279b191..f49ba25c8c 100644 --- a/core-java-modules/core-java-collections-maps-2/README.md +++ b/core-java-modules/core-java-collections-maps-2/README.md @@ -13,4 +13,4 @@ This module contains articles about Map data structures in Java. - [Sort a HashMap in Java](https://www.baeldung.com/java-hashmap-sort) - [Finding the Highest Value in a Java Map](https://www.baeldung.com/java-find-map-max) - [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) -- More articles: [[<-- prev]](/core-java-collections-maps) [[next -->]](/core-java-collections-maps-3) +- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps) [[next -->]](/core-java-modules/core-java-collections-maps-3) diff --git a/core-java-modules/core-java-collections-maps-3/README.md b/core-java-modules/core-java-collections-maps-3/README.md index 142aa34800..64a3b75d83 100644 --- a/core-java-modules/core-java-collections-maps-3/README.md +++ b/core-java-modules/core-java-collections-maps-3/README.md @@ -5,4 +5,4 @@ This module contains articles about Map data structures in Java. ### Relevant Articles: - [Java TreeMap vs HashMap](https://www.baeldung.com/java-treemap-vs-hashmap) - [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps) -- More articles: [[<-- prev]](/core-java-collections-maps-2) +- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-2) diff --git a/core-java-modules/core-java-collections-maps/README.md b/core-java-modules/core-java-collections-maps/README.md index 1323fb97cd..828f8992e1 100644 --- a/core-java-modules/core-java-collections-maps/README.md +++ b/core-java-modules/core-java-collections-maps/README.md @@ -13,4 +13,4 @@ This module contains articles about Map data structures in Java. - [Immutable Map Implementations in Java](https://www.baeldung.com/java-immutable-maps) - [Guide to Apache Commons MultiValuedMap](https://www.baeldung.com/apache-commons-multi-valued-map) - [The Java HashMap Under the Hood](https://www.baeldung.com/java-hashmap-advanced) -- More articles: [[next -->]](/core-java-collections-maps-2) +- More articles: [[next -->]](/core-java-modules/core-java-collections-maps-2) From 298cc81d7d16cfd9acbd9dc6ab9933f808414da7 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Tue, 7 Apr 2020 15:03:43 +0530 Subject: [PATCH 048/194] JAVA-1188: main pom changes to remove java-collections-maps --- pom.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pom.xml b/pom.xml index e21c13efc2..219c7ce599 100644 --- a/pom.xml +++ b/pom.xml @@ -453,9 +453,6 @@ java-collections-conversions java-collections-conversions-2 - java-collections-maps - java-collections-maps-2 - java-collections-maps-3 javafx From 2986e1ace50b1fe369b2e6856be3def7dc2b00c8 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 17:35:51 +0800 Subject: [PATCH 049/194] Update README.md --- persistence-modules/spring-hibernate4/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/persistence-modules/spring-hibernate4/README.md b/persistence-modules/spring-hibernate4/README.md index cfa13ca3b0..a5a72a9b7e 100644 --- a/persistence-modules/spring-hibernate4/README.md +++ b/persistence-modules/spring-hibernate4/README.md @@ -9,7 +9,6 @@ This module contains articles about Spring with Hibernate 4 - [Stored Procedures with Hibernate](https://www.baeldung.com/stored-procedures-with-hibernate-tutorial) - [Hibernate: save, persist, update, merge, saveOrUpdate](https://www.baeldung.com/hibernate-save-persist-update-merge-saveorupdate) - [Eager/Lazy Loading In Hibernate](https://www.baeldung.com/hibernate-lazy-eager-loading) -- [The DAO with Spring and Hibernate](https://www.baeldung.com/persistence-layer-with-spring-and-hibernate) - [Auditing with JPA, Hibernate, and Spring Data JPA](https://www.baeldung.com/database-auditing-jpa) ### Quick Start From 83be0892e7d536956ddc0a65607ba16e0b4b8e07 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Tue, 7 Apr 2020 15:08:09 +0530 Subject: [PATCH 050/194] JAVA-1188: main pom changes to remove java-collections-maps --- pom.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pom.xml b/pom.xml index 219c7ce599..d5e2ddd0c7 100644 --- a/pom.xml +++ b/pom.xml @@ -962,9 +962,6 @@ java-collections-conversions java-collections-conversions-2 - java-collections-maps - java-collections-maps-2 - java-collections-maps-3 javafx From 6ffe07efff4ddda7822faa2ca4bcdea1b0e3b3e0 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 17:39:12 +0800 Subject: [PATCH 051/194] Update README.md --- core-java-modules/core-java-8-2/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java-modules/core-java-8-2/README.md b/core-java-modules/core-java-8-2/README.md index 961941aac7..c1c09d2192 100644 --- a/core-java-modules/core-java-8-2/README.md +++ b/core-java-modules/core-java-8-2/README.md @@ -4,7 +4,6 @@ This module contains articles about Java 8 core features ### Relevant Articles: -- [How to Delay Code Execution in Java](https://www.baeldung.com/java-delay-code-execution) - [Run a Java Application from the Command Line](https://www.baeldung.com/java-run-jar-with-arguments) - [Java 8 Stream skip() vs limit()](https://www.baeldung.com/java-stream-skip-vs-limit) - [Guide to Java BiFunction Interface](https://www.baeldung.com/java-bifunction-interface) From 34927fcc12acb04047bd854a93157366b45896fd Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 17:44:36 +0800 Subject: [PATCH 052/194] Update README.md --- core-java-modules/core-java-collections/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core-java-modules/core-java-collections/README.md b/core-java-modules/core-java-collections/README.md index 340c2b286e..12e3c5ac17 100644 --- a/core-java-modules/core-java-collections/README.md +++ b/core-java-modules/core-java-collections/README.md @@ -3,7 +3,6 @@ This module contains articles about Java collections ### Relevant Articles: -- [Collect a Java Stream to an Immutable Collection](https://www.baeldung.com/java-stream-immutable-collection) - [Introduction to the Java ArrayDeque](https://www.baeldung.com/java-array-deque) - [An Introduction to Java.util.Hashtable Class](https://www.baeldung.com/java-hash-table) - [Thread Safe LIFO Data Structure Implementations](https://www.baeldung.com/java-lifo-thread-safe) @@ -13,4 +12,4 @@ This module contains articles about Java collections - [Defining a Char Stack in Java](https://www.baeldung.com/java-char-stack) - [Guide to the Java Queue Interface](https://www.baeldung.com/java-queue) - [An Introduction to Synchronized Java Collections](https://www.baeldung.com/java-synchronized-collections) -- [[More -->]](/core-java-modules/core-java-collections-2) \ No newline at end of file +- [[More -->]](/core-java-modules/core-java-collections-2) From 959bf74b1e1cf184df9186ea7f68f7032d64f6a2 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 17:48:34 +0800 Subject: [PATCH 053/194] Delete README.md --- apache-olingo/olingo2/README.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 apache-olingo/olingo2/README.md diff --git a/apache-olingo/olingo2/README.md b/apache-olingo/olingo2/README.md deleted file mode 100644 index 826cd0133e..0000000000 --- a/apache-olingo/olingo2/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [Intro to OData with Olingo](https://www.baeldung.com/olingo) From 9ae4555a4f031263925e7958dd76fc5277e65ec2 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 17:52:32 +0800 Subject: [PATCH 054/194] Update README.md --- algorithms-miscellaneous-3/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/algorithms-miscellaneous-3/README.md b/algorithms-miscellaneous-3/README.md index 00b785c1b2..dd5bbac162 100644 --- a/algorithms-miscellaneous-3/README.md +++ b/algorithms-miscellaneous-3/README.md @@ -13,6 +13,5 @@ This module contains articles about algorithms. Some classes of algorithms, e.g. - [Checking if a Java Graph has a Cycle](https://www.baeldung.com/java-graph-has-a-cycle) - [A Guide to the Folding Technique in Java](https://www.baeldung.com/folding-hashing-technique) - [Creating a Triangle with for Loops in Java](https://www.baeldung.com/java-print-triangle) -- [Efficient Word Frequency Calculator in Java](https://www.baeldung.com/java-word-frequency) - [The K-Means Clustering Algorithm in Java](https://www.baeldung.com/java-k-means-clustering-algorithm) - More articles: [[<-- prev]](/algorithms-miscellaneous-2) [[next -->]](/algorithms-miscellaneous-4) From 0625de19744d47721bc313ce1ef193859cc536c6 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 17:54:20 +0800 Subject: [PATCH 055/194] Update README.md --- core-java-modules/core-java-collections-2/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java-modules/core-java-collections-2/README.md b/core-java-modules/core-java-collections-2/README.md index de5daddb38..e5f6126811 100644 --- a/core-java-modules/core-java-collections-2/README.md +++ b/core-java-modules/core-java-collections-2/README.md @@ -12,4 +12,3 @@ - [Sorting in Java](https://www.baeldung.com/java-sorting) - [Getting the Size of an Iterable in Java](https://www.baeldung.com/java-iterable-size) - [Java Null-Safe Streams from Collections](https://www.baeldung.com/java-null-safe-streams-from-collections) -- [Operating on and Removing an Item from Stream](https://www.baeldung.com/java-use-remove-item-stream) From 4ccdaeb5f1f5fa718f63e0ba1a46d38e5b14bce9 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 17:56:49 +0800 Subject: [PATCH 056/194] Update README.md --- spring-core-2/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-core-2/README.md b/spring-core-2/README.md index 1fb591f693..0c0dac3dbf 100644 --- a/spring-core-2/README.md +++ b/spring-core-2/README.md @@ -7,7 +7,6 @@ This module contains articles about core Spring functionality - [Guide to Spring @Autowired](http://www.baeldung.com/spring-autowire) - [Spring Profiles](http://www.baeldung.com/spring-profiles) - [A Spring Custom Annotation for a Better DAO](http://www.baeldung.com/spring-annotation-bean-pre-processor) -- [Running Setup Data on Startup in Spring](http://www.baeldung.com/running-setup-logic-on-startup-in-spring) - [Quick Guide to Spring Bean Scopes](http://www.baeldung.com/spring-bean-scopes) - [Custom Scope in Spring](http://www.baeldung.com/spring-custom-scope) - [@Order in Spring](http://www.baeldung.com/spring-order) From 44517677a68e52717cacce6ab503249fe3d14ff6 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 17:59:28 +0800 Subject: [PATCH 057/194] Update README.md --- spring-core-2/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-core-2/README.md b/spring-core-2/README.md index 0c0dac3dbf..a144f5203c 100644 --- a/spring-core-2/README.md +++ b/spring-core-2/README.md @@ -14,6 +14,5 @@ This module contains articles about core Spring functionality - [Spring Events](https://www.baeldung.com/spring-events) - [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations) - [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class) -- [Guide to the Spring BeanFactory](https://www.baeldung.com/spring-beanfactory) - [Reading HttpServletRequest Multiple Times in Spring](https://www.baeldung.com/spring-reading-httpservletrequest-multiple-times) - More articles: [[<-- prev]](/spring-core)[[next -->]](/spring-core-3) From 694ed29f705e3e228b866625dbdfea0b11523ec3 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Tue, 7 Apr 2020 18:02:08 +0800 Subject: [PATCH 058/194] Update README.md --- spring-core-2/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-core-2/README.md b/spring-core-2/README.md index a144f5203c..947b816db8 100644 --- a/spring-core-2/README.md +++ b/spring-core-2/README.md @@ -14,5 +14,4 @@ This module contains articles about core Spring functionality - [Spring Events](https://www.baeldung.com/spring-events) - [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations) - [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class) -- [Reading HttpServletRequest Multiple Times in Spring](https://www.baeldung.com/spring-reading-httpservletrequest-multiple-times) - More articles: [[<-- prev]](/spring-core)[[next -->]](/spring-core-3) From 6640e14f8bec1c63a117a75acebc16a0e4fd14a6 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Wed, 8 Apr 2020 13:11:01 +0800 Subject: [PATCH 059/194] Update README.md --- logging-modules/log-mdc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logging-modules/log-mdc/README.md b/logging-modules/log-mdc/README.md index b676d3ba76..0d516619ef 100644 --- a/logging-modules/log-mdc/README.md +++ b/logging-modules/log-mdc/README.md @@ -1,7 +1,7 @@ ### Relevant Articles: - TBD - [Improved Java Logging with Mapped Diagnostic Context (MDC)](https://www.baeldung.com/mdc-in-log4j-2-logback) -- [Java Logging with Nested Diagnostic Context (NDC)](https:www.baeldung.com/java-logging-ndc-log4j) +- [Java Logging with Nested Diagnostic Context (NDC)](https://www.baeldung.com/java-logging-ndc-log4j) - [Drools Using Rules from Excel Files](https://www.baeldung.com/drools-excel) ### References From 15d4893d2e2742261e2661d3ffabcfca443a6851 Mon Sep 17 00:00:00 2001 From: Joao Esperancinha Date: Wed, 8 Apr 2020 08:13:28 +0200 Subject: [PATCH 060/194] [BAEL-2749] Bumps DBUnit to version 2.7.0 --- libraries-testing/pom.xml | 2 +- .../test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries-testing/pom.xml b/libraries-testing/pom.xml index c4d2786441..ad6c81a3d6 100644 --- a/libraries-testing/pom.xml +++ b/libraries-testing/pom.xml @@ -198,7 +198,7 @@ 3.6.2 2.0.0.0 1.4.200 - 2.6.0 + 2.7.0 3.14.0 1.8 1.8 diff --git a/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java b/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java index 20b0337f4d..93c7e9a456 100644 --- a/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java +++ b/libraries-testing/src/test/java/com/baeldung/dbunit/DataSourceDBUnitTest.java @@ -17,6 +17,7 @@ import org.junit.platform.commons.logging.LoggerFactory; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; @@ -33,7 +34,7 @@ public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { private static final Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class); @Override - protected javax.sql.DataSource getDataSource() { + protected DataSource getDataSource() { JdbcDataSource dataSource = new JdbcDataSource(); dataSource.setURL(JDBC_URL); dataSource.setUser("sa"); From 5fc5e76929e92bb781dcc0dc707be61ffd98078b Mon Sep 17 00:00:00 2001 From: Aitor Cuesta Date: Wed, 8 Apr 2020 11:30:52 +0200 Subject: [PATCH 061/194] BAEL-3075 - PR reviews, removing Oracle jars, adding extra explanation/configuration to Oracle configurations --- .../spring-boot-persistence-2/README.md | 3 +- .../spring-boot-persistence-2/lib/ons.jar | Bin 139977 -> 0 bytes .../spring-boot-persistence-2/pom.xml | 101 ++++++++---------- .../configuration/OracleConfiguration.java | 2 + .../configuration/OracleUCPConfiguration.java | 4 +- 5 files changed, 53 insertions(+), 57 deletions(-) delete mode 100644 persistence-modules/spring-boot-persistence-2/lib/ons.jar diff --git a/persistence-modules/spring-boot-persistence-2/README.md b/persistence-modules/spring-boot-persistence-2/README.md index a74bf7ff02..fac8b75615 100644 --- a/persistence-modules/spring-boot-persistence-2/README.md +++ b/persistence-modules/spring-boot-persistence-2/README.md @@ -1,4 +1,3 @@ ### Relevant Articles: -- [Using JDBI with Spring Boot](https://www.baeldung.com/spring-boot-jdbi) -- [Oracle Connection Pooling With Spring](https://www.baeldung.com/oracle-connection-pooling-with-spring) \ No newline at end of file +- [Using JDBI with Spring Boot](https://www.baeldung.com/spring-boot-jdbi) \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-2/lib/ons.jar b/persistence-modules/spring-boot-persistence-2/lib/ons.jar deleted file mode 100644 index 637cf11887b54ddf4d567b7251ee51a18d235af7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139977 zcmbrmW0Ymvk~W;Kw9QJ}cBO6Gww+mN+qP}nwpD3orHwbwJ@Wj4eYaoA({~(p(lNJ*eQc$Fk5|)aph4rID7J4Lk502uv3tav#%wovEhaM7C zNq&!z9+QNO`nh#F;4X97d1T#@Zo0W2zkBLO3(7yFcHkn`i2h0vTL&`Dt0}^O)wzGK z0O{lhHHP3|cbr$t7|Jm~ELdN76I(wN!IYe5;SmXmY#4*<=wN{d3@ubu`$G{tMGx~5 zt^oNxGNu=lSZ|G3|LT9CC zt!H9nWn}I6Z>C`WPg87ct*rmeJmP;l&&=A<$i!aH(Z>GYECKbOOW0WdJGS8dN@#Cu z@NZWA!yx`Ct3Ou#gV@Z<*7D!X_}lUhwr2l9{HMKn%OV%leJy+cHMstB`7c%c7ZLwM zUjKz}0UIk@8|yFO3+P!|^6ME`&=^?iIXD4mN^kC`0&!BCg zdp1zQo30Aiyiz)ewtXr7^nGW~#M5YRrP#QBdLSu$G-_u1lvq^_Hxphs6qWRTcN`N* zCB+PfV1hT(lLgd6y0FALLisZ#pOzR#)11!7tnUhK4Idt}Bv?IwMEyRtAO1 zr!3kEW`mP}0RY~?zMi}Ptt@1|Y)R}tOoB+(%-TfW$j-^g!BNu8!O_Ut$o@~^R4Qq? ztP8?-Vznm`QV!Ui1~I{B{6gi_5%12CT1(()=&j5wuoGPmsBY|Np{O%dmS=w^fAix> z2DbKfaNYOi?dSbDRVFRfvvaq9rF$`Pc|4WLxwrV+=i`m?=PkVd$ZkiJLQBlRAQ8=p zD<0l)O9Z9AAvJMr#U4e~iE6JC44!#QZoh0Vabwk~=nkRLrsD4naXlD3Qn@8tjeZ;$ zlpw*YnTOkO=wynl{Uk!k%XI3?n<7&PR=Q5-ab_!4c&SlfnKZ2ZWS!P=5ZguP3*EpS z`yEyAL7bqcvSoPaew1~TGre+}eU@s@hWJufR2S!#hQ#g72+A?&{Pd>v4aDt$J~)ad zJa83Ju>AA6wo}_}G-O2{*kVsS!!pMihxT;n`0B8G&FuuM@eOm0&G`}{VZPNd!jF`6 zSeNv}2Z0l>@+YJi5;$Fw58yz2@`5|VMH>oyciF}th`bzlWuO}`ZDZ@PbaD#im`i4` z=yz#o;u0HmiTe4$XBx7qU|Rz%zVj=xVPi3Ub>c~ZSyWIka&YOGEHE2`sQ6eVdh0!; zIY76;^bYc>ecn`-2XGc^{va7coM(L~S&pA}WeYtjPujL#^=h?o-W zz}dTuz}b6Hz&d5$L^4mAb#wXRUUH2fvN^gQc$qWsHwhc%e2Az{mlt9$PCHq=4JYtN zlARa^Ak8&DylZ4cse=?1K+@+dpfJuEGpOG@fWqE`2&7tD_L9@9NCzn%m2_S^+a*dn zYgh}LOswa`ejNEVC&6(zxuyqLQ%>7O|0tBF!OjO{s^&V?`Pd-X6oS~YhDu)J_*7SN z2@YgCD^N?+C8O*g<=63z^L5GbitCej^=%{D4cyfZ1@IheCw`m3H$n{ToU^w3#@-en z<6DGGm8tB5)t3J4*aZ`*;T2U4ZB&KxW#T+qmvNfziYd%3JqscXP@|7%HK;Ck4@Yu- z?26__D}WbXAY^7i`ix zpVA1-L#7Ffgak9XVPSdX8gwzoC^B*})0|_%Bw+2o1z$}+SM)y|0O(iblKDS60C^)z z8$HAS!39{UU0hvy zLvpiMzClhfN!|ejI`1agxQwO`;(XD@D8bBCQE4Bx&E5bW-Yul6F%G zsKvP5+17u@{!$S9Su5x`Z5bJQPiY+mYtva^1ZT_ElvL@S>hj#)jIz5MLy4HN;H>Z3 zwVtNy6q2`O&HKA1K1M{C#93OumyYbpi&$A2R+yBf2zPV$XpEcKii4MeGgbXo?MpE} zwJ_hw>7PD8<8bQB2UN1bfB68tqEFC3e3~yGFlj?h4<@_r+pvk68Ey4#p{HMn#Sesk3X=Rx0w9m!8KiBtcfto+Rxi*Q!&^HjjOI-PGEJSmKv*r#mRC4 zVT3o8LD1gZ@Wb8qhp1JMpah7<+!;6qcFcaOk2Ih6iY^g3n#-H`_LWVo)uYs2Inp714S1Zm^HlOcMFJDhf0aO6pn)@gqqxWpEY zKT(-V_r{6cFXwW)2Y4URNwrtUI>mZ6=F=i~ebaCaiY?ZgIJ=9GgH{E@sDm*Q7{*E| zOx)o*d;#yq_am!(RESl)W0$^%e+3J*$t~RFj;LGfbJ3m7Q_BY#2rd@ z7oD5y7qq%YlSD@K5Eb(7IRVeo?TFzJux4`14!Sp?6VM3~RaJ?ls!@xmy%nu@ldR)n zs0hJO?xE7?Ls9N?YKm}b^7A;CSN#N9WRqaC(a(}CS>r)6>I~FO*(13@X7vNQkls;z zflHL@&kG`sjAMW~+!yo%63-R1Q4kYH#3Xx3G4lNn{Q4&bc-1uLOZ@+d0TdiC{)|Y@F6VSv!BZ#c5%zc$-M~y|Bt(})wVX{7ueE_qs zO@FWjM|)pQKfxt%T8LK^;mSng)j9m0*gV=gYGtkO{`hz!{z)9dXINXXhdf1W#}f+0 z!P67WL9;veT`f6Yb;%A?#YwaO3j>(_3j-XB?il=u0d`n;#PTY36kuGK6wwiPs&Mwv zFlZFHMyW+oxac%C4y0xgtxes%|G)sqQlkPgX%=4?p#2L23_4$2VfGL9)xw8qKwqO& znaC zi+jR`PY=TtX%9@=K#H7V9XUyU;D1R>!Nb%~sQGfg%8=3l{aOSr;#98F*Q0yOkq zj6T*e+k55t%}kvGy>#l`FLt#RmZ3JA9<$#7dfHez4l8)(dLvx$=Vp1|>*5`(10ufkt!63KfK_IyOLpetB2Nc&_|p;esah0 zwK;x5OZ`+DW;Oa?#rdSUZ8q2aT;Cv@@fo?Y!ssIG7sBW&-{H+P9eMG6 z*vNkfhM_#xv-c*-d@^>RSiWEmDLdJwPI#-XRTLrJ`YYf`EHLU|(Lu0kTp=Neh?HA#^LP zWmT=hxp3dsmaBcC*zV|L(79HrT~x}QwpL#11zFC2;!0q;nOG}t=0lX&q^~UBdo{@R zC^)G&CLT)$A1X!l-5geZwuQY3pql~x7z5%SH2B4j5LoNo3zFtj?6%<~GOZTEhAfk) zz7vwteYaL|Eut`Z!gNSp73cgG&iOv-&hhzuQ;S>V#sj#^*B>e-H{aja-q7GX+X^G% z`PnHB?g`c@7F*dbZ0I|<2<$6R0T3pvt9yH=3SK&UNo8gQ6R>am8)wm^leP;t@}#u% z3)M8K;K3F9X6$n>yVC<6{?9f4?+<)TjK*9 zAn()6>X|~oL}b)=n9S}L3`w|AyE%npUkPeO-Mjm;Sho9IH6V@0WBl?-d4_kqiatZ^1u>WvNeGt_x5@FqjIt1hUdR26XL>I}P*ig*V=fcp@L~V3)G_FrC$53QG_WFEzNB%*B>8 zZ%bb7TZmV>k;FD1Psz`DNw6<^hpxz`)wT8?8lbhLGc|70IIt=pDW@5x4Ot>JqJUbd zGZh|DOEoo~j1uK{GQC8tu`z(b#Wj!=+z|U43F*45*OmRWTD;;)UUYlNjhm~n2%V5H z_pix1LL)0hlsHh4CkfDTV(4G6pka`%y^m1k!oi3Rkn%-Q50m1Ny%Q_DF!el_WGx>d z=VXI)+;rm#JtZ}Bp-d&zP?2;lxe`K@Xdze3JSI817G+4}!Hm@`lQ0y{k6kEOxI-lO z<;v35nwCg?q^H$|iN4h?yd|uizgAE#g;O?(J@B5MO zEx$aWqFdim139npmF0?u*7!ycCsr>0XoG}?@$`+$^w%u|7jeIat#Z&ewN)=Ie4CtY zjTS+e0t6GLn>DWQBup^~E!t!+{P?XuU@}k@m4=;xT?nmzxm<$*+YF>bzu|gs_u&14 zgXzGq*(FwU@0KrV8|>lENlt^r@EMVmVhB#H3p$nGoC|>th;oLxy9;HKx<@Zlxh}II zB8a*j&F0`YDT3d9JmJ zWDy+w_6laE?25d2<1o$yijfOT!^ZPVx0C`c>jI9UugcCMWIEa=84Zmk;}vGdL*WSV zK-j2G@T=+!#i9WF3Z;0r6PnWL7)lCSb*}J2W)K64M^9sTf)^7Z*dvWgt@;F|JI7rmk+kek4Bu0Sj7Y^T*a3%PJXD}|CJ zO(+LM)7zqHq*<6*Y|T7@+G(tKg9`?QnS&IvMkAupn53(=4kAVN|cq0;O_@Y_h z*%}3S4O(K&L19+x z8S1MrYq|kc_G&w2X;X~ID$lxFqZ}g=luVsoPT=b*4;?|uo)wDKn&#+}p**8;q%pci zqcK6RdFf0o5$(ZPZO7)^wWntl^;TN6p+;CzoxRNrN0qyjh4^Vu{zVIpqa8$><|9U^ z2k?FpiOhJ$S~@Lap(%qTI5Kg(#rhcDdm@~e%G5+maM{oo5zNRd5qcehugZj1fpP}Pyks3c{Tan6TB*9uZx ztY}HYxF$Zo)*})bNCSkgnS0@B3Vo#R@E5Cf2Rv*$PtGVk_YfPLW9wyGVvsRJTZqFPT+ub~j z1#G6zPcBlexR0z)&e>UImo%3tvcD^uHVYg&kd@JR!+A*o`E5~Mv zj@O}aH>kXnhzV-yN&{AosvMlvLSDEbLj*Jwv za@67umg-;FO@nG_!elvZW4A+(f+{>=WNJ@sz1)k&-ayp^w}Vd8DARxHakMe zJAw%B2)&f9v;nq!J-?y!0pN%wvy8s{kX?n8KBS0s+L;v{JtFRY^mo`jS!|Xp=If4r znkmln-9Nwdr}XOFSx?N*69pA3JKf<7#Oqajrb^~YSKF_&-$3(^y<$FO59oZvCV&Sl z1KI?YGB7{H&0KvRWbB>+Vel4gqlgA;d#gCnQfTFI0(t6RqqfEL0-5$iC5gnc}C=`9?)44 zD4V&WYgJuh+_|n5&uWY;fvty{oTRuY?0Q(9Sk!SI0_Ol8smbmy*92c*i+jG>d%`8$ zdhtGc|McW-A=_SF^W^RAspxssjryHy--U<29Ub?381=v-d(tInR_|7cmJZy>+hd}( z+!(e?Z`9&?mkRcG>4E;eT89m+$gv(TVP5ua55Q~{X-Z*6le4X+6QDn=ou_WJ0cMqw@YTB`&hbt7Yo0Kqw5*2|u&8%*eegK~AP<_IUz{`OemtS_=>$IiDH?u*rDLB0(RBm6+r+c8rwSfg6WQRLJPJ@^D zg6g7;_A7L!xZNw&DbB@$XXJ1Jm`1OVHt#eee*I_Iw@zqc zaM%KRvSv45;1g)-6Dom9vCjx5E>m`fcv;9z#hWR}m8pzQd!i6M91;gPAbQa1TILG+ zBVv)&h9YW7BtAWdA;KLHtFwm&)98BU4lpOQL?LRB+x5p0v7B}kW=)CRt(n1Sf7F-I zw3I9fThr{S^r!fkTx;>M=#-5Vo!YOy83?hQ)~&?cjI+F}xZ?Y>Ph9?7z7zA<2B}A$ zD1p$Pd!qj99`Tu`XqXNV0O0r6;Qznv5rte0jBFjvY^?v>EEdXfO91o1d&NhGXN7)U z-&s)oFt2)8@TC+(u+;_UZKe)1Ti0Pcu&!;?AW%O5d=l7P#Hj|xsErS~|M+b4YHtH% z=nsovtTQ`W93!ZwHi#23nlT#PUF=8vNDdfUIi7&HFeXqNqqu2S=K1a_P?(5?&=$Po z?~2Sv;D{}mslH^g?xwr*|V zQA*$RaxCp21$|!gAHTV()~<+zR>Q(O%kd@F50?aBsw9ltZ|E8iXol9iZ1@0jqj5V$ zdG|KC)%k;|bXLHVK zueY9nE4r8l*o63kOBs;yNMPXyfidTJ@{3h9MUnK^o=wfdWdgY9ZT~Ke|IQ!^!B=FGh>5J71?s{~>aPHB z#W$FG=X|Fp{GYQ^ACI1aYWlf`n1uO5Dn>J`!1EVh_(h}ON-g5)067I%qg*JcAtcKy{Jf);C!K)-7L#5e!||K$|KABP6` zZ4BM`Ep7f)vyW7Ra@9C+^Y%Fr6^V1>DbVKeC$-QH|JE?(4Jt`aF+9x zhkQR$jk8J(4&Gn(d8hg9!o9O@!()%xGf08hXXH9Du>I`{4&U|46`t}MCiOjkB8%>N z5+2A^5_LOnHD2h6rAr~8_(}^S3-LdRXkN5XzAF_4cxYcL@(;?o`-uODt zsR7<#_*f_e_V8b%3~%8ZK3fA&HxhQ*&^wwP$bB-`)g<1iJ>7vdki5zL$wp6sG44V^ zI%78~46iP!@4?WYX1m=1XA%r=>dx9IxS!PHpRqeW2OrZyvCD=JSUb1t03Xu>zmfSb zN_+h|*DrEi<@p*Zk!{3@MHp%gjXkL7%{?Hnkg2>Z(z%%|Ng3;kjUQP^&sVvp&$rs+ zJ>pB#=n+M@m4QF#@-7~psZp}GaOp7-+=gRd{TRDkgho5BSZNRA| z@KZLGt~6!LCLJjfb2TByITTJ-e)L%vJx$tACO$A|W7Y<9>=9xF+8#yLzSkbkN^;Fo zadJUJHmVvkNfphy4O@lJZuA6yG`TWlt>*lyEZ?ruwG@X5Bgwoj*yQHeuqpO1c!#)5 za47=Q551^$)LgnOid{v*lT&5L=JOz6u1OxK#OE|CHo(weaqFzoZcy@6I~YNiVRpH* zs2*l_EV1`w(IL5NX_GH0NxYq7oh=A|gCe?ApyB zbF!+X&G5o}v}={R(z8{y!b8or*FW$%|LLYn`mLlkJfv^XNv+Fag&IsR_~)Tiq%laK zAFUe~LDD_(`Ma|pC1)(TuE{d65UqB~;!j_ZqbVT4it!u#MK(&R>h`WqZ+a}(m*=td z>=jBs!#RC1Y7>GaZ1bXs>;0IK7FyzEL>8^N?51D?L{Z_xUpyLQchmH$48<9tG()_M z2>HtcXO0oe>iq_ibm2l1e$J>y2W4Hn^9PPhI(Ih0qdiJ5&T&O)P@{WlG1b{w%?+N;(pjS z1%yCY#9A1duOLh04n+!^ss0A>s2npl*`?YP;!sQW{E|w&+}4dYuY1E;XXc7WPA8$c zy)`S>Ex^F%{?nVwG(3x9s+(0Fq3#%-G~#!Z1f;fhid1m?Kq?LYb;o*^VfTKOYLN$1 zY)nRHOU43a%zmY}7v&5~jID*NsfIZdw{ACOR!U_iN4OS|BGujQ=0sf}wWv`+&{!cW zm1F*JADZn#pYmHQ|D;9|B2?ya-IYfMz1>n@rfd9QZy)q{viz8V9vrx=kgvNDIjuEa zV(;*n33)dI^@e|Ut>O<*YLq@0)XSmSK!$d0<5GeySyb9RixgcL%7m|)AQe0>oYZWJ zU$=Fsz7a)6vO{N-U>|N6F-uXfaG-{=d7!9^cm)f5ywQcNr(pn(I;ZG1vbj#}721;o zltIg)JaOJUn%zd<@HK=)Vp&aK^)3$-DgCIhVORcbCq?}gc#)B^^^W#z4Zo6lnRpPf zc`0~XgdBrN(8o&7A#bpu%xC1o&wby(MDA@|cB&9Z-<5g0{dxT1?-ld--*Apz3!l>F0im$@FeRZEN!$o?r+76_4n5v%A7K`A>KL@+ zbaCI=gJvV;07c0RDz4r*OZBru>@vN>esg1gIU-%yOIK~zZP(P&c&iAX*A-c$%(n|ekl09$o?|Y zQJifZdcivD$XReOs9!^DA+Bv zl4slIg3xHbl??OXf^GRct*cC-2mC?Zi~Pb%Y7Ckcws003{V4UpdyJ2<{@Xjh!k;u@ zCGr`ZerV$(A|56Wj=`2J=f>@^SUJSUBqHQEK+Kx2HTou5;XA4zmRUe7DFfYW^EU?5 z!5|gLt+b%DU(;WDX3by^YfIh;{@ni6Be zn{eJ25dPVDy)!mXa{~9aLG0Vfh*a~5;-QID(?pw1gn%;1tm%$2pF3uE%S2ks%szGz zq%3e`h#G_`AGN3F2vaF%9t{bSLnwPWKU*wuA zm|-AT=&G?Zc=+Zwq_aP%Fd$t?l$wG-)ZMv_n6kWnN~XYZ<+;xxIb{ z-t*mX52BGi>xXfV5w0l)e-~QLWA`}Tb7`GLM5J=!66JpadYC6qS#qNZx|1E_)Vu{1 zyC=c^l^QrL8%^CHNX{eHrr}zSikBy?ajc0U?wL{#K&&D1&NGs%Z;a*pl_^bYSse(L z+{mN;&=WF|Gl5q`@vU!>PkkDJ<|b(Pg{r{F1C#|fDVqXxbdzAoKd0ET(;m($by zj7lmuJyOc*jMM*$X^0USrsSo>vrR9US3EOw8jX(dNrai{f1RpQ=GoBVgDr)S&q*;v zl4%q6dq4ISv4U*c>|NQw^DrueJ{G3kn#AOnT~$|aj0cd!H8sf!soD1LnI;)Mn6B{} zSIp#H4CB_{wJ~oot!E<8{dkPf*#;{g0f5h3{+B{)d&E}5<)!l6VJGzDyW0I!uBz+$ zjPXy|v&J`YKgc6F@6K6RzbiaBSjo|ndnGUmXdKw5m@tbsXYdIs%?lP@A&Es+yarcq z_rzgz-5bg5gJvK3F%jWp`g5Y(pFq~e#xOSumCNkpRSlUN*lyxnMVDgmxd=>d$fgN9 z=;SxMLt3cAkgFr)2MJLI@0+_LTrrG(_+5WW?7mP?_Mep$nKrWZ=P~=Ea*SFse|JCw zE`<(uDKsMyJ?u; zmC>tY8yy6F(12l25iW?%VhD6XT74-;Q5d`{MMN%@S1hATDz#rIfy}6;m@O!)QKp_$ zsGu%id8yF1zzE4xB`$v|E{Q^uV%jfm)Muwg27YuVjV+VD6tmnILoQSIDqGB^-hc+~ z)=*v=nJA@@23MLnqGb=VPgSw|h$2M97mj+iO_c<%A2AEk9 zd@r;g#ovoOsJR~42$3t_Q9|phJ{4^ZjnNEnSilrqRBtGks8MVDrS8PuR7P1NP-|K0 zd@iqopIbF3rFdR*I`nNpIimEe4naU@GwX+OHZh&}G|zCV$TUy2-tBI`V!O!ldwS}t zd;t3hczgW8ShZIH&i>Ns%m!vI^5n+Y1LF<}7lp=O=DF{mm5lbm_Q_1_W zZ1AmSF=;rT45~ja8ZaEramW-N4@-{ADL?f~lBgT3g_jE}#+>F&`7%tPaaBN&OvA); zgAU80m77<=w9)xp#c<0o91mJGP8z%H65SaMOjPrJ2S01+sRG?Xap|>5$@N9r6XKDc zaydiuJNg1`BDe=@*Zz%LT5=(KhcISvg<4y>W69in+ zB#4sPiG0EDeraneEEB;M^fb?f^8;y)E43CL!^f0KlgJ%cX*ke046;%pFNeOsJZ znDd2n1{6C_6bC&5e_)nudBPz^IWbhJG>r|a8&h$}pyo@gt@5qhlY8oTjKr9etRtp7 z9KXlhJZ^4y_^tXwr{C=~vSZ2>Mf!M2+!)Tb={XR#ANG|Ql2z8y}bcV^3kc7&x`%*oC$-R zwY}-vUd*OY>2}#YWn^H4rWkoSDzL?Vb#V~_C)CA?Xov7U!W3tt^#gag!Y12$1eGG? zSTk)d52`1wL2!3*xgGNH+ahrl>=RnN#a(EQ53XvmZ&xm>(_1OZAjjYu(O@qfTU$JY zo-Q`ow4N=^(|E9V52-sU?yo>Qz@1)tK2OWolUEc`zE{#wy;pE-L4EPq;eDH(a0HJ0 z!D1{iD`}J&OSxC~yno9c2vIhl4}K+5e7=r>VgF}3>0g^?AkoOYR`CPRHmtTlZ#60y3H0f~5jFnppg-s4qm^%O*%6X$KdGn$KgPE`uM1 z6jvQYT)K+oIKam-rh_UG9n+(T^J5B=NRe1--#4N?dkc1cuN#mZv=TCf`-aH>a-eAI zjQmE8((&VExc6ld{7Ho3Nr7So9rRNg)JIuCC+lzOe>Zw(iva-u5c%p%`ES&(U}W+~ z+sU8m4^$F!KoUXzP!AtY8mcqufv=|pbTia23|^t{{fR^zCq|&}4-7$Q7Bh?+t;>}6 zD@Fmf^+;H$2`d>phhpfUfFcnq5&PDsu49>d>5!hi<;dyrwd=97@PPO8`G6ImIxn@y z+cTvH5Sa-XDI|~X2PqV070FC73*PmO9Z+`8z!I}IkCZ-wM2Du#E?AP=vt<7y$Xv_d z_|f?%s7CYZ_=4<`EW!-cFzpJAj&4hh`4+2#)V8y|Cj&K|Y@J2b2`jfm&v9!O`2u(S zu4-%B`pD#BIb1c{Qrp4Hd_Bklrm|G+2W^GnVw*11A%_r_9Nn;^MQhyeRqM!Vtu{*4 zs-GiJ12|`02jF*;D^(ZMkmuv)Ad$3?12l`}g6xVlS{Avj+D#o6#;dV>rzrDkOx)>@ zy?PTmwOBykoaf2uFcC?oeP1k+bY%1LQtjeOW_`y@Y>c_6@_T!HFPB?*;VT{c)(-ZFT~vxB6OQgIiwIBI4WdwL5p`}UtX=YZzQ`f?Mg1A4*jvDi}%wL z8}r;$mg0tF1e73BnmdEGDw8c@e0(i7oXeMheHF3timVOWH!|lZwE55y zmj__0(WFUPNmqiIP1Y0BkqY@pew1$AQ7m;#IxuhSFb>K&W$-7V;YLeiT&5`*(Q|0` zrSxPyYzj>?;+2*6qtDwR4>N7d%JmmS?Xl(V5lNe>&gvN`4P#=P|BP~K;W%xP$j8za z$1zFOgJj2fL_eur{Mn5(OVMNNpygy} z$;jPBmBXp^W-soXDQ-1rNu>(sS?b?IuVUSnZTLevuEIlV-mGL9n=6GZm5Kzv1)0a;wy&AVlx+C?>oY~#RyABq}@_S zE&&UET)ccA;Ne(&3&mDFY_RXtMQDbzx}b(S2x zhOBhDhS~VFz6Exs!0w#;2n0rL=%rW$ee@jM;=R+dGZ2vJv3`a>lOjfwBE(Yh!ZW^W zK#a{M|K1&%p7AjUJ&g}mh?7-;1LnQ-h;AKF)}_`3I7)ibMHO0wjtungiR*@O=XsT@V3jaGt9 zI~wZUgk`_!Bk(v7C7Tf?_q^%?EQOH$&a#scc%R_@ngtFBL+_IK3S|9X7O+e}yqAnZ6&$8HqBnvCV&ZVK}ai^Hx*P4c0idg8uF<-*C z8CMNH;j z&TD03UC(C(E3iDeG7#FPnAFZlJw>NP;%+kYNx<pQX{aCtrFTv0TWN$%j%X z;+vL3UW_J;QC!S?PdoCGx3Za&MfRqlZb*n~CPxaQ^^kM3`%dx-q80=aPwd249!KTfwh)$CCU-rXQZMefXP|KfcWqV6$fXrANMdaQmf%wU_sWPfa@XY5IfRI$axx zLX(Hpp4PG)QB;o1+qVo?+LU&2?-wL}5LF*2MMB0WiY@$vMbzJVBcd=* zp)HzaPeyiHqnwaUj6ub4$cZrG!p+h1lFmF9&ZSGaitkE%%ry)U8#sAAh7a=PZi^ae z>sTJK?qVF>z2>~NnZAt_2gslefG5Nvh@h6|Od(svp^2pXc?s=9&Y^{&U&ciSwleKF zsHX3@AVAn4mB&zS!*}{oK@vcLK8~C&)9uTF-!{P3`Q-tI^86@O3{MWpq$O9e)iE9R zhrflVz>V!xwik^LQFsM>CMp+AmZgP<1D1mI7rY}CnoHOk4doK*>j2>VWYuCou9enU z`?(@zxMbw-Oz^h!wh#9?tFiJ0765?ozqca=Cw&J4do%riwMqbts2R!s4YK;ukxd_X_J%cD)MuJAEf+jQPP!`r9m~M!}sstrZMX;y1Dn&N#Z*e zT}we*EeVQB$7vd8nvt^=&%#j#4y(52(&Aj-v7F*q6RmLKBGn|NoAsffpl0*dMbk>X z?-X~Qao&V+wsVm1V=CoaKh{S+$ z;h-8?t>i*3%TLt*H3NiHPcf^&?&ulaNb#~~v>mTaraM=`DGus;nY5$Ou8P+9<2M8n z;;|XDLmd~+sm3Rtkj(X#(&l3`WcAeelIPC0+0UmZA}W{)FTWd1_aWGAtER~)9R z244ZNEc&a8p5#w|st@7Wqh!ODLI`Zs2U-hII6D|Ppo@3$>$}V**26J;+5}&db~j!} z=Na*Zjqukq!b;w8YQhHa>Qa9!qLp6gGFevYe&}(UT7M68wM_NMYW+QI(D)5jp?2nd zHwJXa3vnSnB^Lv)By;kzMs|r*>&+eb`dR^<$#QfR5$etZ^;FKmJfu??uHiSzIjnUS znA&y2(b53EO3zV09hk5ia}lYFyj9aW{#B!OHCJ3()fV_O>W+|P=nl&rl#VjCYKWdb z(BtMBXtUjUom}YFDymf)PWFWK2UH`N7-hlID%~o^JFbsXPOssXhHXM??KIiv=|C0?G6j=trjulktRJmqSjz7sJaGBZ}x2 ztVj2pM}7vd56{xaiA(3+zB(R)Q+dT)GDqo7>1p97PCUN_d;|X7$L}5OvIh;eHViNi zO(HQ|e(VfWwGe6@zA;6VmM+F55?bz<$DV25UZgliFIAebmnKh6%2X)NawovCKFhotl7w>j`KdIg(#B1Yb+)5?UBmUdD*1B#3f%pN6mj=iMmp>U?a zKBe|JpDt98#aKC6eOsDBGrmS#lsf8rgb z2tLR@y00Tcrp%3~7YLdyEXOEeeo%Hh5c(VoNijbZxHF*Oe&r63S7l6R@ASXkesJjk zIFFzt@C%R7>};v=FhxO_ouo-w;0D!fc%1QDdV1}Cpi%^~=YnU}Mmb%{LA7lm{uqhg za!}zwA{6lr`nHClb9UQkw2p-O*{M%liQvtM$|vs^x&flF%4kOd4O1%G{Z~f35Q~z9 zzxtWQzm9|aJ??%n^7Sf*uNOTS3fNd%8yWmFtC6S@?t!g@^0_&BIc3N|q&NQ!B1YOm z{noTi49ijsiriA6KIR)sVQr;4X?wik+GeVeG0Uj3kQ|?20h#<3foz2hb)Pd|X_$>? z_r1@K!gS`Uv$#(Eih^R(X zy)m|FKGUM25+kDM@w(zQEzp%l&udzUmJm@OD*V!Ybpa?4AbOEkf#ni?i>=F7Ln(rst?dzRj~l%ODg}5 zuXBE{EZnwq#Wr_Xv29mu+qUggY}>YN+qP|1oC-SUIrrY~bGlFeu=gLZ)_Ugm%`x9G z<|FYy@peK&Ns}>6^77=+YNaLiaefO=eB&gTVcg!E1P{|fgMCa+1ItRSRJGaIxSM{d z;y|w%f0de8YPHQqTV+Mbuxf%wb0J~;k`;~M-60&A#PDf!`O*r4#I2vsE6zT`#;4MRg7AS`xSTf1(ts6NG;A&OUhG96!sSNjE?6XTA1lw zpr?sAlu;Ty(A`0{2^%3{yyTpLo9>?g&0Tb{0Pb33=Eqt|gf87 zX4DtO79LB0r)ji1T(F&?XYvkc+C37moso$|Q?Q!cUl7u6zSd>6GK0oo!ky*2EbqVi z5MFONs}YG&-yu~|-!b_J7O+6n2eF}j!gDBIIA->~&2UIP3b&S>WxH%IRiQf+FFc>Q zyD={b{(J{?u-cD(o7bfpltY3G-9DR>@8)#(zlU~&-nIMqZe=MagS!Is9j83~OPxnA zG?<2J%tM^Nss5^vUTpB+gfp9?sb(>+nw=`oMY4>SXDq-3ME*CQ2zMDr?FVr!iRrCS5N7LIdS+^IOQLDbL;Iq;M^vJ^Y zXpe(Pox{#HtMD^cC0*!iHo5kxre-crA0wQ7lb%&(!JZ{&SZ4qxX0ajHo7)=IFF8!N0)x0#FhP&KO#UO9XAp>7Ll0D1JaX3*7y4 ztxY-&J!GOjL#HmsEk0-go0G?*z1~2xP(KuTEVulzgIyL_mT!4$B+oWTI>Ug)y8n(~ zsa(SUN$*j0q8ae((OUyVRrWCakR-#-(1q6%^|fi|Ysi$yU=ddK8Raj6@QTEv_v~HY zctr`odnSNY|;YeW#LIaXRM@hXFt zwE#J>t&Cq+iq~jqjj#%i70jrOw9y9(5Ws8b-x`H^cGI!?Lqp@_Yt21EPM1FQcN)jHxEdQLCP0&@~!!JCjEX`eQ9_Uzv~eVn@{Y>s_5 zD`ip&lrWf|CTx~LK(CFuhjv@R!S_6-%{OM&8jJ?so?^q8(-hhl#D+@F=@zU>?f*+g^TLvIY+q}L%RoLg@#v1 z&K=0Ghcg@$!a%_7PqD`>e8hl*kv&MU2bhGBB_QFBTIg?3L(d-Y?!RXz)9QukkI-2} zC%@S${G#8MJirt-1%~RMb4yDh+_rAT)yHdbaH7*gRy5M5noiJ$3co=;mf$kEr4doKXAtGfEQs@)v)FmF_NCn6=2K@Nw zL&iavW01z_`~XSm^Y5#CLpBy9dO=JAzc(ql)vqCDwmspt`Qw8idde3AGRPseqj~BX z-))vs+W5zfl<)x5Th~{p#~WdvaP>FPzaGPdgh<`Qus?oieyc##|Mz|3zmH)DV|^#% zfA526sBx}I#Scx%Y-R-& zTHsscG%J@i4XtZ5C0kfhp|kRr=RYc2YE~^ZD_MCrHV?g7EJ>hwUQZIQZCT}itlvzq zdCs(*WO{BtYq=dBX1Ri-%1%K$ZN|>zV5433N<&L|X%0_8cL#Vgc2oJ-#@Say-i(Eg zzjQ}#fWqB;{JQ**8@^(EnrIaqjxoZCwU-l75Xp)30fZQBQXJGq;!m_n4sS7D%iDoI zkGIMWH!=DU9{2zd$lVYT!e#~-eJBr*!1x9V{BKWq-+_BjcMXBR&-5B%?mRs_ADYpe z$&)2TWS@kXoqbnm^u5yFcb)zP=;Zy>7jB}~ub&4o$k}MOj?gNcTr*T|K)>T}O`+%{ zUMl>ZTg8WW25;=aSlq-bKdbd}om@0$Zrpg*Hr2T!#1`^3R+kX9)P)3}k3YF!SK$W`;X1+td_(J4wu&=-@bc;T2y zCd@kOC{T0e-s{(5GFo%i%m(lWKHDhT=Y086?(J_JKia)rYp2( zhzqucD;7b7`~6hlQdVvAAYmW_JpW=XWefB29ci6lIIhuZWu>*+3JPO;RW0C%helY# zdXdqfPN>DWu_*q~`GTPah+HHi?wf0N`UV)N;X&vvnbfrU$Ak2@PYUU5_ z7F3%@C)+q4xrDxsVLFmv%Tnm`Fik-OhP6q>+VTX9D4xDVxgqv>hJ}?EVQ~lg;c7G$ z4)g&y(>!Uto`;DLqj;*iGn%n{lXaj!sU$*HkNizDlQc0aZ8Etoq3|N@k=?6<^SZFB zzcikckrp97P+;1?JeOjayGtt%kMcg#%=E1kaPp=RsR6;kWUZKMTAgFif)b{gDv|(p zjhJ$o@36zM(Ap6)TDcSSD~I|%h)Ov-G2-QVY0)zxDg3n=25V8^qd`Ao2`V#Bd0j{o zfv9=MfJ%vpGnR&^TME*W!UBIp$7`(ZNv!@_Q3|Dc5h2zHRx`jpx^tO1QyoTwfd>mg zliHj0Vtvp?ea$9klAzwn29{xpk%cU)vD7?hV}O7QV&Ac8K3suj)uizvER-cf z*l}y9$%W~d`cW-of=#u8jm8i@Vu@zk(vVscGtA7xlgktc-*}}GJsR3zn&t^SPv(U< zG2KNVK`0Zf>B-`{PD99vvMSHsS$eA-7aNPUdO{Cs1Pq2OO^HbkXGp+qN)H^KQ;E^z zq1vWo3BV)OYDVs~A?XPl9oW>RWVoO@iNWcbAwOKH=hlGKVgZgA7$oRbX`jB3Il7+D z`s{*Dg;VAqS!)q`^)WpQF0Kk|KHO9y%8r}g9$IlsoQsQqG!tsGR#vZfny5t392xH3 z&&y>(wcZ9@?#{DB572!l|H?E(VlDI%hOJLfS$zCY^PB&9a%=ie2hNDJ^eKDV-puXwEq$cg9R9 zZ%#TzD1}#~dB^jImqtACWks114FWWb%3%JNsVil`Mpd3G%Sitvf7rMZWeG<Sv`h1&47+a)Jn+^t=*g>#i)oMVLwbm}O{-!AzExVc}5Y&(b|48|G~N z?xp;3UOei$F%edVI7Km22WARH!=xPkJG-qb;kLLLj&-4=;VYd{jQIBiRSO{~(yh~o zA5HgVBSacPJ-B*(uhi<;1kk6{9da~V!@i(PM!S8MQgi?odtU)vuiftRiJiyzB>$O$u(sKI|=WMgfObesFYAGGBF78{&h z0ab$-wR|#v_LQk${XDf@+09>)-~jDOay<1dM1T^q*)j25UoyqcIHX+}2uI+GaZQAxX3qxQM~bWt?+@^M-V-=x z+#H*#iq)B@bPZ)&z~P}PgPWFFT%E(-#8NQbx}zgae~fmJm{8`L7eC!~?3B8xn^My) zxUDPo>&{-2pK^)s&G(DIc}Ok$aSfytlI26J-C%_m%$J=D|wW@XIDNSvY^q>xd;KUvsU)L|19EjH#!PTO36(_7(U8qH*69tiaIF!&`8E&~fjZ zkF3H6qca}v=@wPK|Kv9I9$lM>g~)oJ3UD*giKeent_$|hI`wz+6tVXs@~ak!j{PM$ zo^bo-m@s-TDLy*Ino9S}81Vs04i^*#lNy8C@ZAuQCZyl?g$neFYlf*TkG0f_R2sfe zIvn$hg&@kpfKs`)IGy-5VWCt8*Uv%%YiSXww75v#oOUU;=cIqcrxV!lOhT%tLXO{a zR%j(RrF!7e2?Q@U!#>kyujJX9n|8-$#JKaola1B@O*oQBFmzy_Ct7a$0!KUv0V)~S zw`B7IU-Bchdk&oY)8Gp>_*~n}|BE@eyo*-tkPb<&8fN-o#-J9z=mS#aq-}JqOl(Xz zxrorXd>X+mfqW-|#GnV?krFpN}Z4%~O7Nm+Dzx>sK3wvgaNQxu{$df{qDq zq&tnj?;CxO1{67v%cg&T8s_L@%IY^ObVQHdwCT6-xAx^{^5p_*7Bg|6>{ zjXLtg2bI-+8T_4or4EyYb=7x4*S%M|HuP8dd=B)$}n#5OHRRBY!@|Ma z;f&LDAmq6LsZ!#J_Cm??1d9t$lX9Q*xAb4a+yMCc}iDBH0rOZh>v2;nX&003*Z08C- zkZ#G^E+jblvv{UNd-isaohf_7Y(E^jac67E#)1WZ9fj2(;27lHIm`ACFA$W-Ob6XE8SPV+_7WKF5P9A3Jw8QdU=7kVE~vE@CEuQ{d;9&ofw32=vd--`7}F zfuVJVz@LBc?_<`FU)-yCVak-ZPqTM-82&0eXfp>BFX-Mps@!>GA&F< zF&2(TS70ZPay6&WsU367Po+1X>FS+M1Sb_BU>bmxkYaj_7t^3)J(k?x_XRIpB*SHHC1dFklFq$oAn6uE5oi8hSt<1A6UR zt7!J>i-B9cycK8_`Az%5QQP*JwFI@8j5Cmlvto0ZAM{g#vrdyrz`$CVH-~ZIT;=8M zWCy(EPWR04*y`rBghSJdimgXv>A2uJNSU}7Z^ z-_o$Kv>q%>S{FvT$71pBag?6Wg4ob?T`1YhP{}@)n?7U(TB;=sts`1{dc}>xI@?<7 z;U-pH%)(%HiNssz&7p7hpxz=vgUt#)asxJhgM6Cx6!R-ma46KWfWtV zXir6T0nJ$F9-wWpznMoRz_}rVI4vInD4+E34`DW9_EZ8B{CLLtqj~%ce=DvzShW|M zlejPla02#GIHAzxCcD7#BN(3G>)hRaLZ%IGkWSPvzk;u0t-_FhV;-jfC4%`$ZKH4=kTyi^L?VgBu^UxhlfNC9Sa_ z9Wm8uFQt&6W|yA-JI!i3tk*FeakNJ>Q-d?0iAbxi0Z_7-HEu zAEN5dfAj6SwQt+Nf73a6-@pGOb^0Huso?(>=l{(t9wav*G4Rctq8K6@T3K3lDE9>+ znDrK+vGMam+E8xEF62c^nHa@Oq z>M;q?4WbL$Q8rc1V7~o*rRg~-+xN(hwxoLWa-!G2Wnw~sz0$II8 zuYhWqf6U3%-5CwfOGv9f^l<5>9@M6ZG7+O~LT6R%EC*$9aWr(#6S8nhGLg9cP>IA` zowt5dC9h;k@iE=y8aNw!cONIhTQa zCWi2BPR_XRMB>k0&u|zUljoZsSs~9j106wmfCaK)kV@XBqwL+FSBkcxg0H@L z9NjZWf4DL!;vqB4Ehyz^t?5chwOP(YE{hZ5nO?+()!9cc{G(mpe#sfD+$8Oc*3_@T zinI84j6Q>Bs-Z4g8(eVhu?qWu*_hLd#R9FPtu~#e5rC>K*v9%ao8sEqP_2}-uLAWU z*IWbbngK^7^ZE~Qlm5a9>wrUZV_DC#vZQPIdHPM7j5CEREUIV=NYIzB+|&+qlGj8@ z)wb0lrVft!4g>M%5#O5V%4V_Y?MQLy488Cav@*1aokAZbI_h99x!RyJfDLtXkOt6# zwh5GH6g^C4H;hJoKr6Wa^ThN>+UA9^^fe*C4^u#W?o@7w1v8!};C7ZJ{mPwtX=a+< zz)kDf-O~Wm0fckKc5vixs=3R9M-~@al}MR9SUpc4;aSfuFp6L&iBT432bPr8agRh` zP3UD69PKPo)O_Spj*t&i_Xbsrg=-i1_nDN&(BGk7A!`DC>1MHf-y#mLT=PgdOQEz1QHU;zev(R~&%uNd z9+##fKS~u2`+)rG_x(q`;CAvmo-pd0O#b;F5B7h2-~Sv?7O6tHDXlnv#xSQpGkYKl zSRu2Tfda=65Bf$LQ&Rv_2hzlXCZp1W8}NxBnCmeUnTY(v8Ck<&yN++Qjz=$v-lA49 zSh2Pm0S=mBHQywaerC2$shmE({<|+{@F#~2hN%E(!KB-EyW=_AafaiW`itj=%GT>s z_=h#}^PY{@Tu92DC+|CNx6<@kiuVhMm$2w>v;7##+mRQPtoO3$&&l2#?3Z!`^iKhd zp5p(kMHO_B~;?s<}WrWxcL<7GT{WHx~yG z;67@89`B>QmhG>$aPL_NU%tN=NBETWSU%fuzWjf)+}ZNJbA1ZBe=YR>PJ6LM`BL;- zxij2y>FfQX{K)sq!E_r4!M=NhZrnr0_lHKJU?^M+ncANdP2=t4Z4B+xHb_^HVGEr} zgw9b@FyF15u8>mKlW3}^W-b~|6fUM_H4dYYlvY=vZBh`0G2)~>`Pz^_AjUl+kH|qv*-^a!>me=|2O+Ntc)~{%RbT59;B+pn;`*L{YrF*bG8nu zsI@YaKN1%w`ehb8N5YsLb-AegkpBhDBJ1%>xK`4DIG2-EZ?+Q&qqMobDm#{p3k*6K zw6qFL28gsO(%N@S7Ykvg6Dg>+9}ZDS!kwK{<^2~SiG^${Z7P`%i%`rU=wndxahBp$ zb>?BTkw;Q=nfL~C60E4dlkbF*OMkRf+viNl-73dic6MXJK_A!i?HU&kz!e#)oqOeZ zxpCfQHP49JN20d=Wt%zc-I%sVPu*U`VU)Seqd*+3g?Oh`#5IkZWKX1TAICsOdrrC?mP}7A&VxgNTqtG~Q6uZ0*WT#lF(sW~i85X;oR%feDrYWI! z0_}j+6eL!)Tu+g@)WvAA8xk&ek?(Y z+B`uPdbHkTJgqxSi~?vE*aTe-ytHt_9u%2mp~P9U9qNeEYhVy$Xsu-poRsrDy7KSw z{w}u;63sgo=>WyKLg~OV1*#7SfwHL(P-{=-1Y{pqZ~tGWF&v+2i#f-)7krtW1bePT z2Z*-F$yN!PaA$Q!9S`+`G;0Jc>JA;~EBSWqT6l&OWf&h;!&_@yY z+7`2>!>am~e$(5+pLSIkz9fH{i6bHigt8HuhYp@7w3`lP)@DLSwW+-&;Ya!Tx6mr& z4yHkH6%?dYk_I$+XIYF@t_x z$&L2F+D;71LEwM}ZL+!7d|1%8uX6_HL3O<>O!y2&WY*3@qkU?V*O!&yoSVzGUl#~P znCy|r2;Zu1YNHexKB!C3IKL)oIV-nzkZ0PgiC-iOKO@)c&|d2QWkc6rG|dg^>ON`5 zdY^n;ck)m)+?s_s>Gic)RMpL;p1C)3(=D|>zpWHfZGRR)8t=k9n8ru9FYIZRfISbT z?MiYz{f@n_)c@f@5hYF1pzX?z?sOv*JY7e|$>f&ZGpRXb-RIUczpp(_@tEbKL5~8> z*+Jz}Cw-rGN~>xWSgIt`_aWmXH6yt4Xr8d5%8V;uz<#7ldsQRJ z^2esQK5D&)8N8f9%euya)pa#nYX=QsjNhX?HYUN6hP zZ|UKcIx0KG=N%_ybjum&=={ZLxs6G}C;_@>=@#M|7O>ab+gzJm@#cw&ogRY3q*t*h zorbZ3&{*BYmdFVyX?u0Noy@;5ip*ToyVOE$Cl@hY=~3iKX$@adXu5%Z<~j- zL;9iY;01B@LfgFSnMypOaBeHg5lwVGz8Vf1?R^E2x z&O5Ege@|VWvnLT&(Hai^gD-a!KOdRTAxW+Jw7k)54xE$b%A{S&Jn5v?t|z1Yfu{nA{XvmN2)r*sGhQY;zK0y89lai`Myt$ce)0GsHChc&taHsmHvkN7b%} z)htBsFyeR`bzUW-viqg7U;2WS0`AjU*)LcR9wYW6W?X}tlx>%3K5{3{*-b@5TNIvQ zU<0uHyxX<-fXVd1j<@TDP;uw&7Hj#}j?4%C#?)o;Kwsk#MoJn+b{FGL(grbm0(_6d z%U1yu|8P~dI&m|Ef~e^}Wvfu7I%KST%X^g^DoCUNQ2feKp5;}VSA9b^eSo1UHs<1}kA zk9Uf%=g)l6y~dl|V98XtYzu6n%lCFHnSzL#Y4{oFsex+G_B0kw3kjqeUHPt)gi?tj z1@mWEO7_a9nSC0jlK<_FRs$FkiLDE4;LgeX z&1Aue8olG0J?^zEzXto3FxA^~hKw|IK$uSET$GI1z(*sym;0AD zrAvdaHv+F7Ux&k&k|UIpBT%F+%`0T=Os^plX?M6zG1@>ZT3?AUbQJVDg&Z#tlb0~z zB^74`CBB!6F=*u|aB*DxZlbX=*|SLaIswF?r&Dm7B4)hfQ1Oq=`ER-G_~+4uKRO%} zcO34&bYh>!QVu_C4DbowyZo~POJ^7mW{3{`GegjeSJZIQno8W`51hh8b?o?=rWGJZ z4Qb8J)9~&28o*aJoZ-7k5=a96Q#S-cvbwZwM22 z^;lN|VcXV3pfAL`7ImSe9OH5 zxf7IjcKRP{&VMz&ESoDEYnrP7hD@i>X|>3dqwJ}1WdOAdTcsA<_`s>jT6iJ(`lxP8Fn+k;)i#|1%U z!&~Zo_{#3cdNY#B=b@$cC1~w=tITM{y)Y3?@Az`u1#^xh%!GmJmG$Epn~W=lRS zTxBEaPN&W=NOw$Ig>}d>FiC0_;TBYJ;90KRLLdG9*EcV6fHnjM^=(c@{{IoZa?S=; z=8k6nlmU{|JpVxueG|Q;OleXAYLK;^I99&Wz{G(e?TCKVeStQ3q?qAyS4NHru$R}B zObxNhbG(-W%gfCVNd}e`Rc8b10xbOIWy#@H8h?E#yn8CwPfnhje!rN{WNig*870hr z6GYFMjx!hEdk8pO?++_tGJ$48f0wQL6BRuGRO-;o(K_r4{4w$hs*9JKwqoeQFv(#^H5sY)r2R#MEdelx!oi%lpAFI zjM;Sre)FOb|II&yVc!!@w+95Ki|(n5l!M~GSBUso{=!XuKmagg90o{i5-gP2=#@sQ zH6umcc~I>wh8P~BuWwk8Nh#C;_o)m*!er|0}!+aP70MuhE2rp1t z#MLC#syXyT;8q%uVg0naqcdsr$;?w(!J2#ljEvO#s(J&at1c`w4B5FsO$=hBKqTS= ztox|!EEXi-lYQ_+GJUi$8h3@?xxH)wf8Q!UnQ21Ww#aa5-{6lk&Mvt|3#v!mMc@YN zH&L8i9s+qh#3Vd8wTTXpYO1gE^NWBJSt<+S6aoy6oEzOeQvB~!;oOAI_Y1g%w8Zdb8#rB z5P+RUJM&>N$+&sjbL74w+Lo*W*ed-DY}%EmK$*K) z#|DW;A0Da++%2a^qGGPXj&D;2Gs1l!-c%Hxpt*wpLmR1-xf{+2rKs_)KJ?2W`LIKf_OEAXKG_Wpc`#`52J4?cW)1%~|x7SAAso$RJm=6QyRQ{94_Q>d1vGZn(*ghlLA^rLx<;q~CMLk*TneYABY(@kmlS z?F4axA?dD!xblX>t{H71bP3CI|=F`n2i|rk2oV*4;nB^6@hT9Aj8W z?gMjI>~Umb%+j&EL-&}du?w2c-(tV3(0|Gd+}uF`elOmVy{ix3V|@~Ws*4T4xXBMl zzElMF?A>75^zkvjqnMUzPp&tccS>EcyhcODHCMuFAH(eKr)j!m&r9VLQplzLu1AQI z1DapF7I?&Y5XrPwKQvc|kZwOt1YBTXG_$HPP5dmI-YX()I^Sm>Qgd|A)VHkdy=`-I z>^71R>hNq`dbM3^wLJS1 zFHPE{AXc3rL28`E@R50BP-=om4hhy_{Ih)bfnQzG&P8E?)qpvo0$Nhcn8`PUW%ijz@GwSV~0r}sIpwI9^ zYm&CB;tnfbJ@|-_wIG}guULc?R{(937t&4;lT}=X{Xi6am}NV`O4e)x$-V>hk!aEu~r9as#b{lus|-}PA; zd85-`WLNUcMc5SQj^yPL7WjcmWUm-+DOvr0o~T)6D@*L4;yCLIDSKqpMo;p1hd~uG z^)>5`^|dGolRtj39DH zrF&bB$YU#r>|u!c#%qWsvJjB$Vh^k%P4YxJ{{1By-vewPUqN zY_$rW580dZT_?fs20GzROMp*H%6I;>@1%ySH5k(~p65SKF|f)*eP(p#JKlGxUkIwm z+XeD(pA$^;NjvqlgQK*|_Gx=Ipc}W3{__f+U*;Bmy~L{(!N@JhX2ZvyK6)tB4aND( zYY{vxoGrdG5bcGnny3^K&JAw`<&bFXC*z#spcVb8D@M5KJDwc>WL}& z%Qy%&3tkfQMF_E#R$)U>ZQ?$_ju;uk#I(5M7J$NQ)r=H!j}5er|3#36axOMp6;9l0 z?9Nt+P*I|E`ZQ!$&L`x*SUJsPLm4U1`vUvdTa@OA{jB?U%nSYZP3k|7UKNdT^2*K8C;aHm8y++ zUQzm6nD1?9hLgp~DcE+Jo%5Xi`|sc-XVv4{39ko#p^1NDja;U5w|5>io$-1I&R4k4qE>$KmR15M8XRK+OXU_%aAn(|Xsp8;x@R0qrEb_h=fE2d ze^(F=f6p))0&DpWs%iYo3D9)z!c#Lz7nV6;S1MsXzmosn9E1DFWtB1qEoRgRf9Y(v z32g0|=@MU_rw2()qBYe40FBL_fEp2pML>>ree%^QSRj3lx0n>K5;+WJQXy}*)S+)N zx6%G9QYU6u!?lQOJ(ey(aPBdNC${{k;He>n-yf|Z@Wn$Ia&ZSK9kQP5&u>~^O{Bg! z+-dg_TyVyne7W`eTG?B_uSfjM+oo z)H#sw5l{U!`-Zwjl-O?>%L7zPep||-a#aSE5`|wrKY~||!GmSJFJGQx<>3xmAkI)` zk;ut2+Xni|LicM$?u`}kCEf;_(;O}VHu1(TaXOt_aEQT4uv>5@ccjH`IDt%~Y5zIf zz%%HKN<}H>ds!q0ahNFSs&F78!M4W^5&4INWG%@9=H6L?@oh-0Sp>JpK%^0`Kc}2X z!Eb884X;qvuP2&x8|&P*NRW-oIX&)H4rJ)aK*K$?Q%9$ffV$f=dAt)N(l<2tVRrzH zaib5qi7xktW-;Qe0(+2%#GWWK6(2$Idt|{lofu`0fzT`5!T1e*BA*`B?|t4ZeDdG! zWjY1KusA|=Z@qCtKi=%)&%G0naeqb-ymdeS6fU73JE0FH_#L9^>w4V^MgG~7Oint0EDK7GSon&Pk1uyNP$Ra zz_@O5!cDsmTP(sj4=AE_-nYVy$-l+O2sOTjB6PRipQMwl?j0W@Cw0(y{m6KJr^1O zsbM5r6clDq8&58Xn`vR;21W1mmdBHEOKH}eT%yqUW~T><89gy;Pu`!YKIy3G=sZE} z>FEsO0uz%#e~OS+&SwOOVP^VDqHPx)>mqckI2R3%HZn`vUC;QP$7@wSsvj}> zz51wXAH0;MZrv-iIh4Y1D-enO*O4o))GEg^y1kaM#3kN~Q5J~KP{kC9ZCgeMTcJ)WL{0}lHZQ;Ta zNZUm#w=8&t*yj4U+?IrPk)Sqbx}`hPPSZHE#TlQwI4ccTjeMvh@22Vn$`joDxg%$Q z7GgYql5%p;Em52Dy?421;3FDf-^(rWULM*rBsD3UAt_~}^UxoTKgA0YExTHqG( zc*GJGDc)G0Uu51D``FO!w>X0d4#+dAgqe@;;;Jz3b0EzrQD}Mqk8qV>yodNGfm(Qh zz_I4$m|Z*p7(rda$y)&WnV`uFdfd>SC*+QY({DF?xP(5pTduVvgy|+K@bf-?TQtKI8Oz04>1Oxbwx=ZI2{|c|b@C^^aH4 zJ_ZyPqA?z3r>5?cLl3fX3<#&bl>BqrGmG@1@QUtJY|XCvIs|zUI`sjlIdY@xf={%| zAR#l)gc=-GYOc26A>Y5=u}sp@sYbtPEd6g9>pyFhO2&@=WjuFQl>P^P%0nlep%AW= z`*So!t`@b>*B3ezA1pB~e>zeBfHIK`e4#J_9OC&C9>YfKqLe*)p!F%|1wkwCqzJcH zf%T@_b>@TpdGm1P?wRNZlN+ia=o%@WA_HcsP5zAuY(pxO-9)c7h$|@Jr({KZI#=L5gklp$wgls4G_=CwV2;>=g}zH-y-WX>+}s)9&7g&vvtj4 z(=ykovI-I4DUKE;#;h!9^*gZri)f;*OluX&cs*O~jKws)KXWuEL6&-VjpK&qDPZ8| zXGPP!KuZzO5J1$_2uAX`Ods4mrroR!&1aV;Fx{pc9sKR3rFql*Qp`Mb!roYiNR35; za+NS<=yY-QXK5tg;UzC7cT2(Q@P!PsbcmWfHP!HN|h@RAi zv>cn8F+y!^=evt0&}N=49l6HliQ(NaZmW%6WxmE=ylxmWd#X5Tw zvr%{k<%3-7kXN@a!-I1UW;(Lx-ZyhBaf_zt{W-a=Aw7ieDj4{mpDNM<{0Xcwz*i8Q zjYJRg@aB90!4uR=ePK2E82adVLilgy1C1bFL7|VkShnpJ-)k^11tU=!e^Ojw%7ai4 ze8!%L{mke!15UK5WPO2-2wrSVyBoM)P&LM`{3dL|ehMN9+hLCg{rrsj=@<{b)U*6Aup3%-R zT{0jHh=Ha9NcbssP`~*l1O<_>Wb%u+{X$X02$A8E7$grz>k2wRj@HQCe&A7#;|T=j z?3!Gy*_y1}Osuf|z&NFFLVbdadz9tZ&zT(`uqysIfa~DM<9W!A*gUI0jJIRN3=+T| zQNJ}#=JI@t>gMi9_^DG%@Bsc?Q06n2w%`*VRnh-8Cd${QftjtU@(vC02QTEL|F+3l zDwO1|vzY=1Df)L5md`Y@jrUb`$tJJVno{8B7u7fdD_c)<{9up5+rlC!B-~;N5>j*S zk1_@qAz7iQ!sbA;6;Kxf@Q0v?SOZN|aiNwp$b@~wJLrF{8OOV$G;!ZGL;L%F^Z$5S zicb1YO8SnL|9o0eO21|QQ7~+Aov4JtM-lnKfV4vtK;Qj9K*3WI?n>2+?-B2pgvoitRl>k95L@@| zyHQQ=U89e#UGi%+|A50GEst*n9;*X(EMFH1mM8fjY(?K%7L?0trbsI1Xk&Bh$PZ;` z%7_t}@U{NXA%qPc@DP6zmV5d~L=cg2v6#VLUR);e=Y!dlaD5nOoimCVe)s+(X@|2E`%=Zx2{Ah83v)1Ei#Rv~n z;rMT`p!c-HiD#pNUMjps{xNJ#p&2g_*d>fxGrGGS%VMS_E#i2uddI|Wwu>|3K9 z+qP{dE4FRhcG9s{Y`bIIwrzB5bj(iD>6>%*KKHx(|DA{XQ0rkm%~`W*)DNS^sEAi5 zIdn+V>23JvB@vJPCP?nJr?+!AbJc%mrVSaqCRP4&-%lj+6wy_%zG*prA_H_UDV(n) zi>#M9Y`KBrP*8#6sUl$LZrRK>WUkfFZ*E(mz^Rl>lx1VP#d0vkGIg`>JZGdhE13Ak znrWqR0FS`@X5FK(fI6ZqujqdPPX8AovfBmpSXGZ(s0wpn5_C}pL_5kIAa#sAEdQMi z-n3Zy3B*Q@BVQ1bSK=O>AbO}-Q^4ed4e-8v#8tdQ?Of>sbo&jzNz-{hB+pN=I#n3b zN_VERI$u|9sl()YQe*f(_q?SX{|^m0R{hcgO&$GH!66x5G*a4DTv>%70q!fr z?Zz0OM30bHC2qhVJ1}$E%mZXbCc~sl-od=aMwi;EAIAqry^;!qPWdS`ZIbsd{&r@3 z@9pb($t?T(O8}G^N^z`;8>{FTjUbtuNfGPlzCsVv4P9y386_H*abn7xfJHB|kUTPf zq&~DU&RmVXde{kLt+2heC@Kp$=N@CKK9mJyV&5_{A^=V_US_7vJk%~tXm-WM9Y;dG zoZyf;tT}r60lmDZy6sQGvJD?X>%10bOMS}rIByaYnWUF@(R0snXaGhvR&drQIZmMg zc_f*H<`x<_BI0cmIB_XqLv-7i9krPV+0>DZwwceB=P=$kXrhZK9X!yFQMOziV@4@o zBxv!UzudT`fLQ{t~-T@JGP?E~7zGq;&*zPw=(Aarn$RZ!TXOihTA7AFt% zquVe%^BuBhCHxa+@qtB5Et5{|7s;3AO*Qw$i^?tR$c;waclZuP9W#~fpq`dTtW`ho zFpTD_9M+m%DM*}SP@iJpSNhR+IGylmyesjzqt+0*gG?cJhIMg!S)I@fZQITF@G?R_ zg#Fcb(Pn``kn|Nli|O6L@ZAwEAvxD{NX__u54PnSwUO*%%tidJW8nkug%CmCe zQ^hL&bY)Pe+12ZwA;^a$ZnJE=gyVJWh+BE$GdYsqwTGeW`_Y&N~`=>j5(SnD+QoHEqjo2FY#YTc)t>RQ6SQF?z0yYLPFG z%HubMMX_!mGJooFMFJ5=)nvk~o_$uYO=UJ;rTj27(TH(!9rcjL^$ZH zrF%&J?Hl_4mDK<1yvx;rGg3QF{hZy(>|o>WDjg@Vy0}a*J_{)X2>M8OmXztYxgaV`}BHpHD)x&dJ-?Qzf{q~i^_H|L$&npl8 z)V#m>(iWg-QE*#-oj+Y?13n+#=JIbp)9dh|l*9$^3&Z&e@1i8o@P2vg-tB#$#?O@Q)=vxm__fM2TxG0O`@iLvR+Sw>itM!kTKX?wS4 zSVS*;*~k`j;La5NCIo0AV?~#W5vN3z%9Xevsh2kk^@re|sFZ|b+Ng=2T4yjFX%`pd z_!9ccmyF;Bt1)0RDO*=aOqEL%>F6*L)A2Q{lss_I7pN0fKFmYVuGp4iG_BCqEYz#O zuT?fHh~{F~YE}pj*|2mgl|-{wqYX(Q-n-_wEgi0t7J+AL9vT?G%L z7a=0KM?H9YQ`4(`FA1+jeTc|VgXMRJ%N7?$L!&!62U*p8X0vCLtZto)e9J7y(B}b&(V1_qn!T3>WMMPXDNxE_u!w zDS9zT)l7tS_KdxzOf$`pTblK{g=`}OO5>pY23{=}nR9CIsEE17+8F5-=-5(%#AHNw zDVN#kl@q;;lBo-tz})L7-Iu~dM)OdjQ8G#$g_rJN?pNJVhyMLwp=wHXDFWpRzI9!L zds90bLK?=PE6H2Vii+7q>uYm}Z0oh9UpbIuK_r~^!(jt&ir9V@g* z;n?H#Yfy~x-vF01jw`PNDCd#!%)w7jQ`JBptxAoFK*11=6$~V}L<|phZ?uirq|Y6Bv^}pJ-M{)=$kX2&$1m0QV%n3RZ1u z#bU-}&u~!`#+2zQLZOP0mGGo6<)lkk=?~7=^?gH;Z9P@#ZW35^fDMO{oI#jycy5`I z&>cp%hzg4t#~gx<_QoAggsD7bnojZ1)CyH-g<6&zoK}T#e^5?oHG>*x$X(EfK@?L8->%!z&4;Dc57)}Jlh!4JL)uu3Ej0gO&Ooo$s|DU zEzLNIUrT~-jBgn|uU@SsJ%tnD2#q26%D8VE8dAU1Tv7-VJHnH)>BNbsnY4uMjQDL9 zpNB#G*Qvr#;|XkPrt&quu|qeBN3c^DAAbWKcaa1a(v#bsJ&N-PE|D~v9qY@z6T4lV znf)5jpP&(g|W2E#@`~Mx*5Vh(ve*pzW4p!Y8xG zLaJ25lkaLID)p$k6df*ddH(i#n7T=E``5CW7ViO_OOahW9eym;MmntO<-XQ!u$g4I zb>>yJ9NDpB@1un~N!*56=;8Jx_!fk*u0hhVulQX>XRMQ(8JorGe9nd(2Io>t!Z@uf z9UUFa@d$+>4Og)>7VPH6NEuLP!rFRgK{vCY5><^(vFNRG^in^=*gMat`y4aZq2wp`Oa5eZ=KK|4 zTX=WzT%l9;ho5d)7sLR+TV0%_7G`Js_1YZ)U-2Rs;HnHt{Vh%bY2gq4CY{^&48nzT zWnrH{!liTP@4?Iu@nXD|teFWNvyB!rveQwczqAP&is_RTW;g--(uy!V`IK@~g*N%> zd`!woBKWyA_z`^=W&`mpspX z0C^IEr-HLE{0E=;dGG7zNvg~O)M%!ipzdu`GRe$TT-#?N%h}kqj4%&l>u1fl>aj?g zZKmU#Dt`d>s#_PTu0{4~(X)(ELcYvV9W(s1-n8C5*aR?bMx0M zU6NKSL@;}1^%x_Dah=Vm_29^El4|W9U~d&H{d_D{*d3d5=YxCR?i-N=^oZ77Jl2{K ziGxfmZ>|55NI5j5{v#J=`N@Xu1aaFTUCUulS zSvlF;VxMN3;UUSxy^E+9bB;?_61^@%*6n6#{n>mG3w|k-D1NYrpEX;Mp!cQ(5I@Pv zpHl0X-zNBCQd7}SkvKDw9RY#`*SZ|1ZZRke&TS*zDe|{w2o7+VC*N6_bSxX(I`6bO zQ3aLvozUh$$Z(^9zgt>_1-N0yzE|C=FJ(?F!MR9#m3m%xv!$uBuBs|x-uYweCp}Ww zHRO^C%d`;E`uF$IZ1J($$@83tcXf_z~f zCsx~Hvda|!3uQmDeln5C%$GBOsyjql)$w{pIzv-xUP2fnuZM=0Tlz5(m6B?>lC3Rn zalwO??*0qMWBPYf{y~$UfU}U~%r?S8sJ)ZOfZd~!Kp@|%SQz|Z51;Fvz-PN%nki#( z2NU{8#V?|?9>tUzve$T*sS*6Ptnx~V7+c3{s)&2}13|W^zhZ-KBL^&`Rvz5LROBeQVz0ElotC{`P}8k_FD5*C6132>U#~1ucAxbnyMT zeQU9acRgl4Mv!Yf{Pr9(nrm?7Qu9l)Yqw>wj-P3^HAt{*nOSMlFr^Rnlm0X9-ts|n zH~v1*CzvyE!Z&M!4?i7O;iQ0zV;Zjg4=M>ozW~!yfOq{zyV|rEO=u1@$s*L;9Do~X z1w_spp%(=Gs~`6x4kNx3Cv?VATWh4RO&mPkMA5d+An#Wz~^}hbAAG46lNE zA_jIO1iIFw9`oeCiq+eLFO26Qo0aKAmJyRl&q(21%dxhbu~<66Ft?$y35OiI$5qBQ z-YYZiyIu(|JqcU(h<)lby~w9rwaW7)nViX;q?V$+a3t5)UMmL6{9$3)zXQ$vqc~XN z@&=U&JD4*G2U!Hd@Yv2B;P=&^?|9s(3=aAEko(#eGIedP+zogK63jDvQ6GL(c!`c= z)9#RxVmMa43ZUHboFr@TS!Y@5B~Ga}_ZL`az2WG6%-xtezq(H`yu%WhdJM`7RC_^9 zET*$OVV9ynxwvY_((M5Zt~4su`z|~M<1j$d4Qndz@FkS{*#ghOG8%|nK?!%|*1lP+ zctJS#SE(V?vw7#Lk1Hsw_6{B&MPAM#+wzqbVGh*FLzD>hWe;OK5 zJJ6(CTv>H_`*v;S9*~VT&Hqd7#Tcfn3LtQZnRl~ygnk^FvS+qD1aoHNQQebccWrJe z*k9@wEdK_`c3OXQziq1O8G~dp9`ntg`6Ud}^%Du_ z8fGAa*N!qhAb12vELFbztunm6xFrR$f!$mmMlTIci!D?KMlTOSk0mq})yp5#X$AR$ z{5F{0=nt}n>|PfA-X=+Pa{m*Jkxn~h$GTD;Xxcj?{-8K&4GWac67(jJgk82dmS(&F zC4FOpHhd5R<=Kd@c7R+jx}rTc~!Wui80ENg6Y?{G?w*!Ms02}Vt%ls z4%*?b-fFaVJXJJ{1-K&>ubA`!P$kEXdk25G%YMB+QoT|RE#ITHw~yjDrOEG>DW%5r zlzt`?u~m+iXA=%{<0vtZ`eJ*kQVKF5b5*kCw z;Al`|XqBl=qA{3wTaXb2j4VcXl{pWu;N7j=+c64EyuaclBJgMurEEC8rqE2jFER=u z)-wI5e5JvVTkY14yGC|AZ-#A^NpUy60?ByH7jk~ zJP`zFjsed`tX8O&#!ZWLp?fjxEN8cZ*zfl>R`VdstlR-%e+fQ_($>YGZBP z&l9*#eDH_LvDTSjwDud7rR}%K&tyN+OGM(009KEPxkqHGF3aCBg@U6P!ZOB~yOT<| z8wc_k#dc=0j-#mNa2hn}CN+yukmgXWbi56!Ec2zI^CfOZ>5E~-E))(*Chf`_VY(P_ zp0xb!y5~cplN??;9UybGYX{!P0QlS23>SW2N)PwIVOxsdB6T*m^v)#VJzVBf4pO1>ZA%OZ|x=zChc3OA<(Iysj#$O(MzD}_bL9VLTC(H46Eu#3p=G^I|6MCUdx5vw5)tx@bJ%8r$Hqv}@ zB%Pl~GW#FaXWkayvT1$AI&i!vuf{bU2E2|n(5c&uqg=)!9%4_M{DT8ho5NVINzB#v z*MA)B@}cp)dVWwch$M=c?jsJ7fu zg+6Dzw!PlCF|QPdOfU>lbGg$xZPD29yye2@BzhUg{SDbIFOhwUx;^WqC z>0y=BOSIcq*P1-`okuGVS$_Q-0u)|_p7Zig)q);=sog^KP77D(5Zp=s4xj*cZb<>M z$mkjZO|u_hdu0r{!I1nipfv5{@ImLbVT53LmWErbHPvOOS_yDuKT{x9Q1q*+FQL4) zMHy#ZX(VJ95xGV@XO#8cQKNjS7decC5pF4ygNGeWxZ#&|D}B4a_tL!*KMym{M5L%?dXerPu<#` z{R6nZ+56Pp+MW1Ad41zzn=|~qz4PJYA2LHeXvQb5U!|(xuklZJ8#_l=V-vf7Uq1O? z+-+8may|~!Bp@viW|$=)Yxh1D3y;*=rtyCu*Rd(lvd~beGto8BCngGW_ffO(P^k+F z)@cz@j*Jt3OIn_jo|avEQJj>KXEZi7Gcq$W`353^`C|Z{o){C1F2T&i2<#s&HX029 zw0U1o`SWX#eho(#V^ceGrvDaNakO`GbojD#`yV@-f0f$)mq#Z28@$DL`v3aySpJ6( zPuWL`Oj*vyk)5rXa{Tge$}(xWmxhUUp}&HOL1%A(iiV9#WQzqh8JMP%zqPVUrLKhn zEm=s0tG|P=zk!Vb%s4L9503A|@-gtNQWhrV#%9PuTv@S+L5V?;AmG^A*f<$DT0-=Y z8pIRB{gD57J8l^wh{vzD`u^2n{3jpC(ZRyn(%r?_&Dzo7{}PgsmmLy9_Cqr*Y}nLM zLduK666_CLlVK89EFdK9aXiG8JgBupy>s+N{cq2w#SI-XB_|}_o1V-Ui;eiXHqURC zXH;6kToO#9oFo9tp_zz!*Np8ds#J~16zd&s&f{Av8R)TR3A9ceJbr5;i%tD1Z3-E| zrm)J=$%a!|7Q5?qN_?}`io(ST4tGH7N!rwE1+b>Wi}A4tN)&WO;CM|#BdhtbFsuad}fvO=k~z2Am0eVd*6I24pdH5{sdft{O(`_aEORwgn#CLTwc5wSQcgj9l z_lufJ0`O;>K6wJMagOn%j`N{L`;Q(ww~W$~&dz;hUK*fi%) zIL0px8yt1=B7{3AGDv-3IaPwlgBGJgbN(gZKnD7`w*ac#$qD{zQmZO zQ^H7r-$NlsW$liaf(@3hFJvcKWe$mKEM7-}s}%GXvX%)9d`D?Un%#Pq1C6>ksx~5s z2Mj%HlXaxV5Z*P6n!5Y|8_y#|gMQ(q)6ac72^e z3R(nCn&B4Oj2><$>lM>kRm(K_)*x{&cwO+5zgSVK07I1?Ke=t_(+(NMaw6?AzfM~s ztM8^91gb*32G|RMLWD4AVl0%@_q=KPqu-Ka$r9kS-F8QwP8X@Y9>m!k!X5TnRCD&H zTYg}@-0ekS8L3M!#nrd?Za52C-ax?N72=?)wz^>sSyLk`y89-nUiPgJoYM!KQ~$V+OH}_!cR~N#O8L6XEa`iLrR{#PSZj zaJ_+t+DANbOk{Jez7XC)hvG+7_)PnMamUsY(|LM>e3K6`j&$*NB@B*V5%2ZmZb)`d zUqSA1$1cb5Zf|3VNE}_BQF~EZ{a?2vD9i&JVsC_cDHs)RdGaE}y|Vbwpu8aGHrBwI zQ0vnF{sT{3GbSyWzOV%HYip4F11j%1wb<3o zi&YI_a7P>r5FN!Q6`;^D+>~x; zWkInhRG^J|lP)GQPp(Fn8VXbd?=#QFN~z!+cSb-;M5*k^CRY?HbzCoGU}lPbB${y> z7@M_lFeW8=6>Acls3wo&ne#WNLCjrwAlO3Nm9yc09L7!aHi%HF7EP|5>7dj8_8Wts zeGGc`GQyNeR9z|CEaE+LvovzN_RBR{aTm?9GYM&Y_KkYWjzj$cWH8av@Eho)h=twm zUgFOl&;?#CEcS*F%#8UP`GPcQhp^f@|FpmH{fDNHYh_3j-q%dGe07T1{&Tj)%q@)F z?c7uyO>NEH2uY7#{u6bJf{=U8;^rP{$ zDvfTk%kjsau$fxGEyDy!>OTVoLgKnTekz3l1bHu zJuLWG4WDXFiR&Xo3|*$(caviBhU|6YjQbF366cXLPPIGqmpP>0)aiEK%DC?bsml|K zyUV}M1voA0ZH6R9fML9pgd62W#-><4oEr5ugXZghm`veYrbYUP3V!0{z~uiJ1s7*c za=01qs?F=;^quc&kn()^*~F4!zPOMU&o=isJ`*rLi0fC$ie0MwL+bNvt!LiCnh}*X zgmwhioWGKKUeCQZkY|JrJtvnAoe754DD40rK57abPpqx5E|%HI*%$tyS)_H*{tWHH zwzx;Ma@MYH<_^{lmTFdC8{h2Tt4&>36HW7rp@51l1(^_yUX!-2f)|`o+2hg# zM9#)lf|&=caZ18BGRrWYk!!vZw9fZB+-Lz$uc`98*}XMv@3iS-1A$9P8xeiZ>6vR| z+7)=u`M6tS>H}$yOXcolUXD?Kw`D0DvC1*2#=&x8i(_(@6myIvUiuKN`rYKY@tb+Sw8%ZJTFl(HWm>=2iFEfo5hCS=;t z+E~aJG;WfXb)&JWZnP(`&(lI`>!AcI4{9;soWkWGyQ|qNRC@Nk(WDAK!~#*6s)S54 zbQJEs{TS>hIBkXM2_K2{70OKju4h1o`FNzqx-K+Yq5%?*y}K-O`%m7o%$ z>2$TXj0Qw)uGS?AR#F^~3z^(w-5_|OL2OS%sas_54_WtwqF{aOhQ4>xzoWl^subMOjUVziFZD4 z+@d5lT~uDwOaI647k6s5+>Jx}=dEOveV z4Y7GWN>_qK;$P-?MP$KL#$9h(9>I}iEYWQA`z}&-sjQMdc@d;6FOgZK6+ZMmp?Je_ zCV2u=dJHCUFFrU(w+SzHeK0hmlY62kQhS`W4f?_DjGGRjS6aKa3z8r1L$7EsU_=iM zujHGbu=?6y`5p@|P4##AP3CXJWFKHTCRI=Qr|54efARh^P_~L-t^@NXw{W?{PQQP$@q>3A61s6R61Q1 z{AO?;qbar`V~gjiSv~2hUZWhluWox4>6c&PTDiC`qOpP9Yf!zu^_zj!^PV7j-g=5~ ztkt?0RZ`s`=TvN&iDE|WEvGykY=l#dK>z{OmizRuk8t~SR(+do>f!qg1)X!jw+;ru z7`_HH*Q+7Q+Ae>gAnn{B$=SHapN}a`UF+~zK=866@)dl_Czbd_h4YvE4Hqt#vu|T- z@SlH`35mQdzO%9p&2unRC34fl^4^E!E6&R0#XYvOr2s(|{hausjrmBbKH|`|{dwz; z3yW%njFnJpD@7q;Gc4L&Dnl1mcrld**x~txIe_OwJphD>&)lacAz*=vF6;boW02!* z1T6=>gJBsujdjT|ZHS5qgSfvnXHIs>)ray%maSq5fwLB*#x28GWzfxSPvJc4E%p+= zB7Dj%*wD0eMhWY2kBFutw0a@u?RR{K{MZVfUTsIh9Zukci{YJGwB?XPX&L0U*ztgU z{tgaj2l_j4=eYuYtdhF%u{xLa@jAdiROf{hhwaE`(0=L!7^PFk{>Ep+|66_>c?Cgm z9VOJ)_S*_o>>)&jIwVK0zJU4MXS%_!$O19T!7tk3)bC`x=zWU-b;y)`=aM-%EEef} z1R&QrUQ%i1X7s4%**Rb)=4AR9alNitszB7&bc(?Ltqpx(-5&kPFc?g%-hZcQn!4tAa5tmdxol^t9#i7@@7;o-5I8-A99sF6-40k8>6_Gk#`KR^;SE!pqUI|L0RP(eH2-U?py}vhYv*We_CJy7zg_WS zRes8l2_y684#y~1$VYe{*0xczL>0XkUmrwcIYqwzD4e^J%Wn4QG-eFWr=TuG^6&Rw zZd?%+G6n-Mt8c5XoaR(s3kDb(fcTExBSR`RS&WLK7|Ol^wV_-QPjF<~^j5%@u3QLM zV_Iu}GrVA|+5aV9$ugw93n|F>@(0;9(z45pfRcHY82jvPKd6vllyfVBM~d$_u}9gs z&sX_s-Wr$PMZWo`(4E4E@uR^4U1V+Uc&`ki&ZbYWD;dz7+-J$GUwVuNWX!&Wcow%r zJfp{(3MZDtQ!H~yy9vl}Yye9<6yy2+gx4GfW9 z5CZqUJ29UXgt9=%5=yX0kbQ*W0~772tw~b@D7#vpUV+A+Lrvt=hyYT#)OD<=U6{`0 z35h3!)?m_OCqhsd{gC*HMMXKyKPbbo|tKyAjS|pFM6vuZh z!-mYF)u81H2D9CN+}P;#&M*XgW{cjkBIJImh?sM25Vywr!e5aKARY#SYH zFFUTY(>+bQy#c>rf5b@wSgCEx&y?zm_R|nCx?EIO>dQn$Fs3gl!u0o(K2%%BmV<)ivp;@f^^9X87(XZ$j@28pLw%5O*$> z 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 z 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

ewb;D-r7XArVu8KG|V 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 f6l~YCbtn6nEB3w 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 OhYSiT6$(iBp#BHktRXf4 diff --git a/persistence-modules/spring-boot-persistence-2/pom.xml b/persistence-modules/spring-boot-persistence-2/pom.xml index 8f76bce1b3..c1afededb0 100644 --- a/persistence-modules/spring-boot-persistence-2/pom.xml +++ b/persistence-modules/spring-boot-persistence-2/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung.boot.persistence spring-boot-persistence-2 @@ -41,20 +41,20 @@ - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - - net.bytebuddy - byte-buddy - + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + net.bytebuddy + byte-buddy + org.jdbi @@ -92,47 +92,23 @@ spring-boot-starter-test test - + - com.oracle - ojdbc8 - 12.2.0.1 - system - ${basedir}/lib/ojdbc8.jar - - - - com.oracle - ucp - 12.2.0.1 - system - ${basedir}/lib/ucp.jar - - - - com.oracle - ons - 12.2.0.1 - system - ${basedir}/lib/ons.jar - + com.mchange + c3p0 + ${c3p0.version} + - - com.mchange - c3p0 - ${c3p0.version} - + + org.apache.commons + commons-dbcp2 + + + + org.apache.tomcat + tomcat-jdbc + - - org.apache.commons - commons-dbcp2 - - - - org.apache.tomcat - tomcat-jdbc - - @@ -141,6 +117,23 @@ org.springframework.boot spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java + com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java + + + com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java + com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java + + + diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java index 327374cb54..9cf7e27c99 100644 --- a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java @@ -22,6 +22,8 @@ public class OracleConfiguration { dataSource.setURL("jdbc:oracle:thin:@//localhost:11521/ORCLPDB1"); dataSource.setFastConnectionFailoverEnabled(true); dataSource.setImplicitCachingEnabled(true); + // Only with clients prior to v11.2 + // dataSource.setConnectionCachingEnabled(true); return dataSource; } } diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java index 67b4b40712..b4c1544149 100644 --- a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java @@ -21,9 +21,11 @@ public class OracleUCPConfiguration { dataSource.setUser("books"); dataSource.setPassword("books"); dataSource.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource"); - dataSource.setURL("jdbc:oracle:thin:@//localhost:11521/ORCLPDB1"); + dataSource.setURL("jdbc:oracle:thin:@//localhost:11521/ORCLPDB1"); + dataSource.setFastConnectionFailoverEnabled(true); dataSource.setInitialPoolSize(5); + dataSource.setMinPoolSize(5); dataSource.setMaxPoolSize(10); return dataSource; } From 3786d6309db285b8d8f2b999b2ee020593816050 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 9 Apr 2020 16:48:25 +0800 Subject: [PATCH 062/194] Update README.md --- java-numbers/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java-numbers/README.md b/java-numbers/README.md index 8f53006b38..f4b76c3c98 100644 --- a/java-numbers/README.md +++ b/java-numbers/README.md @@ -12,4 +12,5 @@ This module contains articles about numbers in Java. - [Calculating the nth Root in Java](https://www.baeldung.com/java-nth-root) - [Convert Double to String, Removing Decimal Places](https://www.baeldung.com/java-double-to-string) - [Changing the Order in a Sum Operation Can Produce Different Results?](https://www.baeldung.com/java-floating-point-sum-order) +- [Using Math.sin with Degrees](https://www.baeldung.com/java-math-sin-degrees) - More articles: [[next -->]](/../java-numbers-2) From d29fef1f518a3d35cb35d74204ba468a263a825b Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Thu, 9 Apr 2020 16:50:03 +0800 Subject: [PATCH 063/194] Update README.md --- core-kotlin-modules/core-kotlin/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-kotlin-modules/core-kotlin/README.md b/core-kotlin-modules/core-kotlin/README.md index 90caccf5c8..151da607ac 100644 --- a/core-kotlin-modules/core-kotlin/README.md +++ b/core-kotlin-modules/core-kotlin/README.md @@ -3,7 +3,7 @@ This module contains articles about Kotlin core features. ### Relevant articles: -- [Introduction to the Kotlin Language](https://www.baeldung.com/kotlin-intro) +- [Introduction to the Kotlin Language](https://www.baeldung.com/kotlin/tutorial) - [Kotlin Java Interoperability](https://www.baeldung.com/kotlin-java-interoperability) - [Get a Random Number in Kotlin](https://www.baeldung.com/kotlin-random-number) - [Create a Java and Kotlin Project with Maven](https://www.baeldung.com/kotlin-maven-java-project) From b132703ce9a61e3ca0a8b6ea69b9790075907265 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Thu, 9 Apr 2020 21:04:10 +0530 Subject: [PATCH 064/194] JWs module dependency fix --- jws/pom.xml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/jws/pom.xml b/jws/pom.xml index e6ab7e05ec..f867df8051 100644 --- a/jws/pom.xml +++ b/jws/pom.xml @@ -17,7 +17,7 @@ OpenNMS Repository - http://repo.opennms.org/maven2/ + https://repo.opennms.org/maven2/ @@ -27,11 +27,6 @@ jnlp-servlet ${jnlp-servlet.version} - - javax.samples.jnlp - jnlp-jardiff - ${jnlp-jardiff.version} - @@ -84,7 +79,6 @@ 3.0.2 - 1.6.0 1.6.0 From bcf5d50baa5e4b8ce46be437095123a985dcadda Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Thu, 9 Apr 2020 23:42:31 +0530 Subject: [PATCH 065/194] JAVA-1188: Removed duplicate entry from README --- core-java-modules/core-java-collections-maps/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java-modules/core-java-collections-maps/README.md b/core-java-modules/core-java-collections-maps/README.md index 828f8992e1..15cb32fbe8 100644 --- a/core-java-modules/core-java-collections-maps/README.md +++ b/core-java-modules/core-java-collections-maps/README.md @@ -4,7 +4,6 @@ This module contains articles about Map data structures in Java. ### Relevant Articles: - [Guide to the Guava BiMap](https://www.baeldung.com/guava-bimap) -- [A Guide to Java HashMap](https://www.baeldung.com/java-hashmap) - [A Guide to LinkedHashMap in Java](https://www.baeldung.com/java-linked-hashmap) - [A Guide to TreeMap in Java](https://www.baeldung.com/java-treemap) - [How to Store Duplicate Keys in a Map in Java?](https://www.baeldung.com/java-map-duplicate-keys) From db789ae6748a944168dda12c507406e748405315 Mon Sep 17 00:00:00 2001 From: Krzysiek Date: Thu, 9 Apr 2020 20:55:15 +0200 Subject: [PATCH 066/194] JAVA-976: Fix spring-security-mvc-login configuration --- .../src/test/java/com/baeldung/SpringContextTest.java | 2 +- .../security/RedirectionSecurityIntegrationTest.java | 2 +- .../src/test/resources/mvc-servlet.xml | 8 -------- 3 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 spring-security-modules/spring-security-mvc-login/src/test/resources/mvc-servlet.xml diff --git a/spring-security-modules/spring-security-mvc-login/src/test/java/com/baeldung/SpringContextTest.java b/spring-security-modules/spring-security-mvc-login/src/test/java/com/baeldung/SpringContextTest.java index 4cf3b736ea..dfc83a40b0 100644 --- a/spring-security-modules/spring-security-mvc-login/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-security-modules/spring-security-mvc-login/src/test/java/com/baeldung/SpringContextTest.java @@ -7,7 +7,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration({ "/RedirectionWebSecurityConfig.xml", "/mvc-servlet.xml" }) +@ContextConfiguration({ "/RedirectionWebSecurityConfig.xml" }) @WebAppConfiguration public class SpringContextTest { @Test diff --git a/spring-security-modules/spring-security-mvc-login/src/test/java/com/baeldung/security/RedirectionSecurityIntegrationTest.java b/spring-security-modules/spring-security-mvc-login/src/test/java/com/baeldung/security/RedirectionSecurityIntegrationTest.java index 1235e2e69f..e2b444de20 100644 --- a/spring-security-modules/spring-security-mvc-login/src/test/java/com/baeldung/security/RedirectionSecurityIntegrationTest.java +++ b/spring-security-modules/spring-security-mvc-login/src/test/java/com/baeldung/security/RedirectionSecurityIntegrationTest.java @@ -25,7 +25,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration({ "/RedirectionWebSecurityConfig.xml", "/mvc-servlet.xml" }) +@ContextConfiguration({ "/RedirectionWebSecurityConfig.xml" }) @WebAppConfiguration public class RedirectionSecurityIntegrationTest { diff --git a/spring-security-modules/spring-security-mvc-login/src/test/resources/mvc-servlet.xml b/spring-security-modules/spring-security-mvc-login/src/test/resources/mvc-servlet.xml deleted file mode 100644 index aee837c977..0000000000 --- a/spring-security-modules/spring-security-mvc-login/src/test/resources/mvc-servlet.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - \ No newline at end of file From 06a4e640bb6da563db64c2d2d949b2ddbf4c73cf Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Fri, 10 Apr 2020 03:15:39 +0430 Subject: [PATCH 067/194] Fixed a few cassandra related issues --- persistence-modules/java-cassandra/pom.xml | 6 +++ .../src/test/resources/cassandra.yaml | 51 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 persistence-modules/java-cassandra/src/test/resources/cassandra.yaml diff --git a/persistence-modules/java-cassandra/pom.xml b/persistence-modules/java-cassandra/pom.xml index 54879fb321..091efaeff4 100644 --- a/persistence-modules/java-cassandra/pom.xml +++ b/persistence-modules/java-cassandra/pom.xml @@ -18,6 +18,12 @@ cassandra-driver-core ${cassandra-driver-core.version} true + + + com.google.guava + guava + + diff --git a/persistence-modules/java-cassandra/src/test/resources/cassandra.yaml b/persistence-modules/java-cassandra/src/test/resources/cassandra.yaml new file mode 100644 index 0000000000..59687444d0 --- /dev/null +++ b/persistence-modules/java-cassandra/src/test/resources/cassandra.yaml @@ -0,0 +1,51 @@ +cluster_name: 'Test Cluster' +hinted_handoff_enabled: true +max_hint_window_in_ms: 10800000 +hinted_handoff_throttle_in_kb: 1024 +max_hints_delivery_threads: 2 +hints_directory: target/embeddedCassandra/hints +authenticator: AllowAllAuthenticator +authorizer: AllowAllAuthorizer +permissions_validity_in_ms: 2000 +partitioner: RandomPartitioner +data_file_directories: + - target/embeddedCassandra/data +commitlog_directory: target/embeddedCassandra/commitlog +cdc_raw_directory: target/embeddedCassandra/cdc +disk_failure_policy: stop +key_cache_size_in_mb: +key_cache_save_period: 14400 +row_cache_size_in_mb: 0 +row_cache_save_period: 0 +saved_caches_directory: target/embeddedCassandra/saved_caches +commitlog_sync: periodic +commitlog_sync_period_in_ms: 10000 +commitlog_segment_size_in_mb: 32 +concurrent_reads: 32 +concurrent_writes: 32 +trickle_fsync: false +trickle_fsync_interval_in_kb: 10240 +thrift_framed_transport_size_in_mb: 15 +thrift_max_message_length_in_mb: 16 +incremental_backups: false +snapshot_before_compaction: false +auto_snapshot: false +column_index_size_in_kb: 64 +compaction_throughput_mb_per_sec: 16 +read_request_timeout_in_ms: 5000 +range_request_timeout_in_ms: 10000 +write_request_timeout_in_ms: 2000 +cas_contention_timeout_in_ms: 1000 +truncate_request_timeout_in_ms: 60000 +request_timeout_in_ms: 10000 +cross_node_timeout: false +endpoint_snitch: SimpleSnitch +dynamic_snitch_update_interval_in_ms: 100 +dynamic_snitch_reset_interval_in_ms: 600000 +dynamic_snitch_badness_threshold: 0.1 +request_scheduler: org.apache.cassandra.scheduler.NoScheduler +index_interval: 128 +seed_provider: + - class_name: org.apache.cassandra.locator.SimpleSeedProvider + parameters: + - seeds: "127.0.0.1" From 7e26a04973e631dcb6ea88cf0e9fbc7b2ad35a34 Mon Sep 17 00:00:00 2001 From: Kai Yuan Date: Fri, 10 Apr 2020 09:24:15 +0200 Subject: [PATCH 068/194] springboot shedlock building fix --- spring-boot-modules/spring-boot-libraries/pom.xml | 4 ++++ .../shedlock/SpringBootShedlockApplication.java} | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) rename spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/{Application.java => scheduling/shedlock/SpringBootShedlockApplication.java} (71%) diff --git a/spring-boot-modules/spring-boot-libraries/pom.xml b/spring-boot-modules/spring-boot-libraries/pom.xml index 2b1b1b7d12..090967d8a8 100644 --- a/spring-boot-modules/spring-boot-libraries/pom.xml +++ b/spring-boot-modules/spring-boot-libraries/pom.xml @@ -28,6 +28,10 @@ org.springframework.boot spring-boot-starter-tomcat + + org.springframework.boot + spring-boot-starter-data-jpa + org.springframework.boot spring-boot-starter-test diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/Application.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/SpringBootShedlockApplication.java similarity index 71% rename from spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/Application.java rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/SpringBootShedlockApplication.java index 15422e1065..cebb234036 100644 --- a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/Application.java +++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/scheduling/shedlock/SpringBootShedlockApplication.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.scheduling.shedlock; import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock; import org.springframework.boot.SpringApplication; @@ -8,8 +8,8 @@ import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling @EnableSchedulerLock(defaultLockAtMostFor = "PT30S") -public class Application { +public class SpringBootShedlockApplication { public static void main(String[] args) { - SpringApplication.run(Application.class, args); + SpringApplication.run(SpringBootShedlockApplication.class, args); } } From 52ca4fbcd9e8d1d42eafdb1b4b16326fa09eb404 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 15:29:38 +0800 Subject: [PATCH 069/194] Update README.md --- core-java-modules/core-java-date-operations-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-date-operations-2/README.md b/core-java-modules/core-java-date-operations-2/README.md index 728162ca1a..19c7b98d30 100644 --- a/core-java-modules/core-java-date-operations-2/README.md +++ b/core-java-modules/core-java-date-operations-2/README.md @@ -7,4 +7,5 @@ This module contains articles about date operations in Java. - [Checking If Two Java Dates Are on the Same Day](https://www.baeldung.com/java-check-two-dates-on-same-day) - [Converting Java Date to OffsetDateTime](https://www.baeldung.com/java-convert-date-to-offsetdatetime) - [How to Set the JVM Time Zone](https://www.baeldung.com/java-jvm-time-zone) +- [How to determine day of week by passing specific date in Java?](https://www.baeldung.com/java-get-day-of-week) - [[<-- Prev]](/core-java-modules/core-java-date-operations-1) From bf764f5f44da4adf16a24d08313c85fecf4a93c2 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 15:31:19 +0800 Subject: [PATCH 070/194] Update README.md --- spring-reactive-kotlin/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-reactive-kotlin/README.md b/spring-reactive-kotlin/README.md index 629f7e7f58..d6ce3b7645 100644 --- a/spring-reactive-kotlin/README.md +++ b/spring-reactive-kotlin/README.md @@ -4,3 +4,4 @@ This module contains articles about reactive Kotlin ### Relevant Articles: - [Spring Webflux with Kotlin](https://www.baeldung.com/spring-webflux-kotlin) +- [Kotlin Reactive Microservice With Spring Boot](https://www.baeldung.com/spring-boot-kotlin-reactive-microservice) From e1cf55dc822408210083eff3d52f6502d2c4060f Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 15:40:36 +0800 Subject: [PATCH 071/194] Update README.md --- core-java-modules/core-java-lang-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-lang-2/README.md b/core-java-modules/core-java-lang-2/README.md index 65d40c6a26..3ade982397 100644 --- a/core-java-modules/core-java-lang-2/README.md +++ b/core-java-modules/core-java-lang-2/README.md @@ -10,4 +10,5 @@ This module contains articles about core features in the Java language - [How to Return Multiple Values From a Java Method](https://www.baeldung.com/java-method-return-multiple-values) - [Guide to the Java finally Keyword](https://www.baeldung.com/java-finally-keyword) - [The Java Headless Mode](https://www.baeldung.com/java-headless-mode) +- [Comparing Long Values in Java](https://www.baeldung.com/java-compare-long-values) - [[<-- Prev]](/core-java-modules/core-java-lang) From 404f13f940d2f2d7143f5d6bcd9231c27f63059a Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 15:46:47 +0800 Subject: [PATCH 072/194] Update README.md --- spring-security-modules/spring-security-mvc/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-security-modules/spring-security-mvc/README.md b/spring-security-modules/spring-security-mvc/README.md index 7d1a492cd3..bb4cfe1a4f 100644 --- a/spring-security-modules/spring-security-mvc/README.md +++ b/spring-security-modules/spring-security-mvc/README.md @@ -10,6 +10,7 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [HttpSessionListener Example – Monitoring](https://www.baeldung.com/httpsessionlistener_with_metrics) - [Control the Session with Spring Security](https://www.baeldung.com/spring-security-session) +- [The Clear-Site-Data Header in Spring Security](https://www.baeldung.com/spring-security-clear-site-data-header) ### Build the Project From 721f339d8c32ba93f908e021a298e90666544ce5 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 15:50:44 +0800 Subject: [PATCH 073/194] Update README.md --- core-java-modules/core-java-strings/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-strings/README.md b/core-java-modules/core-java-strings/README.md index 4a418db29f..5daae8394a 100644 --- a/core-java-modules/core-java-strings/README.md +++ b/core-java-modules/core-java-strings/README.md @@ -12,3 +12,4 @@ This module contains articles about strings in 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) - [Guide to Java String Pool](https://www.baeldung.com/java-string-pool) +- [Fixing “constant string too long” Build Error](https://www.baeldung.com/java-constant-string-too-long-error) From 086d6a9531a5f42f1284ed1809254d22226c688a Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 15:54:59 +0800 Subject: [PATCH 074/194] Update README.md --- persistence-modules/hibernate-jpa/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/hibernate-jpa/README.md b/persistence-modules/hibernate-jpa/README.md index d0a253f028..fb48f975bc 100644 --- a/persistence-modules/hibernate-jpa/README.md +++ b/persistence-modules/hibernate-jpa/README.md @@ -13,3 +13,4 @@ This module contains articles specific to use of Hibernate as a JPA implementati - [Enabling Transaction Locks in Spring Data JPA](https://www.baeldung.com/java-jpa-transaction-locks) - [TransactionRequiredException Error](https://www.baeldung.com/jpa-transaction-required-exception) - [JPA/Hibernate Persistence Context](https://www.baeldung.com/jpa-hibernate-persistence-context) +- [Quick Guide to EntityManager#getReference()](https://www.baeldung.com/jpa-entity-manager-get-reference) From f88c53eb4921eb6aac480f4524912e8ef5620f10 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 15:57:27 +0800 Subject: [PATCH 075/194] Update README.md --- core-java-modules/core-java-regex/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-regex/README.md b/core-java-modules/core-java-regex/README.md index 21cd7a95a3..6fdea9f2ca 100644 --- a/core-java-modules/core-java-regex/README.md +++ b/core-java-modules/core-java-regex/README.md @@ -9,3 +9,4 @@ - [Pre-compile Regex Patterns Into Pattern Objects](https://www.baeldung.com/java-regex-pre-compile) - [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) +- [Regular Expressions \s and \s+ in Java](https://www.baeldung.com/java-regex-s-splus) From 012465bed2504d614c0c694e24c0f023492ba1dc Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:00:00 +0800 Subject: [PATCH 076/194] Create README.md --- persistence-modules/spring-persistence-simple-2/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 persistence-modules/spring-persistence-simple-2/README.md diff --git a/persistence-modules/spring-persistence-simple-2/README.md b/persistence-modules/spring-persistence-simple-2/README.md new file mode 100644 index 0000000000..a6408df8f2 --- /dev/null +++ b/persistence-modules/spring-persistence-simple-2/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Spring JdbcTemplate Unit Testing](https://www.baeldung.com/spring-jdbctemplate-testing) From 564e7fc0337630a6b7e53a49abbd018dabf3eb06 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:02:20 +0800 Subject: [PATCH 077/194] Create README.md --- algorithms-miscellaneous-6/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 algorithms-miscellaneous-6/README.md diff --git a/algorithms-miscellaneous-6/README.md b/algorithms-miscellaneous-6/README.md new file mode 100644 index 0000000000..d9d6483a39 --- /dev/null +++ b/algorithms-miscellaneous-6/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Boruvka’s Algorithm for Minimum Spanning Trees](https://www.baeldung.com/java-boruvka-algorithm) From 09b03f875416b14694b3491c46cbcf52e796bb91 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:05:30 +0800 Subject: [PATCH 078/194] Update README.md --- algorithms-miscellaneous-6/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/algorithms-miscellaneous-6/README.md b/algorithms-miscellaneous-6/README.md index d9d6483a39..99be63d7ca 100644 --- a/algorithms-miscellaneous-6/README.md +++ b/algorithms-miscellaneous-6/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Boruvka’s Algorithm for Minimum Spanning Trees](https://www.baeldung.com/java-boruvka-algorithm) +- [Gradient Descent in Java](https://www.baeldung.com/java-gradient-descent) From acdcb5cacab872b1ce9b907483efa67a67e9cc23 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:07:16 +0800 Subject: [PATCH 079/194] Update README.md --- core-java-modules/core-java-concurrency-basic-2/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core-java-modules/core-java-concurrency-basic-2/README.md b/core-java-modules/core-java-concurrency-basic-2/README.md index e3f7a94e14..c7143baf36 100644 --- a/core-java-modules/core-java-concurrency-basic-2/README.md +++ b/core-java-modules/core-java-concurrency-basic-2/README.md @@ -8,4 +8,5 @@ This module contains articles about basic Java concurrency - [Difference Between Wait and Sleep in Java](https://www.baeldung.com/java-wait-and-sleep) - [Guide to the Synchronized Keyword in Java](https://www.baeldung.com/java-synchronized) - [Life Cycle of a Thread in Java](https://www.baeldung.com/java-thread-lifecycle) -- [[<-- Prev]](/core-java-modules/core-java-concurrency-basic) \ No newline at end of file +- [Guide to AtomicMarkableReference](https://www.baeldung.com/java-atomicmarkablereference) +- [[<-- Prev]](/core-java-modules/core-java-concurrency-basic) From 88afc279cffb8c58ec7f0e5416a34d2efb5ca282 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:10:17 +0800 Subject: [PATCH 080/194] Update README.md --- core-java-modules/core-java-string-operations/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-string-operations/README.md b/core-java-modules/core-java-string-operations/README.md index 18a2649a6a..c40e56bc46 100644 --- a/core-java-modules/core-java-string-operations/README.md +++ b/core-java-modules/core-java-string-operations/README.md @@ -13,4 +13,5 @@ This module contains articles about string operations. - [Adding a Newline Character to a String in Java](https://www.baeldung.com/java-string-newline) - [Check If a String Contains a Substring](https://www.baeldung.com/java-string-contains-substring) - [Java Base64 Encoding and Decoding](https://www.baeldung.com/java-base64-encode-and-decode) +- [Java Convert PDF to Base64](https://www.baeldung.com/java-convert-pdf-to-base64) - More articles: [[next -->]](../core-java-string-operations-2) From c34f99f42aac0ea22d6afbbbf356568c1afaa24c Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:21:07 +0800 Subject: [PATCH 081/194] Update README.md --- libraries-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries-3/README.md b/libraries-3/README.md index 62bd3b9f66..ec433960ef 100644 --- a/libraries-3/README.md +++ b/libraries-3/README.md @@ -16,3 +16,4 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m - [Introduction to Takes](https://www.baeldung.com/java-takes) - [Using NullAway to Avoid NullPointerExceptions](https://www.baeldung.com/java-nullaway) - [Introduction to Alibaba Arthas](https://www.baeldung.com/java-alibaba-arthas-intro) +- [Quick Guide to Spring Cloud Circuit Breaker](https://www.baeldung.com/spring-cloud-circuit-breaker) From 45abeb493b4d34a3b6502faa632d0bcd160cc3c7 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:22:40 +0800 Subject: [PATCH 082/194] Update README.md --- core-java-modules/core-java-concurrency-advanced-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-concurrency-advanced-3/README.md b/core-java-modules/core-java-concurrency-advanced-3/README.md index 2c554e948b..b11cde5158 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/README.md +++ b/core-java-modules/core-java-concurrency-advanced-3/README.md @@ -10,4 +10,5 @@ This module contains articles about advanced topics about multithreading with co - [Guide to RejectedExecutionHandler](https://www.baeldung.com/java-rejectedexecutionhandler) - [Guide to Work Stealing in Java](https://www.baeldung.com/java-work-stealing) - [Asynchronous Programming in Java](https://www.baeldung.com/java-asynchronous-programming) +- [Java Thread Deadlock and Livelock](https://www.baeldung.com/java-deadlock-livelock) - [[<-- previous]](/core-java-modules/core-java-concurrency-advanced-2) From 76d15b81c505e8f82db8f70d786ee09c253622d6 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:25:53 +0800 Subject: [PATCH 083/194] Update README.md --- java-numbers-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java-numbers-3/README.md b/java-numbers-3/README.md index 598acfb927..f818bdb675 100644 --- a/java-numbers-3/README.md +++ b/java-numbers-3/README.md @@ -10,4 +10,5 @@ This module contains articles about numbers in Java. - [Generating Random Numbers in a Range in Java](https://www.baeldung.com/java-generating-random-numbers-in-range) - [Listing Numbers Within a Range in Java](https://www.baeldung.com/java-listing-numbers-within-a-range) - [Fibonacci Series in Java](https://www.baeldung.com/java-fibonacci) +- [Guide to the Number Class in Java](https://www.baeldung.com/java-number-class) - More articles: [[<-- prev]](/java-numbers-2) From cb016c1027f8ec8b9bcea4c87f88fd2a5a622fa0 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:28:18 +0800 Subject: [PATCH 084/194] Update README.md --- core-java-modules/core-java-security-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-security-2/README.md b/core-java-modules/core-java-security-2/README.md index 2eb21fb77e..24a821bd4d 100644 --- a/core-java-modules/core-java-security-2/README.md +++ b/core-java-modules/core-java-security-2/README.md @@ -8,4 +8,5 @@ This module contains articles about core Java Security - [MD5 Hashing in Java](http://www.baeldung.com/java-md5) - [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing) - [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java) +- [Checksums in Java](https://www.baeldung.com/java-checksums) - More articles: [[<-- prev]](/core-java-modules/core-java-security) From 618916b6ab8753bf6d419031d21e9e1db934e8f1 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:31:17 +0800 Subject: [PATCH 085/194] Update README.md --- guava-collections-map/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/guava-collections-map/README.md b/guava-collections-map/README.md index b3ec5e2157..4f8743dcfb 100644 --- a/guava-collections-map/README.md +++ b/guava-collections-map/README.md @@ -9,4 +9,5 @@ This module contains articles about map collections in Guava - [Guide to Guava Multimap](https://www.baeldung.com/guava-multimap) - [Guide to Guava RangeMap](https://www.baeldung.com/guava-rangemap) - [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) -- [Guide to Guava ClassToInstanceMap](https://www.baeldung.com/guava-class-to-instance-map) \ No newline at end of file +- [Guide to Guava ClassToInstanceMap](https://www.baeldung.com/guava-class-to-instance-map) +- [Using Guava’s MapMaker](https://www.baeldung.com/guava-mapmaker) From 2b27994c13acca8ad0af453eb05c6e82749e6543 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:35:28 +0800 Subject: [PATCH 086/194] Update README.md --- spring-batch/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spring-batch/README.md b/spring-batch/README.md index d637de269c..3a89459629 100644 --- a/spring-batch/README.md +++ b/spring-batch/README.md @@ -3,6 +3,7 @@ This module contains articles about Spring Batch ### Relevant Articles: + - [Introduction to Spring Batch](https://www.baeldung.com/introduction-to-spring-batch) - [Spring Batch using Partitioner](https://www.baeldung.com/spring-batch-partitioner) - [Spring Batch – Tasklets vs Chunks](https://www.baeldung.com/spring-batch-tasklet-chunk) @@ -10,3 +11,4 @@ This module contains articles about Spring Batch - [Configuring Skip Logic in Spring Batch](https://www.baeldung.com/spring-batch-skip-logic) - [Testing a Spring Batch Job](https://www.baeldung.com/spring-batch-testing-job) - [Configuring Retry Logic in Spring Batch](https://www.baeldung.com/spring-batch-retry-logic) +- [Conditional Flow in Spring Batch](https://www.baeldung.com/spring-batch-conditional-flow) From 44f3912f83a0aa0f7aa4dcdec5a0496d020e7bfa Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:38:35 +0800 Subject: [PATCH 087/194] Update README.md --- core-kotlin-modules/core-kotlin-collections/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-kotlin-modules/core-kotlin-collections/README.md b/core-kotlin-modules/core-kotlin-collections/README.md index bbea5869af..f0da2b4cfd 100644 --- a/core-kotlin-modules/core-kotlin-collections/README.md +++ b/core-kotlin-modules/core-kotlin-collections/README.md @@ -8,3 +8,4 @@ This module contains articles about core Kotlin collections. - [Overview of Kotlin Collections API](https://www.baeldung.com/kotlin-collections-api) - [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) +- [Collection Transformations in Kotlin](https://www.baeldung.com/kotlin-collection-transformations) From fba81f5e629ca568d197622b6d32dbe1c653de15 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:40:10 +0800 Subject: [PATCH 088/194] Update README.md --- guava/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guava/README.md b/guava/README.md index c67a3604ea..71f76c1360 100644 --- a/guava/README.md +++ b/guava/README.md @@ -12,4 +12,4 @@ This module contains articles a Google Guava - [Guide to Mathematical Utilities in Guava](https://www.baeldung.com/guava-math) - [Bloom Filter in Java using Guava](https://www.baeldung.com/guava-bloom-filter) - [Quick Guide to the Guava RateLimiter](https://www.baeldung.com/guava-rate-limiter) - +- [Introduction to Guava Throwables](https://www.baeldung.com/guava-throwables) From a70207b99317ff43992f9704b1832de960132d79 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:42:37 +0800 Subject: [PATCH 089/194] Update README.md --- core-java-modules/core-java-14/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-14/README.md b/core-java-modules/core-java-14/README.md index 0e8278c4f6..13bb468b30 100644 --- a/core-java-modules/core-java-14/README.md +++ b/core-java-modules/core-java-14/README.md @@ -7,3 +7,4 @@ This module contains articles about Java 14. - [Guide to the @Serial Annotation in Java 14](https://www.baeldung.com/java-14-serial-annotation) - [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) +- [Helpful NullPointerExceptions in Java 14](https://www.baeldung.com/java-14-nullpointerexception) From 28401da21a1410bd54c2c4be125d68ffc529f933 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:44:41 +0800 Subject: [PATCH 090/194] Create README.md --- libraries-concurrency/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 libraries-concurrency/README.md diff --git a/libraries-concurrency/README.md b/libraries-concurrency/README.md new file mode 100644 index 0000000000..d1ffe81fa8 --- /dev/null +++ b/libraries-concurrency/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Intro to Coroutines with Quasar](https://www.baeldung.com/java-quasar-coroutines) From a1b1870921120ac90c7b68fa3a19004f564b801a Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:46:53 +0800 Subject: [PATCH 091/194] Update README.md --- core-java-modules/core-java-streams-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-streams-3/README.md b/core-java-modules/core-java-streams-3/README.md index a739245399..05c4b99900 100644 --- a/core-java-modules/core-java-streams-3/README.md +++ b/core-java-modules/core-java-streams-3/README.md @@ -9,4 +9,5 @@ This module contains articles about the Stream API in Java. - [Guide to Java 8’s Collectors](https://www.baeldung.com/java-8-collectors) - [Primitive Type Streams in Java 8](https://www.baeldung.com/java-8-primitive-streams) - [Debugging Java 8 Streams with IntelliJ](https://www.baeldung.com/intellij-debugging-java-streams) +- [Add BigDecimals using the Stream API](https://www.baeldung.com/java-stream-add-bigdecimals) - More articles: [[<-- prev>]](/../core-java-streams-2) From 8e1787ffeacc858d72180a8d0919650feb796e2e Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:48:28 +0800 Subject: [PATCH 092/194] Update README.md --- spring-5-mvc/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-5-mvc/README.md b/spring-5-mvc/README.md index e98012c047..aff8bb227c 100644 --- a/spring-5-mvc/README.md +++ b/spring-5-mvc/README.md @@ -6,3 +6,4 @@ This module contains articles about Spring 5 model-view-controller (MVC) pattern - [Spring Boot and Kotlin](https://www.baeldung.com/spring-boot-kotlin) - [Spring MVC Streaming and SSE Request Processing](https://www.baeldung.com/spring-mvc-sse-streams) - [Interface Driven Controllers in Spring](https://www.baeldung.com/spring-interface-driven-controllers) +- [Returning Plain HTML From a Spring MVC Controller](https://www.baeldung.com/spring-mvc-return-html) From 08472ff2e9e2dc28f7d7975a9d01a81d2e330742 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:50:04 +0800 Subject: [PATCH 093/194] Update README.md --- spring-thymeleaf-3/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-thymeleaf-3/README.md b/spring-thymeleaf-3/README.md index e1ddd727d7..a8e234b067 100644 --- a/spring-thymeleaf-3/README.md +++ b/spring-thymeleaf-3/README.md @@ -2,4 +2,5 @@ This module contains articles about Spring with Thymeleaf -## Relevant Articles: \ No newline at end of file +## Relevant Articles: +- [Add CSS and JS to Thymeleaf](https://www.baeldung.com/spring-thymeleaf-css-js) From fd1b953c2760173a9679638862a3ad79216a7e50 Mon Sep 17 00:00:00 2001 From: johnA1331 <53036378+johnA1331@users.noreply.github.com> Date: Fri, 10 Apr 2020 16:51:50 +0800 Subject: [PATCH 094/194] Update README.md --- spring-core-3/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-core-3/README.md b/spring-core-3/README.md index b2c4f694a8..6c210b23ef 100644 --- a/spring-core-3/README.md +++ b/spring-core-3/README.md @@ -10,4 +10,5 @@ This module contains articles about core Spring functionality - [Spring – Injecting Collections](https://www.baeldung.com/spring-injecting-collections) - [Design Patterns in the Spring Framework](https://www.baeldung.com/spring-framework-design-patterns) - [Injecting a Value in a Static Field in Spring](https://www.baeldung.com/spring-inject-static-field) +- [Difference Between BeanFactory and ApplicationContext](https://www.baeldung.com/spring-beanfactory-vs-applicationcontext) - More articles: [[<-- prev]](/spring-core-2) From 76cdbd811ebe8ad93758b22807b8ff4b331a50c5 Mon Sep 17 00:00:00 2001 From: patkorek Date: Fri, 10 Apr 2020 12:49:52 +0200 Subject: [PATCH 095/194] Modified one method --- .../com/baeldung/strings/ConvertStringToInt.groovy | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy b/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy index 3b179ee193..3b73c31596 100644 --- a/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy +++ b/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy @@ -62,10 +62,17 @@ class ConvertStringToInt { def stringNum = "123" int expectedInt = 123 int intNum = new Integer(stringNum).intValue() - int secondIntNum = new Integer(stringNum) assertEquals(intNum, expectedInt) - assertEquals(secondIntNum, expectedInt) + } + + @Test + void givenString_whenUsingNewInteger_thenConvertToInteger() { + def stringNum = "123" + int expectedInt = 123 + int intNum = new Integer(stringNum) + + assertEquals(intNum, expectedInt) } @Test From 949881921e6513972cc7143517c94b85b81f5644 Mon Sep 17 00:00:00 2001 From: patkorek Date: Fri, 10 Apr 2020 13:27:27 +0200 Subject: [PATCH 096/194] Added test case with isInteger() method. --- .../com/baeldung/strings/ConvertStringToInt.groovy | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy b/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy index 3b73c31596..7a4be4a957 100644 --- a/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy +++ b/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy @@ -96,4 +96,15 @@ class ConvertStringToInt { def invalidString = null invalidString.toInteger() } + + @Test + void givenString_whenUsingIsInteger_thenCheckIfCorrectValue() { + def invalidString = "123a" + def validString = "123" + def invalidNum = invalidString?.isInteger() ? invalidString as Integer : false + def correctNum = validString?.isInteger() ? validString as Integer : false + + assertEquals(false, invalidNum) + assertEquals(123, correctNum) + } } From 5a1f7ffea8d617a80d38234bb0f097de49747aed Mon Sep 17 00:00:00 2001 From: gindex Date: Fri, 10 Apr 2020 13:36:51 +0200 Subject: [PATCH 097/194] Add blockingHelloWorld() --- .../java/com/baeldung/mono/MonoUnitTest.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/reactor-core/src/test/java/com/baeldung/mono/MonoUnitTest.java b/reactor-core/src/test/java/com/baeldung/mono/MonoUnitTest.java index b493cd1159..f9e67b0a2f 100644 --- a/reactor-core/src/test/java/com/baeldung/mono/MonoUnitTest.java +++ b/reactor-core/src/test/java/com/baeldung/mono/MonoUnitTest.java @@ -12,13 +12,13 @@ import static org.junit.Assert.assertEquals; public class MonoUnitTest { @Test public void whenMonoProducesString_thenBlockAndConsume() { - String expected = "hello world!"; - String result1 = Mono.just(expected).block(); - assertEquals(expected, result1); + String result1 = blockingHelloWorld().block(); + assertEquals("Hello world!", result1); - String result2 = Mono.just(expected).block(Duration.of(1000, ChronoUnit.MILLIS)); - assertEquals(expected, result2); + String result2 = blockingHelloWorld() + .block(Duration.of(1000, ChronoUnit.MILLIS)); + assertEquals("Hello world!", result2); Optional result3 = Mono.empty().blockOptional(); assertEquals(Optional.empty(), result3); @@ -26,14 +26,18 @@ public class MonoUnitTest { @Test public void whenMonoProducesString_thenConsumeNonBlocking() { - String expected = "hello world!"; - Mono.just(expected) - .doOnNext(result -> assertEquals(expected, result)) + blockingHelloWorld() + .doOnNext(result -> assertEquals("Hello world!", result)) .subscribe(); - Mono.just(expected) - .subscribe(result -> assertEquals(expected, result)); + blockingHelloWorld() + .subscribe(result -> assertEquals("Hello world!", result)); } + + private Mono blockingHelloWorld() { + // blocking + return Mono.just("Hello world!"); + } } From 82e69447a54a650c59953fed9b0fab312fe552e6 Mon Sep 17 00:00:00 2001 From: kwoyke Date: Fri, 10 Apr 2020 21:58:48 +0200 Subject: [PATCH 098/194] BAEL-3730: Add example of usage CacheManagerCustomizer in Spring Boot (#9048) --- spring-caching/pom.xml | 4 ++++ .../caching/boot/CacheApplication.java | 14 +++++++++++ .../caching/boot/SimpleCacheCustomizer.java | 24 +++++++++++++++++++ .../SimpleCacheCustomizerIntegrationTest.java | 24 +++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java create mode 100644 spring-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java create mode 100644 spring-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java diff --git a/spring-caching/pom.xml b/spring-caching/pom.xml index c3ededbd14..d33f24de1f 100644 --- a/spring-caching/pom.xml +++ b/spring-caching/pom.xml @@ -19,6 +19,10 @@ org.springframework spring-context + + org.springframework.boot + spring-boot-starter-cache + org.springframework spring-web diff --git a/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java b/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java new file mode 100644 index 0000000000..714dc443e0 --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.caching.boot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; + +@SpringBootApplication +@EnableCaching +public class CacheApplication { + + public static void main(String[] args) { + SpringApplication.run(CacheApplication.class, args); + } +} diff --git a/spring-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java b/spring-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java new file mode 100644 index 0000000000..a76a01caae --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/caching/boot/SimpleCacheCustomizer.java @@ -0,0 +1,24 @@ +package com.baeldung.caching.boot; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.stereotype.Component; + +import static java.util.Arrays.asList; + +@Component +public class SimpleCacheCustomizer implements CacheManagerCustomizer { + + private static final Logger LOGGER = LoggerFactory.getLogger(SimpleCacheCustomizer.class); + + static final String USERS_CACHE = "users"; + static final String TRANSACTIONS_CACHE = "transactions"; + + @Override + public void customize(ConcurrentMapCacheManager cacheManager) { + LOGGER.info("Customizing Cache Manager"); + cacheManager.setCacheNames(asList(USERS_CACHE, TRANSACTIONS_CACHE)); + } +} diff --git a/spring-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java b/spring-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java new file mode 100644 index 0000000000..56a4bd4745 --- /dev/null +++ b/spring-caching/src/test/java/com/baeldung/caching/boot/SimpleCacheCustomizerIntegrationTest.java @@ -0,0 +1,24 @@ +package com.baeldung.caching.boot; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cache.CacheManager; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SimpleCacheCustomizerIntegrationTest { + + @Autowired + private CacheManager cacheManager; + + @Test + public void givenCacheManagerCustomizerWhenBootstrappedThenCacheManagerCustomized() { + assertThat(cacheManager.getCacheNames()) + .containsOnly(SimpleCacheCustomizer.USERS_CACHE, SimpleCacheCustomizer.TRANSACTIONS_CACHE); + } +} \ No newline at end of file From a6e5f78a488bbad61cf592185e9b1981cdd3140d Mon Sep 17 00:00:00 2001 From: mikr Date: Fri, 10 Apr 2020 23:59:34 +0200 Subject: [PATCH 099/194] JAVA-1225 Add dependency to Hibernate Code --- spring-boot-modules/spring-boot-springdoc/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spring-boot-modules/spring-boot-springdoc/pom.xml b/spring-boot-modules/spring-boot-springdoc/pom.xml index c99a9c2b24..375cf06c2c 100644 --- a/spring-boot-modules/spring-boot-springdoc/pom.xml +++ b/spring-boot-modules/spring-boot-springdoc/pom.xml @@ -37,6 +37,12 @@ test + + org.hibernate + hibernate-core + ${hibernate.version} + + org.springdoc @@ -61,6 +67,7 @@ 1.8 + 5.2.10.Final 1.2.32 From f154a172398ed6d3b8aa5cda91ad5d3cad08cde6 Mon Sep 17 00:00:00 2001 From: "ramprasad.devarakonda@gmail.com" Date: Tue, 24 Mar 2020 00:55:23 +0000 Subject: [PATCH 100/194] BAEL-3769 | Writing templates for test cases using JUnit 5 --- testing-modules/junit5-annotations/pom.xml | 9 +- .../junit5/templates/UserIdGenerator.java | 5 ++ .../junit5/templates/UserIdGeneratorImpl.java | 15 ++++ .../DisabledOnQAEnvironmentExtension.java | 27 ++++++ .../GenericTypedParameterResolver.java | 26 ++++++ .../UserIdGeneratorImplUnitTest.java | 18 ++++ .../templates/UserIdGeneratorTestCase.java | 37 ++++++++ ...eneratorTestInvocationContextProvider.java | 87 +++++++++++++++++++ .../src/test/resources/application.properties | 1 + 9 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 testing-modules/junit5-annotations/src/main/java/com/baeldung/junit5/templates/UserIdGenerator.java create mode 100644 testing-modules/junit5-annotations/src/main/java/com/baeldung/junit5/templates/UserIdGeneratorImpl.java create mode 100644 testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/DisabledOnQAEnvironmentExtension.java create mode 100644 testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/GenericTypedParameterResolver.java create mode 100644 testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorImplUnitTest.java create mode 100644 testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorTestCase.java create mode 100644 testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorTestInvocationContextProvider.java create mode 100644 testing-modules/junit5-annotations/src/test/resources/application.properties diff --git a/testing-modules/junit5-annotations/pom.xml b/testing-modules/junit5-annotations/pom.xml index d0fba4d21b..9e51d0ab55 100644 --- a/testing-modules/junit5-annotations/pom.xml +++ b/testing-modules/junit5-annotations/pom.xml @@ -46,12 +46,19 @@ ${junit.platform.version} test + + org.assertj + assertj-core + ${assertj-core.version} + test + - 5.6.0 + 5.6.2 1.6.0 2.8.2 + 3.11.1 diff --git a/testing-modules/junit5-annotations/src/main/java/com/baeldung/junit5/templates/UserIdGenerator.java b/testing-modules/junit5-annotations/src/main/java/com/baeldung/junit5/templates/UserIdGenerator.java new file mode 100644 index 0000000000..f19adb13c8 --- /dev/null +++ b/testing-modules/junit5-annotations/src/main/java/com/baeldung/junit5/templates/UserIdGenerator.java @@ -0,0 +1,5 @@ +package com.baeldung.junit5.templates; + +public interface UserIdGenerator { + String generate(String firstName, String lastName); +} diff --git a/testing-modules/junit5-annotations/src/main/java/com/baeldung/junit5/templates/UserIdGeneratorImpl.java b/testing-modules/junit5-annotations/src/main/java/com/baeldung/junit5/templates/UserIdGeneratorImpl.java new file mode 100644 index 0000000000..b39b07bc4b --- /dev/null +++ b/testing-modules/junit5-annotations/src/main/java/com/baeldung/junit5/templates/UserIdGeneratorImpl.java @@ -0,0 +1,15 @@ +package com.baeldung.junit5.templates; + +public class UserIdGeneratorImpl implements UserIdGenerator { + private boolean isFeatureEnabled; + + public UserIdGeneratorImpl(boolean isFeatureEnabled) { + this.isFeatureEnabled = isFeatureEnabled; + } + + public String generate(String firstName, String lastName) { + String initialAndLastName = firstName.substring(0, 1) + .concat(lastName); + return isFeatureEnabled ? "bael".concat(initialAndLastName) : initialAndLastName; + } +} diff --git a/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/DisabledOnQAEnvironmentExtension.java b/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/DisabledOnQAEnvironmentExtension.java new file mode 100644 index 0000000000..cd8b7b677d --- /dev/null +++ b/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/DisabledOnQAEnvironmentExtension.java @@ -0,0 +1,27 @@ +package com.baeldung.junit5.templates; + +import org.junit.jupiter.api.extension.ConditionEvaluationResult; +import org.junit.jupiter.api.extension.ExecutionCondition; +import org.junit.jupiter.api.extension.ExtensionContext; + +import java.io.IOException; +import java.util.Properties; + +public class DisabledOnQAEnvironmentExtension implements ExecutionCondition { + @Override + public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { + Properties properties = new Properties(); + try { + properties.load(DisabledOnQAEnvironmentExtension.class.getClassLoader() + .getResourceAsStream("application.properties")); + if ("qa".equalsIgnoreCase(properties.getProperty("env"))) { + String reason = String.format("The test '%s' is disabled on QA environment", context.getDisplayName()); + System.out.println(reason); + return ConditionEvaluationResult.disabled(reason); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return ConditionEvaluationResult.enabled("Test enabled"); + } +} \ No newline at end of file diff --git a/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/GenericTypedParameterResolver.java b/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/GenericTypedParameterResolver.java new file mode 100644 index 0000000000..76321be101 --- /dev/null +++ b/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/GenericTypedParameterResolver.java @@ -0,0 +1,26 @@ +package com.baeldung.junit5.templates; + +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.jupiter.api.extension.ParameterResolver; + +public class GenericTypedParameterResolver implements ParameterResolver { + T data; + + public GenericTypedParameterResolver(T data) { + this.data = data; + } + + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { + return parameterContext.getParameter() + .getType() + .isInstance(data); + } + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { + return data; + } +} diff --git a/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorImplUnitTest.java b/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorImplUnitTest.java new file mode 100644 index 0000000000..a2306154a6 --- /dev/null +++ b/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorImplUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.junit5.templates; + +import org.junit.jupiter.api.TestTemplate; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.assertj.core.api.Assertions.assertThat; + +public class UserIdGeneratorImplUnitTest { + @TestTemplate + @ExtendWith(UserIdGeneratorTestInvocationContextProvider.class) + public void whenUserIdRequested_thenUserIdIsReturnedInCorrectFormat(UserIdGeneratorTestCase testCase) { + UserIdGenerator userIdGenerator = new UserIdGeneratorImpl(testCase.isFeatureEnabled()); + + String actualUserId = userIdGenerator.generate(testCase.getFirstName(), testCase.getLastName()); + + assertThat(actualUserId).isEqualTo(testCase.getExpectedUserId()); + } +} \ No newline at end of file diff --git a/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorTestCase.java b/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorTestCase.java new file mode 100644 index 0000000000..dd41dd5a27 --- /dev/null +++ b/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorTestCase.java @@ -0,0 +1,37 @@ +package com.baeldung.junit5.templates; + +public class UserIdGeneratorTestCase { + private String displayName; + private boolean isFeatureEnabled; + private String firstName; + private String lastName; + private String expectedUserId; + + public UserIdGeneratorTestCase(String displayName, boolean isFeatureEnabled, String firstName, String lastName, String expectedUserId) { + this.displayName = displayName; + this.isFeatureEnabled = isFeatureEnabled; + this.firstName = firstName; + this.lastName = lastName; + this.expectedUserId = expectedUserId; + } + + public String getDisplayName() { + return displayName; + } + + public boolean isFeatureEnabled() { + return isFeatureEnabled; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } + + public String getExpectedUserId() { + return expectedUserId; + } +} diff --git a/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorTestInvocationContextProvider.java b/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorTestInvocationContextProvider.java new file mode 100644 index 0000000000..277ec03f05 --- /dev/null +++ b/testing-modules/junit5-annotations/src/test/java/com/baeldung/junit5/templates/UserIdGeneratorTestInvocationContextProvider.java @@ -0,0 +1,87 @@ +package com.baeldung.junit5.templates; + +import org.junit.jupiter.api.extension.*; + +import java.util.List; +import java.util.stream.Stream; + +import static java.util.Arrays.asList; + +public class UserIdGeneratorTestInvocationContextProvider implements TestTemplateInvocationContextProvider { + + @Override + public boolean supportsTestTemplate(ExtensionContext extensionContext) { + return true; + } + + @Override + public Stream provideTestTemplateInvocationContexts(ExtensionContext extensionContext) { + boolean featureDisabled = false; + boolean featureEnabled = true; + return Stream.of( + featureDisabledContext( + new UserIdGeneratorTestCase( + "Given feature switch disabled When user name is John Smith Then generated userid is JSmith", + featureDisabled, "John", "Smith", "JSmith")), + featureEnabledContext( + new UserIdGeneratorTestCase( + "Given feature switch enabled When user name is John Smith Then generated userid is baelJSmith", + featureEnabled, "John", "Smith", "baelJSmith")) + ); + } + + private TestTemplateInvocationContext featureDisabledContext(UserIdGeneratorTestCase userIdGeneratorTestCase) { + return new TestTemplateInvocationContext() { + @Override + public String getDisplayName(int invocationIndex) { + return userIdGeneratorTestCase.getDisplayName(); + } + + @Override + public List getAdditionalExtensions() { + return asList( + new GenericTypedParameterResolver(userIdGeneratorTestCase), + new BeforeTestExecutionCallback() { + @Override + public void beforeTestExecution(ExtensionContext extensionContext) { + System.out.println("BeforeTestExecutionCallback:Disabled context"); + } + }, + new AfterTestExecutionCallback() { + @Override + public void afterTestExecution(ExtensionContext extensionContext) { + System.out.println("AfterTestExecutionCallback:Disabled context"); + } + }); + } + }; + } + + private TestTemplateInvocationContext featureEnabledContext(UserIdGeneratorTestCase userIdGeneratorTestCase) { + return new TestTemplateInvocationContext() { + @Override + public String getDisplayName(int invocationIndex) { + return userIdGeneratorTestCase.getDisplayName(); + } + + @Override + public List getAdditionalExtensions() { + return asList( + new GenericTypedParameterResolver(userIdGeneratorTestCase), + new DisabledOnQAEnvironmentExtension(), + new BeforeEachCallback() { + @Override + public void beforeEach(ExtensionContext extensionContext) { + System.out.println("BeforeEachCallback:Enabled context"); + } + }, + new AfterEachCallback() { + @Override + public void afterEach(ExtensionContext extensionContext) { + System.out.println("AfterEachCallback:Enabled context"); + } + }); + } + }; + } +} diff --git a/testing-modules/junit5-annotations/src/test/resources/application.properties b/testing-modules/junit5-annotations/src/test/resources/application.properties new file mode 100644 index 0000000000..bbfa14d866 --- /dev/null +++ b/testing-modules/junit5-annotations/src/test/resources/application.properties @@ -0,0 +1 @@ +env=qa \ No newline at end of file From 552c1d805b281c6c575b269892e58d9b13d84b5b Mon Sep 17 00:00:00 2001 From: patkorek Date: Sat, 11 Apr 2020 14:39:36 +0200 Subject: [PATCH 101/194] Moved to com.baeldung.stringtoint package. --- .../baeldung/{strings => stringtoint}/ConvertStringToInt.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename core-groovy/src/test/groovy/com/baeldung/{strings => stringtoint}/ConvertStringToInt.groovy (98%) diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy b/core-groovy/src/test/groovy/com/baeldung/stringtoint/ConvertStringToInt.groovy similarity index 98% rename from core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy rename to core-groovy/src/test/groovy/com/baeldung/stringtoint/ConvertStringToInt.groovy index 7a4be4a957..48cf48fa8a 100644 --- a/core-groovy/src/test/groovy/com/baeldung/strings/ConvertStringToInt.groovy +++ b/core-groovy/src/test/groovy/com/baeldung/stringtoint/ConvertStringToInt.groovy @@ -1,4 +1,4 @@ -package com.baeldung.strings +package com.baeldung.stringtoint import org.junit.Test From 3bdfd8f72681b94c3ca21bea00bf039a387d89dd Mon Sep 17 00:00:00 2001 From: dupirefr Date: Sat, 11 Apr 2020 18:16:13 +0200 Subject: [PATCH 102/194] [JAVA-1265] Review build time * Migrate UserMapperUnitTest to UserMapperIntegrationTest as it uses Spring and takes a lot of time to execute --- jhipster-5/bookstore-monolith/pom.xml | 4 ++-- ...UserMapperUnitTest.java => UserMapperIntegrationTest.java} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/{UserMapperUnitTest.java => UserMapperIntegrationTest.java} (99%) diff --git a/jhipster-5/bookstore-monolith/pom.xml b/jhipster-5/bookstore-monolith/pom.xml index 5eaf761921..233765e0f3 100644 --- a/jhipster-5/bookstore-monolith/pom.xml +++ b/jhipster-5/bookstore-monolith/pom.xml @@ -7,7 +7,7 @@ 0.0.1-SNAPSHOT war Bookstore - + jhipster-5 com.baeldung.jhipster @@ -982,7 +982,7 @@ com.github.eirslett - frontend-maven-plugin + frontend-maven-plugin ${frontend-maven-plugin.version} install-node-and-npm diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/UserMapperUnitTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/UserMapperIntegrationTest.java similarity index 99% rename from jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/UserMapperUnitTest.java rename to jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/UserMapperIntegrationTest.java index cd6a326c06..cd49135d63 100644 --- a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/UserMapperUnitTest.java +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/UserMapperIntegrationTest.java @@ -26,7 +26,7 @@ import static org.assertj.core.api.Assertions.assertThat; */ @RunWith(SpringRunner.class) @SpringBootTest(classes = BookstoreApp.class) -public class UserMapperUnitTest { +public class UserMapperIntegrationTest { private static final String DEFAULT_LOGIN = "johndoe"; From bbae9153a8cb2fe1179736acb4fb38ede9e80e78 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sat, 11 Apr 2020 22:39:52 +0530 Subject: [PATCH 103/194] Disabling JWS module --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8d4632fb3e..b3d949d495 100644 --- a/pom.xml +++ b/pom.xml @@ -803,7 +803,7 @@ jenkins/plugins jhipster - jws + libraries @@ -1296,7 +1296,7 @@ jenkins/plugins jhipster - jws + libraries From 5b88ab42df3e40721064ad4892b2ee62a9bf1bd4 Mon Sep 17 00:00:00 2001 From: "amit.pandey" Date: Sun, 12 Apr 2020 00:01:36 +0530 Subject: [PATCH 104/194] sync source code with article --- .../jackson/date/JacksonDateUnitTest.java | 20 ++++++- .../hibernate/audit/AuditorAwareImpl.java | 21 +++++++ .../baeldung/spring/PersistenceConfig.java | 2 +- .../spring-boot-annotations/pom.xml | 17 ++++++ .../ConditionalBeanConfiguration.java | 16 +++++ .../annotations/HealthCheckController.java | 16 +++++ .../annotations/HibernateCondition.java | 15 +++++ .../annotations/MySQLAutoconfiguration.java | 59 +++++++++++++++++++ .../WebApplicationSpecificConfiguration.java | 13 ++++ .../ConfigPropertiesDemoApplication.java | 2 +- .../com/baeldung/properties/Database.java | 33 +++++++++++ .../src/main/resources/application.properties | 6 +- .../DatabasePropertiesIntegrationTest.java | 30 ++++++++++ .../src/test/resources/application.properties | 6 +- .../web/config/MainWebAppInitializer.java | 32 ++++++++++ .../baeldung/spring/web/config/WebConfig.java | 8 +++ .../FooMappingExamplesController.java | 2 +- ...egrationTest.java => SpringRetryTest.java} | 2 +- .../web/config/MainWebAppInitializer.java | 16 +++++ .../web/controller/SecurityController.java | 2 +- 20 files changed, 310 insertions(+), 8 deletions(-) create mode 100644 persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java create mode 100644 spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/ConditionalBeanConfiguration.java create mode 100644 spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/HealthCheckController.java create mode 100644 spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/HibernateCondition.java create mode 100644 spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/MySQLAutoconfiguration.java create mode 100644 spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/WebApplicationSpecificConfiguration.java create mode 100644 spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/Database.java create mode 100644 spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configurationproperties/DatabasePropertiesIntegrationTest.java create mode 100644 spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java rename spring-scheduling/src/test/java/com/baeldung/springretry/{SpringRetryIntegrationTest.java => SpringRetryTest.java} (96%) create mode 100644 spring-security-modules/spring-security-mvc/src/main/java/com/baeldung/session/web/config/MainWebAppInitializer.java diff --git a/jackson-modules/jackson-conversions/src/test/java/com/baeldung/jackson/date/JacksonDateUnitTest.java b/jackson-modules/jackson-conversions/src/test/java/com/baeldung/jackson/date/JacksonDateUnitTest.java index a264dd52f2..924ec1162f 100644 --- a/jackson-modules/jackson-conversions/src/test/java/com/baeldung/jackson/date/JacksonDateUnitTest.java +++ b/jackson-modules/jackson-conversions/src/test/java/com/baeldung/jackson/date/JacksonDateUnitTest.java @@ -1,6 +1,7 @@ package com.baeldung.jackson.date; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -8,6 +9,8 @@ import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Date; import java.util.TimeZone; @@ -30,7 +33,7 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; public class JacksonDateUnitTest { @Test - public void whenSerializingDateWithJackson_thenSerializedToNumber() throws JsonProcessingException, ParseException { + public void whenSerializingDateWithJackson_thenSerializedToTimestamp() throws JsonProcessingException, ParseException { final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm"); df.setTimeZone(TimeZone.getTimeZone("UTC")); @@ -61,6 +64,21 @@ public class JacksonDateUnitTest { final String result = mapper.writeValueAsString(event); assertThat(result, containsString("1970-01-01T02:30:00.000+00:00")); } + + @Test + public void whenDeserialisingZonedDateTimeWithDefaults_thenNotCorrect() + throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.findAndRegisterModules(); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC")); + String converted = objectMapper.writeValueAsString(now); + + ZonedDateTime restored = objectMapper.readValue(converted, ZonedDateTime.class); + System.out.println("serialized: " + now); + System.out.println("restored: " + restored); + assertThat(now, is(restored)); + } @Test public void whenSettingObjectMapperDateFormat_thenCorrect() throws JsonProcessingException, ParseException { diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java new file mode 100644 index 0000000000..d59497c2dc --- /dev/null +++ b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java @@ -0,0 +1,21 @@ +package com.baeldung.hibernate.audit; + +import java.util.Optional; + +import org.springframework.data.domain.AuditorAware; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +@Component("auditorProvider") +public class AuditorAwareImpl implements AuditorAware { + + @Override + public String getCurrentAuditor() { + return Optional.ofNullable(SecurityContextHolder.getContext()) + .map(e -> e.getAuthentication()) + .map(Authentication::getName) + .orElse(null); + } + +} diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java index b7cf0fadf2..195df6fb81 100644 --- a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java +++ b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java @@ -46,7 +46,7 @@ import com.google.common.base.Preconditions; @Configuration @EnableTransactionManagement @EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager") -@EnableJpaAuditing +@EnableJpaAuditing(auditorAwareRef = "auditorProvider") @PropertySource({ "classpath:persistence-h2.properties" }) @ComponentScan({ "com.baeldung.persistence" }) public class PersistenceConfig { diff --git a/spring-boot-modules/spring-boot-annotations/pom.xml b/spring-boot-modules/spring-boot-annotations/pom.xml index 9ad63214ef..59de83b4e5 100644 --- a/spring-boot-modules/spring-boot-annotations/pom.xml +++ b/spring-boot-modules/spring-boot-annotations/pom.xml @@ -24,6 +24,22 @@ org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.zaxxer + HikariCP + + + + + + org.hibernate + hibernate-core + @@ -32,4 +48,5 @@ test + diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/ConditionalBeanConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/ConditionalBeanConfiguration.java new file mode 100644 index 0000000000..4719425663 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/ConditionalBeanConfiguration.java @@ -0,0 +1,16 @@ +package com.baeldung.annotations; + +import java.util.Properties; + +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ConditionalBeanConfiguration { + + @Conditional(HibernateCondition.class) + Properties additionalProperties() { + // application specific properties + return new Properties(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/HealthCheckController.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/HealthCheckController.java new file mode 100644 index 0000000000..e87ed6cb47 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/HealthCheckController.java @@ -0,0 +1,16 @@ +package com.baeldung.annotations; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HealthCheckController { + + private static final String STATUS = "UP"; + + @GetMapping("/health") + public ResponseEntity healthCheck() { + return ResponseEntity.ok(STATUS); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/HibernateCondition.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/HibernateCondition.java new file mode 100644 index 0000000000..e2d77cc5d0 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/HibernateCondition.java @@ -0,0 +1,15 @@ +package com.baeldung.annotations; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class HibernateCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + // application specific condition check + return true; + } + +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/MySQLAutoconfiguration.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/MySQLAutoconfiguration.java new file mode 100644 index 0000000000..ba23267525 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/MySQLAutoconfiguration.java @@ -0,0 +1,59 @@ +package com.baeldung.annotations; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import javax.sql.DataSource; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.condition.ConditionalOnResource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaVendorAdapter; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; + +@Configuration +@ConditionalOnClass(DataSource.class) +public class MySQLAutoconfiguration { + + @Bean + @ConditionalOnBean(name = "dataSource") + LocalContainerEntityManagerFactoryBean entityManagerFactory() throws IOException { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + + final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + return em; + } + + @Bean + @ConditionalOnProperty(name = "usemysql", havingValue = "local") + DataSource dataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); + dataSource.setUrl("jdbc:hsqldb:mem:testdb"); + dataSource.setUsername( "sa" ); + dataSource.setPassword( "" ); + return dataSource; + } + + @ConditionalOnResource(resources = "classpath:mysql.properties") + Properties additionalProperties() throws IOException { + final Properties additionalProperties = new Properties(); + + try (InputStream inputStream = new ClassPathResource("classpath:mysql.properties").getInputStream()) { + additionalProperties.load(inputStream); + } + + return additionalProperties; + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/WebApplicationSpecificConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/WebApplicationSpecificConfiguration.java new file mode 100644 index 0000000000..62f68bee29 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/WebApplicationSpecificConfiguration.java @@ -0,0 +1,13 @@ +package com.baeldung.annotations; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class WebApplicationSpecificConfiguration { + + @ConditionalOnWebApplication + HealthCheckController healthCheckController() { + return new HealthCheckController(); + } +} diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java index 41f26d51f7..e54f28837d 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java +++ b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java @@ -7,7 +7,7 @@ import org.springframework.context.annotation.ComponentScan; import com.baeldung.configurationproperties.ConfigProperties; @SpringBootApplication -@ComponentScan(basePackageClasses = { ConfigProperties.class, JsonProperties.class, CustomJsonProperties.class }) +@ComponentScan(basePackageClasses = { ConfigProperties.class, JsonProperties.class, CustomJsonProperties.class, Database.class }) public class ConfigPropertiesDemoApplication { public static void main(String[] args) { new SpringApplicationBuilder(ConfigPropertiesDemoApplication.class).initializers(new JsonPropertyContextInitializer()) diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/Database.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/Database.java new file mode 100644 index 0000000000..6e798672e7 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/Database.java @@ -0,0 +1,33 @@ +package com.baeldung.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "database") +public class Database { + + private String url; + private String username; + private String password; + + public String getUrl() { + return url; + } + public void setUrl(String url) { + this.url = url; + } + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + +} diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/application.properties b/spring-boot-modules/spring-boot-properties/src/main/resources/application.properties index 2e06fad574..d4d1df7abc 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-properties/src/main/resources/application.properties @@ -1,4 +1,8 @@ management.endpoints.web.exposure.include=refresh spring.properties.refreshDelay=1000 spring.config.location=file:extra.properties -spring.main.allow-bean-definition-overriding=true \ No newline at end of file +spring.main.allow-bean-definition-overriding=true + +database.url=jdbc:postgresql:/localhost:5432/instance +database.username=foo +database.password=bar \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configurationproperties/DatabasePropertiesIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configurationproperties/DatabasePropertiesIntegrationTest.java new file mode 100644 index 0000000000..0b9bd797ae --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configurationproperties/DatabasePropertiesIntegrationTest.java @@ -0,0 +1,30 @@ +package com.baeldung.configurationproperties; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.properties.ConfigPropertiesDemoApplication; +import com.baeldung.properties.Database; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = ConfigPropertiesDemoApplication.class) +@TestPropertySource("classpath:application.properties") +public class DatabasePropertiesIntegrationTest { + + @Autowired + private Database database; + + @Test + public void testDatabaseProperties() { + Assert.assertNotNull(database); + Assert.assertEquals("jdbc:postgresql:/localhost:5432/instance", database.getUrl()); + Assert.assertEquals("foo", database.getUsername()); + Assert.assertEquals("bar", database.getPassword()); + } +} diff --git a/spring-boot-modules/spring-boot-properties/src/test/resources/application.properties b/spring-boot-modules/spring-boot-properties/src/test/resources/application.properties index 2e06fad574..d4d1df7abc 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/resources/application.properties +++ b/spring-boot-modules/spring-boot-properties/src/test/resources/application.properties @@ -1,4 +1,8 @@ management.endpoints.web.exposure.include=refresh spring.properties.refreshDelay=1000 spring.config.location=file:extra.properties -spring.main.allow-bean-definition-overriding=true \ No newline at end of file +spring.main.allow-bean-definition-overriding=true + +database.url=jdbc:postgresql:/localhost:5432/instance +database.username=foo +database.password=bar \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java new file mode 100644 index 0000000000..3623217130 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java @@ -0,0 +1,32 @@ +package com.baeldung.spring.web.config; + +import javax.servlet.MultipartConfigElement; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +public class MainWebAppInitializer implements WebApplicationInitializer { + + private String TMP_FOLDER = "/tmp"; + private int MAX_UPLOAD_SIZE = 5 * 1024 * 1024; + + @Override + public void onStartup(ServletContext sc) throws ServletException { + + ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet( + new GenericWebApplicationContext())); + + appServlet.setLoadOnStartup(1); + + MultipartConfigElement multipartConfigElement = new MultipartConfigElement(TMP_FOLDER, + MAX_UPLOAD_SIZE, MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2); + + appServlet.setMultipartConfig(multipartConfigElement); + + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java index 96e300464b..768fda1c4a 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java @@ -12,6 +12,7 @@ import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.http.MediaType; import org.springframework.http.converter.ByteArrayHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; @@ -121,4 +122,11 @@ public class WebConfig implements WebMvcConfigurer { public ExcelPOIHelper excelPOIHelper() { return new ExcelPOIHelper(); } + + @Bean(name = "multipartResolver") + public CommonsMultipartResolver multipartResolver() { + CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); + multipartResolver.setMaxUploadSize(100000); + return multipartResolver; + } } \ No newline at end of file diff --git a/spring-rest-http/src/main/java/com/baeldung/requestmapping/FooMappingExamplesController.java b/spring-rest-http/src/main/java/com/baeldung/requestmapping/FooMappingExamplesController.java index 543ba76273..cafd9a38e3 100644 --- a/spring-rest-http/src/main/java/com/baeldung/requestmapping/FooMappingExamplesController.java +++ b/spring-rest-http/src/main/java/com/baeldung/requestmapping/FooMappingExamplesController.java @@ -72,7 +72,7 @@ public class FooMappingExamplesController { @RequestMapping(value = "/foos", produces = { "application/json", "application/xml" }) @ResponseBody - public String getFoosAsJsonFromREST() { + public String getFoosAsJsonFromBrowser() { return "Get some Foos with Header New"; } diff --git a/spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryIntegrationTest.java b/spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryTest.java similarity index 96% rename from spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryIntegrationTest.java rename to spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryTest.java index 2e5fb75482..b22d5e620e 100644 --- a/spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryIntegrationTest.java +++ b/spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryTest.java @@ -12,7 +12,7 @@ import java.sql.SQLException; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = AppConfig.class, loader = AnnotationConfigContextLoader.class) -public class SpringRetryIntegrationTest { +public class SpringRetryTest { @Autowired private MyService myService; diff --git a/spring-security-modules/spring-security-mvc/src/main/java/com/baeldung/session/web/config/MainWebAppInitializer.java b/spring-security-modules/spring-security-mvc/src/main/java/com/baeldung/session/web/config/MainWebAppInitializer.java new file mode 100644 index 0000000000..f85f9f3fb0 --- /dev/null +++ b/spring-security-modules/spring-security-mvc/src/main/java/com/baeldung/session/web/config/MainWebAppInitializer.java @@ -0,0 +1,16 @@ +package com.baeldung.session.web.config; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.springframework.web.WebApplicationInitializer; + +public class MainWebAppInitializer implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext sc) throws ServletException { + sc.getSessionCookieConfig().setHttpOnly(true); + sc.getSessionCookieConfig().setSecure(true); + } + +} diff --git a/spring-security-modules/spring-security-rest-custom/src/main/java/com/baeldung/web/controller/SecurityController.java b/spring-security-modules/spring-security-rest-custom/src/main/java/com/baeldung/web/controller/SecurityController.java index f35940f54c..ece442430f 100644 --- a/spring-security-modules/spring-security-rest-custom/src/main/java/com/baeldung/web/controller/SecurityController.java +++ b/spring-security-modules/spring-security-rest-custom/src/main/java/com/baeldung/web/controller/SecurityController.java @@ -18,7 +18,7 @@ public class SecurityController { @RequestMapping(value = "/username2", method = RequestMethod.GET) @ResponseBody - public String currentUserNameSimple(final Principal principal) { + public String currentUserName(final Principal principal) { return principal.getName(); } From 2478c10c84b0b3f72f9253fa0fb4f17c075a9607 Mon Sep 17 00:00:00 2001 From: "amit.pandey" Date: Sun, 12 Apr 2020 01:05:59 +0530 Subject: [PATCH 105/194] reverted the file name --- .../{SpringRetryTest.java => SpringRetryIntegrationTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename spring-scheduling/src/test/java/com/baeldung/springretry/{SpringRetryTest.java => SpringRetryIntegrationTest.java} (96%) diff --git a/spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryTest.java b/spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryIntegrationTest.java similarity index 96% rename from spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryTest.java rename to spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryIntegrationTest.java index b22d5e620e..2e5fb75482 100644 --- a/spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryTest.java +++ b/spring-scheduling/src/test/java/com/baeldung/springretry/SpringRetryIntegrationTest.java @@ -12,7 +12,7 @@ import java.sql.SQLException; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = AppConfig.class, loader = AnnotationConfigContextLoader.class) -public class SpringRetryTest { +public class SpringRetryIntegrationTest { @Autowired private MyService myService; From b43d6e9bc8d2bf09f9588a250d61670b31e19936 Mon Sep 17 00:00:00 2001 From: "amit.pandey" Date: Sun, 12 Apr 2020 01:23:02 +0530 Subject: [PATCH 106/194] fix junit test case --- .../java/com/baeldung/hibernate/audit/AuditorAwareImpl.java | 2 -- .../main/java/com/baeldung/spring/PersistenceConfig.java | 6 ++++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java index d59497c2dc..7aef08b2ce 100644 --- a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java +++ b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java @@ -5,9 +5,7 @@ import java.util.Optional; import org.springframework.data.domain.AuditorAware; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; -@Component("auditorProvider") public class AuditorAwareImpl implements AuditorAware { @Override diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java index 195df6fb81..6ae133ca7a 100644 --- a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java +++ b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java @@ -23,6 +23,7 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; +import com.baeldung.hibernate.audit.AuditorAwareImpl; import com.baeldung.persistence.dao.IBarAuditableDao; import com.baeldung.persistence.dao.IBarDao; import com.baeldung.persistence.dao.IFooAuditableDao; @@ -58,6 +59,11 @@ public class PersistenceConfig { super(); } + @Bean("auditorProvider") + public AuditorAwareImpl auditorAwareImpl() { + return new AuditorAwareImpl(); + } + @Bean public LocalSessionFactoryBean sessionFactory() { final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); From 7facbd6bf6458eba0dea40234f036077d48d799e Mon Sep 17 00:00:00 2001 From: "amit.pandey" Date: Sun, 12 Apr 2020 04:31:53 +0530 Subject: [PATCH 107/194] update artifictId in pom file --- ddd-modules/pom.xml | 2 +- jgit/pom.xml | 4 ++-- persistence-modules/r2dbc/pom.xml | 2 +- persistence-modules/sirix/pom.xml | 2 +- quarkus-extension/quarkus-liquibase/deployment/pom.xml | 6 +++--- quarkus-extension/quarkus-liquibase/pom.xml | 4 ++-- quarkus-extension/quarkus-liquibase/runtime/pom.xml | 6 +++--- spring-cloud/spring-cloud-openfeign/pom.xml | 4 ++-- spring-cloud/spring-cloud-task/springcloudtasksink/pom.xml | 4 ++-- twitter4j/pom.xml | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/ddd-modules/pom.xml b/ddd-modules/pom.xml index 38e48ff27d..c6dd6e1f25 100644 --- a/ddd-modules/pom.xml +++ b/ddd-modules/pom.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung.dddmodules - dddmodules + ddd-modules 1.0 ddd-modules pom diff --git a/jgit/pom.xml b/jgit/pom.xml index eef3c9b8e8..d960843868 100644 --- a/jgit/pom.xml +++ b/jgit/pom.xml @@ -2,9 +2,9 @@ 4.0.0 - JGit + jgit 1.0-SNAPSHOT - JGit + jgit jar http://maven.apache.org diff --git a/persistence-modules/r2dbc/pom.xml b/persistence-modules/r2dbc/pom.xml index 55197ad560..70ff8d6a87 100644 --- a/persistence-modules/r2dbc/pom.xml +++ b/persistence-modules/r2dbc/pom.xml @@ -6,7 +6,7 @@ com.baeldung.examples.r2dbc r2dbc-example 0.0.1-SNAPSHOT - r2dbc-example + r2dbc Sample R2DBC Project diff --git a/persistence-modules/sirix/pom.xml b/persistence-modules/sirix/pom.xml index d8e065ec2f..0f114966f7 100644 --- a/persistence-modules/sirix/pom.xml +++ b/persistence-modules/sirix/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 io.sirix - core-api-tutorial + sirix 1.0-SNAPSHOT core-api-tutorial jar diff --git a/quarkus-extension/quarkus-liquibase/deployment/pom.xml b/quarkus-extension/quarkus-liquibase/deployment/pom.xml index c85d986390..5c6b56e152 100644 --- a/quarkus-extension/quarkus-liquibase/deployment/pom.xml +++ b/quarkus-extension/quarkus-liquibase/deployment/pom.xml @@ -3,8 +3,8 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - quarkus-liquibase-deployment - quarkus-liquibase-deployment + deployment + deployment com.baeldung.quarkus.liquibase @@ -58,4 +58,4 @@ 3.8.1 - \ No newline at end of file + diff --git a/quarkus-extension/quarkus-liquibase/pom.xml b/quarkus-extension/quarkus-liquibase/pom.xml index 9536561701..8ed6555ed7 100644 --- a/quarkus-extension/quarkus-liquibase/pom.xml +++ b/quarkus-extension/quarkus-liquibase/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.baeldung.quarkus.liquibase quarkus-liquibase-parent - quarkus-liquibase-parent + quarkus-liquibase pom @@ -23,4 +23,4 @@ 1.0.0.Final - \ No newline at end of file + diff --git a/quarkus-extension/quarkus-liquibase/runtime/pom.xml b/quarkus-extension/quarkus-liquibase/runtime/pom.xml index 83f7c8d4cc..760e6ab719 100644 --- a/quarkus-extension/quarkus-liquibase/runtime/pom.xml +++ b/quarkus-extension/quarkus-liquibase/runtime/pom.xml @@ -2,8 +2,8 @@ 4.0.0 - quarkus-liquibase-runtime - quarkus-liquibase-runtime + runtime + runtime com.baeldung.quarkus.liquibase @@ -70,4 +70,4 @@ 3.8.1 - \ No newline at end of file + diff --git a/spring-cloud/spring-cloud-openfeign/pom.xml b/spring-cloud/spring-cloud-openfeign/pom.xml index e20fe338c1..df529d7fb1 100644 --- a/spring-cloud/spring-cloud-openfeign/pom.xml +++ b/spring-cloud/spring-cloud-openfeign/pom.xml @@ -3,9 +3,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung.cloud - openfeign + spring-cloud-openfeign 0.0.1-SNAPSHOT - openfeign + spring-cloud-openfeign OpenFeign project for Spring Boot diff --git a/spring-cloud/spring-cloud-task/springcloudtasksink/pom.xml b/spring-cloud/spring-cloud-task/springcloudtasksink/pom.xml index 441924f1d3..93255959e4 100644 --- a/spring-cloud/spring-cloud-task/springcloudtasksink/pom.xml +++ b/spring-cloud/spring-cloud-task/springcloudtasksink/pom.xml @@ -2,8 +2,8 @@ 4.0.0 - SpringCloudTaskSink - SpringCloudTaskSink + springcloudtasksink + springcloudtasksink jar Demo project for Spring Boot diff --git a/twitter4j/pom.xml b/twitter4j/pom.xml index 6d98e2fe58..274b5c75c3 100644 --- a/twitter4j/pom.xml +++ b/twitter4j/pom.xml @@ -2,8 +2,8 @@ 4.0.0 - Twitter4J - Twitter4J + twitter4J + twitter4J jar From 4a83c738350acd32e9c6d2035dce0a91238be503 Mon Sep 17 00:00:00 2001 From: Kumar Chandrakant Date: Sun, 12 Apr 2020 10:06:34 +0530 Subject: [PATCH 108/194] Adding codebase for the article tracked under BAEL-2046. (#9055) --- atomikos/README.md | 7 ++ atomikos/pom.xml | 119 ++++++++++++++++++ .../baeldung/atomikos/direct/Application.java | 53 ++++++++ .../baeldung/atomikos/spring/Application.java | 41 ++++++ .../atomikos/spring/config/Config.java | 68 ++++++++++ .../atomikos/spring/jpa/Application.java | 48 +++++++ .../atomikos/spring/jpa/config/Config.java | 38 ++++++ .../spring/jpa/inventory/Inventory.java | 31 +++++ .../spring/jpa/inventory/InventoryConfig.java | 53 ++++++++ .../jpa/inventory/InventoryRepository.java | 9 ++ .../atomikos/spring/jpa/order/Order.java | 42 +++++++ .../spring/jpa/order/OrderConfig.java | 53 ++++++++ .../spring/jpa/order/OrderRepository.java | 9 ++ atomikos/src/main/resources/logback.xml | 13 ++ atomikos/src/main/resources/schema.sql | 10 ++ .../main/resources/transactions.properties | 1 + .../atomikos/direct/ApplicationUnitTest.java | 118 +++++++++++++++++ .../atomikos/spring/ApplicationUnitTest.java | 108 ++++++++++++++++ .../spring/jpa/ApplicationUnitTest.java | 80 ++++++++++++ atomikos/src/test/resources/logback.xml | 13 ++ .../test/resources/transactions.properties | 1 + pom.xml | 4 + 22 files changed, 919 insertions(+) create mode 100644 atomikos/README.md create mode 100644 atomikos/pom.xml create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/direct/Application.java create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/spring/Application.java create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/spring/config/Config.java create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/Application.java create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/config/Config.java create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/Inventory.java create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/InventoryConfig.java create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/InventoryRepository.java create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/Order.java create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/OrderConfig.java create mode 100644 atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/OrderRepository.java create mode 100644 atomikos/src/main/resources/logback.xml create mode 100644 atomikos/src/main/resources/schema.sql create mode 100644 atomikos/src/main/resources/transactions.properties create mode 100644 atomikos/src/test/java/com/baeldung/atomikos/direct/ApplicationUnitTest.java create mode 100644 atomikos/src/test/java/com/baeldung/atomikos/spring/ApplicationUnitTest.java create mode 100644 atomikos/src/test/java/com/baeldung/atomikos/spring/jpa/ApplicationUnitTest.java create mode 100644 atomikos/src/test/resources/logback.xml create mode 100644 atomikos/src/test/resources/transactions.properties diff --git a/atomikos/README.md b/atomikos/README.md new file mode 100644 index 0000000000..19f2e871d4 --- /dev/null +++ b/atomikos/README.md @@ -0,0 +1,7 @@ +## Atomikos + +This module contains articles about Atomikos + +### Relevant Articles: + +- [Guide Transactions Using Atomikos]() diff --git a/atomikos/pom.xml b/atomikos/pom.xml new file mode 100644 index 0000000000..881adae074 --- /dev/null +++ b/atomikos/pom.xml @@ -0,0 +1,119 @@ + + + 4.0.0 + atomikos + atomikos + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + com.atomikos + transactions-jdbc + ${atomikos-version} + + + com.atomikos + transactions-jms + ${atomikos-version} + + + com.atomikos + transactions-hibernate4 + ${atomikos-version} + + + org.springframework + spring-context + ${spring-version} + + + org.springframework + spring-tx + ${spring-version} + + + org.springframework.data + spring-data-jpa + 1.11.23.RELEASE + + + org.springframework + spring-test + ${spring-version} + test + + + org.hibernate + hibernate-entitymanager + ${hibernate.version} + provided + + + javax.transaction + jta + + + + + org.apache.activemq + activemq-core + 5.7.0 + + + org.apache.derby + derby + 10.8.1.2 + + + junit + junit + 4.12 + test + + + + javax.transaction + jta + 1.1 + + + org.apache.geronimo.specs + geronimo-jta_1.0.1B_spec + 1.0 + + + javax.validation + validation-api + 2.0.1.Final + + + org.hibernate.validator + hibernate-validator + 6.1.2.Final + + + javax.el + javax.el-api + 3.0.0 + + + org.glassfish.web + javax.el + 2.2.4 + + + + + 5.0.6 + 5.1.6.RELEASE + 5.4.3.Final + + + \ No newline at end of file diff --git a/atomikos/src/main/java/com/baeldung/atomikos/direct/Application.java b/atomikos/src/main/java/com/baeldung/atomikos/direct/Application.java new file mode 100644 index 0000000000..c51ce70dde --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/direct/Application.java @@ -0,0 +1,53 @@ +package com.baeldung.atomikos.direct; + +import java.sql.Connection; +import java.sql.Statement; +import java.util.UUID; + +import javax.sql.DataSource; + +import com.atomikos.icatch.jta.UserTransactionImp; + +public class Application { + + private DataSource inventoryDataSource; + private DataSource orderDataSource; + + public Application(DataSource inventoryDataSource, DataSource orderDataSource) { + this.inventoryDataSource = inventoryDataSource; + this.orderDataSource = orderDataSource; + } + + public void placeOrder(String productId, int amount) throws Exception { + + UserTransactionImp utx = new UserTransactionImp(); + String orderId = UUID.randomUUID() + .toString(); + boolean rollback = false; + try { + utx.begin(); + Connection inventoryConnection = inventoryDataSource.getConnection(); + Connection orderConnection = orderDataSource.getConnection(); + Statement s1 = inventoryConnection.createStatement(); + String q1 = "update Inventory set balance = balance - " + amount + " where productId ='" + productId + "'"; + s1.executeUpdate(q1); + s1.close(); + Statement s2 = orderConnection.createStatement(); + String q2 = "insert into Orders values ( '" + orderId + "', '" + productId + "', " + amount + " )"; + s2.executeUpdate(q2); + s2.close(); + inventoryConnection.close(); + orderConnection.close(); + } catch (Exception e) { + System.out.println(e.getMessage()); + rollback = true; + } finally { + if (!rollback) + utx.commit(); + else + utx.rollback(); + } + + } + +} diff --git a/atomikos/src/main/java/com/baeldung/atomikos/spring/Application.java b/atomikos/src/main/java/com/baeldung/atomikos/spring/Application.java new file mode 100644 index 0000000000..b480e68d8d --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/spring/Application.java @@ -0,0 +1,41 @@ +package com.baeldung.atomikos.spring; + +import java.sql.Connection; +import java.sql.Statement; +import java.util.UUID; + +import javax.sql.DataSource; + +import org.springframework.transaction.annotation.Transactional; + +public class Application { + + private DataSource inventoryDataSource; + private DataSource orderDataSource; + + public Application(DataSource inventoryDataSource, DataSource orderDataSource) { + this.inventoryDataSource = inventoryDataSource; + this.orderDataSource = orderDataSource; + } + + @Transactional(rollbackFor = Exception.class) + public void placeOrder(String productId, int amount) throws Exception { + + String orderId = UUID.randomUUID() + .toString(); + Connection inventoryConnection = inventoryDataSource.getConnection(); + Connection orderConnection = orderDataSource.getConnection(); + Statement s1 = inventoryConnection.createStatement(); + String q1 = "update Inventory set balance = balance - " + amount + " where productId ='" + productId + "'"; + s1.executeUpdate(q1); + s1.close(); + Statement s2 = orderConnection.createStatement(); + String q2 = "insert into Orders values ( '" + orderId + "', '" + productId + "', " + amount + " )"; + s2.executeUpdate(q2); + s2.close(); + inventoryConnection.close(); + orderConnection.close(); + + } + +} diff --git a/atomikos/src/main/java/com/baeldung/atomikos/spring/config/Config.java b/atomikos/src/main/java/com/baeldung/atomikos/spring/config/Config.java new file mode 100644 index 0000000000..c6ef83c4ca --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/spring/config/Config.java @@ -0,0 +1,68 @@ +package com.baeldung.atomikos.spring.config; + +import java.util.Properties; + +import javax.transaction.SystemException; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.transaction.jta.JtaTransactionManager; + +import com.atomikos.icatch.jta.UserTransactionManager; +import com.atomikos.jdbc.AtomikosDataSourceBean; +import com.baeldung.atomikos.spring.Application; + +@Configuration +@EnableTransactionManagement +public class Config { + + @Bean(initMethod = "init", destroyMethod = "close") + public AtomikosDataSourceBean inventoryDataSource() { + AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean(); + dataSource.setLocalTransactionMode(true); + dataSource.setUniqueResourceName("db1"); + dataSource.setXaDataSourceClassName("org.apache.derby.jdbc.EmbeddedXADataSource"); + Properties xaProperties = new Properties(); + xaProperties.put("databaseName", "db1"); + xaProperties.put("createDatabase", "create"); + dataSource.setXaProperties(xaProperties); + dataSource.setPoolSize(10); + return dataSource; + } + + @Bean(initMethod = "init", destroyMethod = "close") + public AtomikosDataSourceBean orderDataSource() { + AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean(); + dataSource.setLocalTransactionMode(true); + dataSource.setUniqueResourceName("db2"); + dataSource.setXaDataSourceClassName("org.apache.derby.jdbc.EmbeddedXADataSource"); + Properties xaProperties = new Properties(); + xaProperties.put("databaseName", "db2"); + xaProperties.put("createDatabase", "create"); + dataSource.setXaProperties(xaProperties); + dataSource.setPoolSize(10); + return dataSource; + } + + @Bean(initMethod = "init", destroyMethod = "close") + public UserTransactionManager userTransactionManager() throws SystemException { + UserTransactionManager userTransactionManager = new UserTransactionManager(); + userTransactionManager.setTransactionTimeout(300); + userTransactionManager.setForceShutdown(true); + return userTransactionManager; + } + + @Bean + public JtaTransactionManager jtaTransactionManager() throws SystemException { + JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(); + jtaTransactionManager.setTransactionManager(userTransactionManager()); + jtaTransactionManager.setUserTransaction(userTransactionManager()); + return jtaTransactionManager; + } + + @Bean + public Application application() { + return new Application(inventoryDataSource(), orderDataSource()); + } +} \ No newline at end of file diff --git a/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/Application.java b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/Application.java new file mode 100644 index 0000000000..cf1fef2cd8 --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/Application.java @@ -0,0 +1,48 @@ +package com.baeldung.atomikos.spring.jpa; + +import java.util.Set; +import java.util.UUID; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.atomikos.spring.jpa.inventory.Inventory; +import com.baeldung.atomikos.spring.jpa.inventory.InventoryRepository; +import com.baeldung.atomikos.spring.jpa.order.Order; +import com.baeldung.atomikos.spring.jpa.order.OrderRepository; + +public class Application { + + @Autowired + private InventoryRepository inventoryRepository; + + @Autowired + private OrderRepository orderRepository; + + @Transactional(rollbackFor = Exception.class) + public void placeOrder(String productId, int amount) throws Exception { + + String orderId = UUID.randomUUID() + .toString(); + Inventory inventory = inventoryRepository.findOne(productId); + inventory.setBalance(inventory.getBalance() - amount); + inventoryRepository.save(inventory); + Order order = new Order(); + order.setOrderId(orderId); + order.setProductId(productId); + order.setAmount(new Long(amount)); + ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); + Validator validator = factory.getValidator(); + Set> violations = validator.validate(order); + if (violations.size() > 0) + throw new Exception("Invalid instance of an order."); + orderRepository.save(order); + + } + +} diff --git a/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/config/Config.java b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/config/Config.java new file mode 100644 index 0000000000..6716f19576 --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/config/Config.java @@ -0,0 +1,38 @@ +package com.baeldung.atomikos.spring.jpa.config; + +import javax.transaction.SystemException; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.transaction.jta.JtaTransactionManager; + +import com.atomikos.icatch.jta.UserTransactionManager; +import com.baeldung.atomikos.spring.jpa.Application; + +@Configuration +@EnableTransactionManagement +public class Config { + + @Bean(initMethod = "init", destroyMethod = "close") + public UserTransactionManager userTransactionManager() throws SystemException { + UserTransactionManager userTransactionManager = new UserTransactionManager(); + userTransactionManager.setTransactionTimeout(300); + userTransactionManager.setForceShutdown(true); + return userTransactionManager; + } + + @Bean + public JtaTransactionManager transactionManager() throws SystemException { + JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(); + jtaTransactionManager.setTransactionManager(userTransactionManager()); + jtaTransactionManager.setUserTransaction(userTransactionManager()); + return jtaTransactionManager; + } + + @Bean + public Application application() { + return new Application(); + } + +} \ No newline at end of file diff --git a/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/Inventory.java b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/Inventory.java new file mode 100644 index 0000000000..999879218c --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/Inventory.java @@ -0,0 +1,31 @@ +package com.baeldung.atomikos.spring.jpa.inventory; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "INVENTORY") +public class Inventory { + + @Id + private String productId; + private Long balance; + + public String getProductId() { + return productId; + } + + public void setProductId(String productId) { + this.productId = productId; + } + + public Long getBalance() { + return balance; + } + + public void setBalance(Long balance) { + this.balance = balance; + } + +} diff --git a/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/InventoryConfig.java b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/InventoryConfig.java new file mode 100644 index 0000000000..5301ad6ff2 --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/InventoryConfig.java @@ -0,0 +1,53 @@ +package com.baeldung.atomikos.spring.jpa.inventory; + +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; + +import com.atomikos.jdbc.AtomikosDataSourceBean; + +@Configuration +@EnableJpaRepositories(basePackages = "com.baeldung.atomikos.spring.jpa.inventory", entityManagerFactoryRef = "inventoryEntityManager", transactionManagerRef = "transactionManager") +public class InventoryConfig { + + @Bean(initMethod = "init", destroyMethod = "close") + public AtomikosDataSourceBean inventoryDataSource() { + AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean(); + dataSource.setLocalTransactionMode(true); + dataSource.setUniqueResourceName("db1"); + dataSource.setXaDataSourceClassName("org.apache.derby.jdbc.EmbeddedXADataSource"); + Properties xaProperties = new Properties(); + xaProperties.put("databaseName", "db1"); + xaProperties.put("createDatabase", "create"); + dataSource.setXaProperties(xaProperties); + dataSource.setPoolSize(10); + return dataSource; + } + + @Bean + public EntityManagerFactory inventoryEntityManager() { + HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setJpaVendorAdapter(vendorAdapter); + factory.setPackagesToScan("com.baeldung.atomikos.spring.jpa.inventory"); + factory.setDataSource(inventoryDataSource()); + Properties jpaProperties = new Properties(); + //jpaProperties.put("hibernate.show_sql", "true"); + //jpaProperties.put("hibernate.format_sql", "true"); + jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.DerbyDialect"); + jpaProperties.put("hibernate.current_session_context_class", "jta"); + jpaProperties.put("javax.persistence.transactionType", "jta"); + jpaProperties.put("hibernate.transaction.manager_lookup_class", "com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup"); + jpaProperties.put("hibernate.hbm2ddl.auto", "create-drop"); + factory.setJpaProperties(jpaProperties); + factory.afterPropertiesSet(); + return factory.getObject(); + } + +} \ No newline at end of file diff --git a/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/InventoryRepository.java b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/InventoryRepository.java new file mode 100644 index 0000000000..c3868e51bf --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/inventory/InventoryRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.atomikos.spring.jpa.inventory; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface InventoryRepository extends JpaRepository { + +} diff --git a/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/Order.java b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/Order.java new file mode 100644 index 0000000000..4b9ae2dd1d --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/Order.java @@ -0,0 +1,42 @@ +package com.baeldung.atomikos.spring.jpa.order; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.validation.constraints.Max; + +@Entity +@Table(name = "ORDERS") +public class Order { + + @Id + private String orderId; + private String productId; + @Max(5) + private Long amount; + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + public String getProductId() { + return productId; + } + + public void setProductId(String productId) { + this.productId = productId; + } + + public Long getAmount() { + return amount; + } + + public void setAmount(Long amount) { + this.amount = amount; + } + +} diff --git a/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/OrderConfig.java b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/OrderConfig.java new file mode 100644 index 0000000000..b4274bb64c --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/OrderConfig.java @@ -0,0 +1,53 @@ +package com.baeldung.atomikos.spring.jpa.order; + +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; + +import com.atomikos.jdbc.AtomikosDataSourceBean; + +@Configuration +@EnableJpaRepositories(basePackages = "com.baeldung.atomikos.spring.jpa.order", entityManagerFactoryRef = "orderEntityManager", transactionManagerRef = "transactionManager") +public class OrderConfig { + + @Bean(initMethod = "init", destroyMethod = "close") + public AtomikosDataSourceBean orderDataSource() { + AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean(); + dataSource.setLocalTransactionMode(true); + dataSource.setUniqueResourceName("db2"); + dataSource.setXaDataSourceClassName("org.apache.derby.jdbc.EmbeddedXADataSource"); + Properties xaProperties = new Properties(); + xaProperties.put("databaseName", "db2"); + xaProperties.put("createDatabase", "create"); + dataSource.setXaProperties(xaProperties); + dataSource.setPoolSize(10); + return dataSource; + } + + @Bean + public EntityManagerFactory orderEntityManager() { + HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setJpaVendorAdapter(vendorAdapter); + factory.setPackagesToScan("com.baeldung.atomikos.spring.jpa.order"); + factory.setDataSource(orderDataSource()); + Properties jpaProperties = new Properties(); + //jpaProperties.put("hibernate.show_sql", "true"); + //jpaProperties.put("hibernate.format_sql", "true"); + jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.DerbyDialect"); + jpaProperties.put("hibernate.current_session_context_class", "jta"); + jpaProperties.put("javax.persistence.transactionType", "jta"); + jpaProperties.put("hibernate.transaction.manager_lookup_class", "com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup"); + jpaProperties.put("hibernate.hbm2ddl.auto", "create-drop"); + factory.setJpaProperties(jpaProperties); + factory.afterPropertiesSet(); + return factory.getObject(); + } + +} \ No newline at end of file diff --git a/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/OrderRepository.java b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/OrderRepository.java new file mode 100644 index 0000000000..2d5610ebca --- /dev/null +++ b/atomikos/src/main/java/com/baeldung/atomikos/spring/jpa/order/OrderRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.atomikos.spring.jpa.order; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface OrderRepository extends JpaRepository { + +} diff --git a/atomikos/src/main/resources/logback.xml b/atomikos/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/atomikos/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/atomikos/src/main/resources/schema.sql b/atomikos/src/main/resources/schema.sql new file mode 100644 index 0000000000..5136ad1284 --- /dev/null +++ b/atomikos/src/main/resources/schema.sql @@ -0,0 +1,10 @@ +CREATE TABLE INVENTORY ( + productId VARCHAR PRIMARY KEY, + balance INT +); + +CREATE TABLE ORDERS ( + orderId VARCHAR PRIMARY KEY, + productId VARCHAR, + amount INT NOT NULL CHECK (amount <= 5) +); \ No newline at end of file diff --git a/atomikos/src/main/resources/transactions.properties b/atomikos/src/main/resources/transactions.properties new file mode 100644 index 0000000000..8e027032fa --- /dev/null +++ b/atomikos/src/main/resources/transactions.properties @@ -0,0 +1 @@ +com.atomikos.icatch.file=logs \ No newline at end of file diff --git a/atomikos/src/test/java/com/baeldung/atomikos/direct/ApplicationUnitTest.java b/atomikos/src/test/java/com/baeldung/atomikos/direct/ApplicationUnitTest.java new file mode 100644 index 0000000000..1a467807ba --- /dev/null +++ b/atomikos/src/test/java/com/baeldung/atomikos/direct/ApplicationUnitTest.java @@ -0,0 +1,118 @@ +package com.baeldung.atomikos.direct; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; +import java.util.UUID; + +import javax.sql.DataSource; + +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import com.atomikos.icatch.jta.UserTransactionImp; +import com.atomikos.jdbc.AtomikosDataSourceBean; + +public class ApplicationUnitTest { + + private static DataSource inventoryDataSource; + private static DataSource orderDataSource; + + private static String productId = UUID.randomUUID() + .toString(); + + @Test + @Ignore + public void testPlaceOrderSuccess() throws Exception { + int amount = 1; + long initialBalance = getBalance(inventoryDataSource, productId); + Application application = new Application(inventoryDataSource, orderDataSource); + application.placeOrder(productId, amount); + long finalBalance = getBalance(inventoryDataSource, productId); + assertEquals(initialBalance - amount, finalBalance); + } + + @Test + @Ignore + public void testPlaceOrderFailure() throws Exception { + int amount = 10; + long initialBalance = getBalance(inventoryDataSource, productId); + Application application = new Application(inventoryDataSource, orderDataSource); + application.placeOrder(productId, amount); + long finalBalance = getBalance(inventoryDataSource, productId); + assertEquals(initialBalance, finalBalance); + } + + @BeforeClass + public static void setUp() throws SQLException { + + inventoryDataSource = getDataSource("db1"); + orderDataSource = getDataSource("db2"); + Connection inventoryConnection = inventoryDataSource.getConnection(); + Connection orderConnection = orderDataSource.getConnection(); + String createInventoryTable = "create table Inventory ( " + " productId VARCHAR ( 100 ) PRIMARY KEY, balance INT )"; + String createInventoryRow = "insert into Inventory values ( '" + productId + "', 10000 )"; + Statement s1 = inventoryConnection.createStatement(); + try { + s1.executeUpdate(createInventoryTable); + } catch (Exception e) { + System.out.println("Inventory table exists"); + } + try { + s1.executeUpdate(createInventoryRow); + } catch (Exception e) { + System.out.println("Product row exists"); + } + s1.close(); + String createOrderTable = "create table Orders ( orderId VARCHAR ( 100 ) PRIMARY KEY, productId VARCHAR ( 100 ), amount INT NOT NULL CHECK (amount <= 5) )"; + Statement s2 = orderConnection.createStatement(); + try { + s2.executeUpdate(createOrderTable); + } catch (Exception e) { + System.out.println("Orders table exists"); + } + s2.close(); + inventoryConnection.close(); + orderConnection.close(); + } + + private static DataSource getDataSource(String db) { + + DataSource ds; + AtomikosDataSourceBean ads = new AtomikosDataSourceBean(); + ads.setXaDataSourceClassName("org.apache.derby.jdbc.EmbeddedXADataSource"); + Properties properties = new Properties(); + properties.put("databaseName", db); + properties.put("createDatabase", "create"); + ads.setXaProperties(properties); + ads.setUniqueResourceName(db); + ads.setPoolSize(10); // optional + ads.setBorrowConnectionTimeout(10); // optional + ds = ads; + return ds; + + } + + private static long getBalance(DataSource inventoryDataSource, String productId) throws Exception { + + UserTransactionImp utx = new UserTransactionImp(); + utx.begin(); + Connection inventoryConnection = inventoryDataSource.getConnection(); + Statement s1 = inventoryConnection.createStatement(); + String q1 = "select balance from Inventory where productId='" + productId + "'"; + ResultSet rs1 = s1.executeQuery(q1); + if (rs1 == null || !rs1.next()) + throw new Exception("Product not found: " + productId); + long balance = rs1.getLong(1); + inventoryConnection.close(); + utx.commit(); + return balance; + + } + +} diff --git a/atomikos/src/test/java/com/baeldung/atomikos/spring/ApplicationUnitTest.java b/atomikos/src/test/java/com/baeldung/atomikos/spring/ApplicationUnitTest.java new file mode 100644 index 0000000000..0c9392eac4 --- /dev/null +++ b/atomikos/src/test/java/com/baeldung/atomikos/spring/ApplicationUnitTest.java @@ -0,0 +1,108 @@ +package com.baeldung.atomikos.spring; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.UUID; + +import javax.sql.DataSource; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.atomikos.spring.config.Config; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { Config.class }) +public class ApplicationUnitTest { + + private static String productId = UUID.randomUUID() + .toString(); + + @Autowired + Application application; + + @Autowired + DataSource inventoryDataSource; + + @Autowired + DataSource orderDataSource; + + @Test + @Ignore + public void testPlaceOrderSuccess() throws Exception { + int amount = 1; + long initialBalance = getBalance(inventoryDataSource, productId); + application.placeOrder(productId, amount); + long finalBalance = getBalance(inventoryDataSource, productId); + assertEquals(initialBalance - amount, finalBalance); + } + + @Test + @Ignore + public void testPlaceOrderFailure() throws Exception { + int amount = 10; + long initialBalance = getBalance(inventoryDataSource, productId); + try { + application.placeOrder(productId, amount); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + long finalBalance = getBalance(inventoryDataSource, productId); + assertEquals(initialBalance, finalBalance); + } + + @Before + public void setUp() throws SQLException { + + Connection inventoryConnection = inventoryDataSource.getConnection(); + Connection orderConnection = orderDataSource.getConnection(); + String createInventoryTable = "create table Inventory ( " + " productId VARCHAR ( 100 ) PRIMARY KEY, balance INT )"; + String createInventoryRow = "insert into Inventory values ( '" + productId + "', 10000 )"; + Statement s1 = inventoryConnection.createStatement(); + try { + s1.executeUpdate(createInventoryTable); + } catch (Exception e) { + System.out.println("Inventory table exists"); + } + try { + s1.executeUpdate(createInventoryRow); + } catch (Exception e) { + System.out.println("Product row exists"); + } + s1.close(); + String createOrderTable = "create table Orders ( orderId VARCHAR ( 100 ) PRIMARY KEY, productId VARCHAR ( 100 ), amount INT NOT NULL CHECK (amount <= 5) )"; + Statement s2 = orderConnection.createStatement(); + try { + s2.executeUpdate(createOrderTable); + } catch (Exception e) { + System.out.println("Orders table exists"); + } + s2.close(); + inventoryConnection.close(); + orderConnection.close(); + } + + private static long getBalance(DataSource inventoryDataSource, String productId) throws Exception { + + Connection inventoryConnection = inventoryDataSource.getConnection(); + Statement s1 = inventoryConnection.createStatement(); + String q1 = "select balance from Inventory where productId='" + productId + "'"; + ResultSet rs1 = s1.executeQuery(q1); + if (rs1 == null || !rs1.next()) + throw new Exception("Product not found: " + productId); + long balance = rs1.getLong(1); + inventoryConnection.close(); + return balance; + + } + +} diff --git a/atomikos/src/test/java/com/baeldung/atomikos/spring/jpa/ApplicationUnitTest.java b/atomikos/src/test/java/com/baeldung/atomikos/spring/jpa/ApplicationUnitTest.java new file mode 100644 index 0000000000..e6a3c1982c --- /dev/null +++ b/atomikos/src/test/java/com/baeldung/atomikos/spring/jpa/ApplicationUnitTest.java @@ -0,0 +1,80 @@ +package com.baeldung.atomikos.spring.jpa; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.sql.SQLException; +import java.util.UUID; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.atomikos.spring.jpa.config.Config; +import com.baeldung.atomikos.spring.jpa.inventory.Inventory; +import com.baeldung.atomikos.spring.jpa.inventory.InventoryConfig; +import com.baeldung.atomikos.spring.jpa.inventory.InventoryRepository; +import com.baeldung.atomikos.spring.jpa.order.OrderConfig; +import com.baeldung.atomikos.spring.jpa.order.OrderRepository; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { Config.class, InventoryConfig.class, OrderConfig.class }) +public class ApplicationUnitTest { + + private static String productId = UUID.randomUUID() + .toString(); + + @Autowired + Application application; + + @Autowired + InventoryRepository inventoryRepository; + + @Autowired + OrderRepository orderRepository; + + @Test + @Ignore + public void testPlaceOrderSuccess() throws Exception { + int amount = 1; + long initialBalance = getBalance(inventoryRepository, productId); + application.placeOrder(productId, amount); + long finalBalance = getBalance(inventoryRepository, productId); + assertEquals(initialBalance - amount, finalBalance); + } + + @Test + @Ignore + public void testPlaceOrderFailure() throws Exception { + int amount = 10; + long initialBalance = getBalance(inventoryRepository, productId); + try { + application.placeOrder(productId, amount); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + long finalBalance = getBalance(inventoryRepository, productId); + assertEquals(initialBalance, finalBalance); + } + + @Before + public void setUp() throws SQLException { + + Inventory inventory = new Inventory(); + inventory.setProductId(productId); + inventory.setBalance(new Long(10000)); + inventoryRepository.save(inventory); + + } + + private static long getBalance(InventoryRepository inventoryRepository, String productId) throws Exception { + + return inventoryRepository.findOne(productId) + .getBalance(); + + } + +} diff --git a/atomikos/src/test/resources/logback.xml b/atomikos/src/test/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/atomikos/src/test/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/atomikos/src/test/resources/transactions.properties b/atomikos/src/test/resources/transactions.properties new file mode 100644 index 0000000000..8e027032fa --- /dev/null +++ b/atomikos/src/test/resources/transactions.properties @@ -0,0 +1 @@ +com.atomikos.icatch.file=logs \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8d4632fb3e..8a8b8e1b55 100644 --- a/pom.xml +++ b/pom.xml @@ -564,6 +564,8 @@ rxjava-libraries rxjava-observables rxjava-operators + + atomikos @@ -1073,6 +1075,8 @@ rxjava-libraries rxjava-observables rxjava-operators + + atomikos From 40f2f2ea8a431fa6e675ce6d31900f515ea55e31 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Thu, 26 Mar 2020 12:29:05 +0200 Subject: [PATCH 109/194] BAEL-3926 - Java Map with case-insensitive keys --- .../core-java-collections-maps/pom.xml | 7 ++++ .../map/CaseInsensitiveMapUnitTest.java | 37 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java diff --git a/core-java-modules/core-java-collections-maps/pom.xml b/core-java-modules/core-java-collections-maps/pom.xml index c0dd705c1c..b459213e17 100644 --- a/core-java-modules/core-java-collections-maps/pom.xml +++ b/core-java-modules/core-java-collections-maps/pom.xml @@ -26,10 +26,17 @@ ${assertj.version} test + + org.springframework + spring-core + ${spring.version} + test + 4.1 3.6.1 + 5.2.5.RELEASE diff --git a/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java new file mode 100644 index 0000000000..a2171aa326 --- /dev/null +++ b/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.map; + +import org.apache.commons.collections4.map.CaseInsensitiveMap; +import org.junit.Test; +import org.springframework.util.LinkedCaseInsensitiveMap; +import static org.junit.Assert.*; + +import java.util.TreeMap; + +public class CaseInsensitiveMapUnitTest { + @Test + public void givenCaseInsensitiveTreeMap_whenTwoEntriesAdded_thenSizeIsOne(){ + TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + treeMap.put("abc", 1); + treeMap.put("ABC", 2); + + assertEquals(treeMap.size(), 1); + } + + @Test + public void givenCommonsCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ + CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + commonsHashMap.put("abc", 1); + commonsHashMap.put("ABC", 2); + + assertEquals(commonsHashMap.get("aBc"), (Integer)2); + } + + @Test + public void givenLinkedCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ + LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + linkedHashMap.put("abc", 3); + linkedHashMap.remove("aBC"); + + assertEquals(linkedHashMap.size(), 0); + } +} From 7d9d3c5f607260be7a466600bb09b9926a252770 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Sat, 28 Mar 2020 17:50:20 +0300 Subject: [PATCH 110/194] new module has been added --- .../core-java-collections-maps/pom.xml | 7 ---- java-collections-maps-3/README.md | 8 ++++ java-collections-maps-3/pom.xml | 39 +++++++++++++++++++ .../CaseInsensitiveMapUnitTest.java | 7 ++-- pom.xml | 10 ++++- 5 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 java-collections-maps-3/README.md create mode 100644 java-collections-maps-3/pom.xml rename {java-collections-maps/src/test/java/com/baeldung/map => java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys}/CaseInsensitiveMapUnitTest.java (84%) diff --git a/core-java-modules/core-java-collections-maps/pom.xml b/core-java-modules/core-java-collections-maps/pom.xml index b459213e17..c0dd705c1c 100644 --- a/core-java-modules/core-java-collections-maps/pom.xml +++ b/core-java-modules/core-java-collections-maps/pom.xml @@ -26,17 +26,10 @@ ${assertj.version} test - - org.springframework - spring-core - ${spring.version} - test - 4.1 3.6.1 - 5.2.5.RELEASE diff --git a/java-collections-maps-3/README.md b/java-collections-maps-3/README.md new file mode 100644 index 0000000000..9df666296b --- /dev/null +++ b/java-collections-maps-3/README.md @@ -0,0 +1,8 @@ +## Java Collections Cookbooks and Examples + +This module contains articles about Map data structures in Java. + +### Relevant Articles: +- [Java Map With Case-Insensitive Keys](https://www.baeldung.com/java-map-case-insensitive-keys) +- More articles: [[<-- prev>]](/../java-collections-maps) +- More articles: [[<-- prev>]](/../java-collections-maps-2) diff --git a/java-collections-maps-3/pom.xml b/java-collections-maps-3/pom.xml new file mode 100644 index 0000000000..0dd915c87b --- /dev/null +++ b/java-collections-maps-3/pom.xml @@ -0,0 +1,39 @@ + + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + 4.0.0 + java-collections-maps-3 + + + + org.springframework + spring-core + ${spring.version} + test + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + + + 4.1 + 3.6.1 + 5.2.5.RELEASE + + \ No newline at end of file diff --git a/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java similarity index 84% rename from java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java rename to java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index a2171aa326..b12080e368 100644 --- a/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -1,6 +1,7 @@ -package com.baeldung.map; +package com.baeldung.map.caseinsensitivekeys; import org.apache.commons.collections4.map.CaseInsensitiveMap; +import org.junit.Assert; import org.junit.Test; import org.springframework.util.LinkedCaseInsensitiveMap; import static org.junit.Assert.*; @@ -23,7 +24,7 @@ public class CaseInsensitiveMapUnitTest { commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2); - assertEquals(commonsHashMap.get("aBc"), (Integer)2); + Assert.assertEquals(commonsHashMap.get("aBc"), (Integer)2); } @Test @@ -32,6 +33,6 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("abc", 3); linkedHashMap.remove("aBC"); - assertEquals(linkedHashMap.size(), 0); + Assert.assertEquals(linkedHashMap.size(), 0); } } diff --git a/pom.xml b/pom.xml index 8a8b8e1b55..cb0c0cf5d7 100644 --- a/pom.xml +++ b/pom.xml @@ -453,6 +453,9 @@ java-collections-conversions java-collections-conversions-2 + java-collections-maps + java-collections-maps-2 + java-collections-maps-3 javafx @@ -564,7 +567,7 @@ rxjava-libraries rxjava-observables rxjava-operators - + atomikos @@ -965,6 +968,9 @@ java-collections-conversions java-collections-conversions-2 + java-collections-maps + java-collections-maps-2 + java-collections-maps-3 javafx @@ -1075,7 +1081,7 @@ rxjava-libraries rxjava-observables rxjava-operators - + atomikos From 5137f8fa209d1a0c2f8847017cb959e0a6db69b1 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Sat, 28 Mar 2020 17:58:34 +0300 Subject: [PATCH 111/194] tests has been added and split --- .../CaseInsensitiveMapUnitTest.java | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index b12080e368..b3653a97c2 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -15,7 +15,37 @@ public class CaseInsensitiveMapUnitTest { treeMap.put("abc", 1); treeMap.put("ABC", 2); - assertEquals(treeMap.size(), 1); + assertEquals(1, treeMap.size()); + + } + + @Test + public void givenCommonsCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ + CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + commonsHashMap.put("abc", 1); + commonsHashMap.put("ABC", 2); + + assertEquals(1, commonsHashMap.size()); + + } + + @Test + public void givenLinkedCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ + LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + linkedHashMap.put("abc", 1); + linkedHashMap.put("ABC", 2); + + assertEquals(1, linkedHashMap.size()); + + } + + @Test + public void givenCaseInsensitiveTreeMap_whenSameEntryAdded_thenValueUpdated(){ + TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + treeMap.put("abc", 1); + treeMap.put("ABC", 2); + + Assert.assertEquals((Integer)2, treeMap.get("aBc")); } @Test @@ -24,7 +54,34 @@ public class CaseInsensitiveMapUnitTest { commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2); - Assert.assertEquals(commonsHashMap.get("aBc"), (Integer)2); + Assert.assertEquals((Integer)2, commonsHashMap.get("aBc")); + } + + @Test + public void givenLinkedCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ + LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + linkedHashMap.put("abc", 1); + linkedHashMap.put("ABC", 2); + + Assert.assertEquals((Integer)2, linkedHashMap.get("aBc")); + } + + @Test + public void givenCaseInsensitiveTreeMap_whenEntryRemoved_thenSizeIsZero(){ + TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + treeMap.put("abc", 3); + treeMap.remove("aBC"); + + Assert.assertEquals(0, treeMap.size()); + } + + @Test + public void givenCommonsCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ + CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + commonsHashMap.put("abc", 3); + commonsHashMap.remove("aBC"); + + Assert.assertEquals(0, commonsHashMap.size()); } @Test @@ -33,6 +90,6 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("abc", 3); linkedHashMap.remove("aBC"); - Assert.assertEquals(linkedHashMap.size(), 0); + Assert.assertEquals(0, linkedHashMap.size()); } } From 9fc999311cdc4fa83b733631a4213b48728cb9d7 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Sat, 28 Mar 2020 22:41:07 +0300 Subject: [PATCH 112/194] tests has been added and split --- java-collections-maps-3/README.md | 2 +- .../CaseInsensitiveMapUnitTest.java | 29 +++++++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/java-collections-maps-3/README.md b/java-collections-maps-3/README.md index 9df666296b..ab6a37d00c 100644 --- a/java-collections-maps-3/README.md +++ b/java-collections-maps-3/README.md @@ -3,6 +3,6 @@ This module contains articles about Map data structures in Java. ### Relevant Articles: -- [Java Map With Case-Insensitive Keys](https://www.baeldung.com/java-map-case-insensitive-keys) +- [Java Map With Case-Insensitive Keys](https://www.baeldung.com/java-map-with-case-insensitive-keys/) - More articles: [[<-- prev>]](/../java-collections-maps) - More articles: [[<-- prev>]](/../java-collections-maps-2) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index b3653a97c2..82feef869a 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -1,17 +1,16 @@ package com.baeldung.map.caseinsensitivekeys; import org.apache.commons.collections4.map.CaseInsensitiveMap; -import org.junit.Assert; import org.junit.Test; import org.springframework.util.LinkedCaseInsensitiveMap; -import static org.junit.Assert.*; - +import java.util.Map; import java.util.TreeMap; +import static org.junit.Assert.*; public class CaseInsensitiveMapUnitTest { @Test public void givenCaseInsensitiveTreeMap_whenTwoEntriesAdded_thenSizeIsOne(){ - TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); treeMap.put("abc", 1); treeMap.put("ABC", 2); @@ -21,7 +20,7 @@ public class CaseInsensitiveMapUnitTest { @Test public void givenCommonsCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ - CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + Map commonsHashMap = new CaseInsensitiveMap<>(); commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2); @@ -41,20 +40,20 @@ public class CaseInsensitiveMapUnitTest { @Test public void givenCaseInsensitiveTreeMap_whenSameEntryAdded_thenValueUpdated(){ - TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); treeMap.put("abc", 1); treeMap.put("ABC", 2); - Assert.assertEquals((Integer)2, treeMap.get("aBc")); + assertEquals((Integer)2, treeMap.get("aBc")); } @Test public void givenCommonsCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ - CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + Map commonsHashMap = new CaseInsensitiveMap<>(); commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2); - Assert.assertEquals((Integer)2, commonsHashMap.get("aBc")); + assertEquals((Integer)2, commonsHashMap.get("aBc")); } @Test @@ -63,25 +62,25 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("abc", 1); linkedHashMap.put("ABC", 2); - Assert.assertEquals((Integer)2, linkedHashMap.get("aBc")); + assertEquals((Integer)2, linkedHashMap.get("aBc")); } @Test public void givenCaseInsensitiveTreeMap_whenEntryRemoved_thenSizeIsZero(){ - TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); treeMap.put("abc", 3); treeMap.remove("aBC"); - Assert.assertEquals(0, treeMap.size()); + assertEquals(0, treeMap.size()); } @Test public void givenCommonsCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ - CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + Map commonsHashMap = new CaseInsensitiveMap<>(); commonsHashMap.put("abc", 3); commonsHashMap.remove("aBC"); - Assert.assertEquals(0, commonsHashMap.size()); + assertEquals(0, commonsHashMap.size()); } @Test @@ -90,6 +89,6 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("abc", 3); linkedHashMap.remove("aBC"); - Assert.assertEquals(0, linkedHashMap.size()); + assertEquals(0, linkedHashMap.size()); } } From 640f8ce5d28cc78265d13e2f957895e36c7a719c Mon Sep 17 00:00:00 2001 From: omerfinger Date: Sat, 28 Mar 2020 22:50:07 +0300 Subject: [PATCH 113/194] varius get cases --- .../map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index 82feef869a..60dd1da9c0 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -45,6 +45,7 @@ public class CaseInsensitiveMapUnitTest { treeMap.put("ABC", 2); assertEquals((Integer)2, treeMap.get("aBc")); + assertEquals((Integer)2, treeMap.get("ABc")); } @Test @@ -54,6 +55,7 @@ public class CaseInsensitiveMapUnitTest { commonsHashMap.put("ABC", 2); assertEquals((Integer)2, commonsHashMap.get("aBc")); + assertEquals((Integer)2, commonsHashMap.get("ABc")); } @Test @@ -63,6 +65,7 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("ABC", 2); assertEquals((Integer)2, linkedHashMap.get("aBc")); + assertEquals((Integer)2, linkedHashMap.get("ABc")); } @Test From c2e37ce399ab221298a7914275a146c8ce23fb68 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Mon, 30 Mar 2020 13:28:29 +0300 Subject: [PATCH 114/194] changed README, assert has changed --- java-collections-maps-3/README.md | 2 +- .../CaseInsensitiveMapUnitTest.java | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/java-collections-maps-3/README.md b/java-collections-maps-3/README.md index ab6a37d00c..ed68eb00a0 100644 --- a/java-collections-maps-3/README.md +++ b/java-collections-maps-3/README.md @@ -3,6 +3,6 @@ This module contains articles about Map data structures in Java. ### Relevant Articles: -- [Java Map With Case-Insensitive Keys](https://www.baeldung.com/java-map-with-case-insensitive-keys/) + - More articles: [[<-- prev>]](/../java-collections-maps) - More articles: [[<-- prev>]](/../java-collections-maps-2) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index 60dd1da9c0..37d9af7535 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -25,7 +25,6 @@ public class CaseInsensitiveMapUnitTest { commonsHashMap.put("ABC", 2); assertEquals(1, commonsHashMap.size()); - } @Test @@ -35,7 +34,6 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("ABC", 2); assertEquals(1, linkedHashMap.size()); - } @Test @@ -44,8 +42,8 @@ public class CaseInsensitiveMapUnitTest { treeMap.put("abc", 1); treeMap.put("ABC", 2); - assertEquals((Integer)2, treeMap.get("aBc")); - assertEquals((Integer)2, treeMap.get("ABc")); + assertEquals(2, treeMap.get("aBc").intValue()); + assertEquals(2, treeMap.get("ABc").intValue()); } @Test @@ -54,8 +52,8 @@ public class CaseInsensitiveMapUnitTest { commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2); - assertEquals((Integer)2, commonsHashMap.get("aBc")); - assertEquals((Integer)2, commonsHashMap.get("ABc")); + assertEquals(2, commonsHashMap.get("aBc").intValue()); + assertEquals(2, commonsHashMap.get("ABc").intValue()); } @Test @@ -64,8 +62,8 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("abc", 1); linkedHashMap.put("ABC", 2); - assertEquals((Integer)2, linkedHashMap.get("aBc")); - assertEquals((Integer)2, linkedHashMap.get("ABc")); + assertEquals(2, linkedHashMap.get("aBc").intValue()); + assertEquals(2, linkedHashMap.get("ABc").intValue()); } @Test From 46843866bd569096bed78d1d261a82363ada9ff2 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Thu, 2 Apr 2020 10:06:43 +0300 Subject: [PATCH 115/194] changed LinkedHashMap to Map interface --- .../map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index 37d9af7535..c64738a266 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -29,7 +29,7 @@ public class CaseInsensitiveMapUnitTest { @Test public void givenLinkedCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ - LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + Map linkedHashMap = new LinkedCaseInsensitiveMap<>(); linkedHashMap.put("abc", 1); linkedHashMap.put("ABC", 2); @@ -58,7 +58,7 @@ public class CaseInsensitiveMapUnitTest { @Test public void givenLinkedCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ - LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + Map linkedHashMap = new LinkedCaseInsensitiveMap<>(); linkedHashMap.put("abc", 1); linkedHashMap.put("ABC", 2); @@ -86,7 +86,7 @@ public class CaseInsensitiveMapUnitTest { @Test public void givenLinkedCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ - LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + Map linkedHashMap = new LinkedCaseInsensitiveMap<>(); linkedHashMap.put("abc", 3); linkedHashMap.remove("aBC"); From 73892202d1aacee43417e413ba14a1ba3b90b67b Mon Sep 17 00:00:00 2001 From: omerfinger Date: Thu, 2 Apr 2020 12:18:03 +0300 Subject: [PATCH 116/194] changed LinkedHashMap to Map interface --- .../map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index c64738a266..833807c692 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -15,7 +15,6 @@ public class CaseInsensitiveMapUnitTest { treeMap.put("ABC", 2); assertEquals(1, treeMap.size()); - } @Test From db989e2322d3214326c3b5b316d566e0260175bb Mon Sep 17 00:00:00 2001 From: omerfinger <43134354+omerfinger@users.noreply.github.com> Date: Wed, 8 Apr 2020 12:12:26 +0300 Subject: [PATCH 117/194] Revert to original pom settings --- java-collections-maps-3/pom.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/java-collections-maps-3/pom.xml b/java-collections-maps-3/pom.xml index 0dd915c87b..a397eaa033 100644 --- a/java-collections-maps-3/pom.xml +++ b/java-collections-maps-3/pom.xml @@ -8,9 +8,13 @@ 0.0.1-SNAPSHOT ../parent-java + 4.0.0 java-collections-maps-3 - + 0.1.0-SNAPSHOT + java-collections-maps-3 + jar + org.springframework @@ -36,4 +40,4 @@ 3.6.1 5.2.5.RELEASE - \ No newline at end of file + From 0b2e7e9f7c7089329e783fe3e096fe74cfe4767c Mon Sep 17 00:00:00 2001 From: omerfinger Date: Thu, 26 Mar 2020 12:29:05 +0200 Subject: [PATCH 118/194] BAEL-3926 - Java Map with case-insensitive keys --- .../core-java-collections-maps/pom.xml | 7 ++++ .../map/CaseInsensitiveMapUnitTest.java | 37 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java diff --git a/core-java-modules/core-java-collections-maps/pom.xml b/core-java-modules/core-java-collections-maps/pom.xml index c0dd705c1c..b459213e17 100644 --- a/core-java-modules/core-java-collections-maps/pom.xml +++ b/core-java-modules/core-java-collections-maps/pom.xml @@ -26,10 +26,17 @@ ${assertj.version} test + + org.springframework + spring-core + ${spring.version} + test + 4.1 3.6.1 + 5.2.5.RELEASE diff --git a/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java new file mode 100644 index 0000000000..a2171aa326 --- /dev/null +++ b/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.map; + +import org.apache.commons.collections4.map.CaseInsensitiveMap; +import org.junit.Test; +import org.springframework.util.LinkedCaseInsensitiveMap; +import static org.junit.Assert.*; + +import java.util.TreeMap; + +public class CaseInsensitiveMapUnitTest { + @Test + public void givenCaseInsensitiveTreeMap_whenTwoEntriesAdded_thenSizeIsOne(){ + TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + treeMap.put("abc", 1); + treeMap.put("ABC", 2); + + assertEquals(treeMap.size(), 1); + } + + @Test + public void givenCommonsCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ + CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + commonsHashMap.put("abc", 1); + commonsHashMap.put("ABC", 2); + + assertEquals(commonsHashMap.get("aBc"), (Integer)2); + } + + @Test + public void givenLinkedCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ + LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + linkedHashMap.put("abc", 3); + linkedHashMap.remove("aBC"); + + assertEquals(linkedHashMap.size(), 0); + } +} From b2bc2dc00408c6d1fd223e73258f03a5aac4d5cf Mon Sep 17 00:00:00 2001 From: omerfinger Date: Sat, 28 Mar 2020 17:50:20 +0300 Subject: [PATCH 119/194] new module has been added --- .../core-java-collections-maps/pom.xml | 7 -- java-collections-maps-3/pom.xml | 4 +- .../CaseInsensitiveMapUnitTest.java | 74 +++---------------- .../map/CaseInsensitiveMapUnitTest.java | 37 ---------- 4 files changed, 11 insertions(+), 111 deletions(-) delete mode 100644 java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java diff --git a/core-java-modules/core-java-collections-maps/pom.xml b/core-java-modules/core-java-collections-maps/pom.xml index b459213e17..c0dd705c1c 100644 --- a/core-java-modules/core-java-collections-maps/pom.xml +++ b/core-java-modules/core-java-collections-maps/pom.xml @@ -26,17 +26,10 @@ ${assertj.version} test - - org.springframework - spring-core - ${spring.version} - test - 4.1 3.6.1 - 5.2.5.RELEASE diff --git a/java-collections-maps-3/pom.xml b/java-collections-maps-3/pom.xml index a397eaa033..3888623a7f 100644 --- a/java-collections-maps-3/pom.xml +++ b/java-collections-maps-3/pom.xml @@ -8,13 +8,13 @@ 0.0.1-SNAPSHOT ../parent-java - + 4.0.0 java-collections-maps-3 0.1.0-SNAPSHOT java-collections-maps-3 jar - + org.springframework diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index 833807c692..b12080e368 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -1,94 +1,38 @@ package com.baeldung.map.caseinsensitivekeys; import org.apache.commons.collections4.map.CaseInsensitiveMap; +import org.junit.Assert; import org.junit.Test; import org.springframework.util.LinkedCaseInsensitiveMap; -import java.util.Map; -import java.util.TreeMap; import static org.junit.Assert.*; +import java.util.TreeMap; + public class CaseInsensitiveMapUnitTest { @Test public void givenCaseInsensitiveTreeMap_whenTwoEntriesAdded_thenSizeIsOne(){ - Map treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); treeMap.put("abc", 1); treeMap.put("ABC", 2); - assertEquals(1, treeMap.size()); - } - - @Test - public void givenCommonsCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ - Map commonsHashMap = new CaseInsensitiveMap<>(); - commonsHashMap.put("abc", 1); - commonsHashMap.put("ABC", 2); - - assertEquals(1, commonsHashMap.size()); - } - - @Test - public void givenLinkedCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ - Map linkedHashMap = new LinkedCaseInsensitiveMap<>(); - linkedHashMap.put("abc", 1); - linkedHashMap.put("ABC", 2); - - assertEquals(1, linkedHashMap.size()); - } - - @Test - public void givenCaseInsensitiveTreeMap_whenSameEntryAdded_thenValueUpdated(){ - Map treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - treeMap.put("abc", 1); - treeMap.put("ABC", 2); - - assertEquals(2, treeMap.get("aBc").intValue()); - assertEquals(2, treeMap.get("ABc").intValue()); + assertEquals(treeMap.size(), 1); } @Test public void givenCommonsCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ - Map commonsHashMap = new CaseInsensitiveMap<>(); + CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2); - assertEquals(2, commonsHashMap.get("aBc").intValue()); - assertEquals(2, commonsHashMap.get("ABc").intValue()); - } - - @Test - public void givenLinkedCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ - Map linkedHashMap = new LinkedCaseInsensitiveMap<>(); - linkedHashMap.put("abc", 1); - linkedHashMap.put("ABC", 2); - - assertEquals(2, linkedHashMap.get("aBc").intValue()); - assertEquals(2, linkedHashMap.get("ABc").intValue()); - } - - @Test - public void givenCaseInsensitiveTreeMap_whenEntryRemoved_thenSizeIsZero(){ - Map treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - treeMap.put("abc", 3); - treeMap.remove("aBC"); - - assertEquals(0, treeMap.size()); - } - - @Test - public void givenCommonsCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ - Map commonsHashMap = new CaseInsensitiveMap<>(); - commonsHashMap.put("abc", 3); - commonsHashMap.remove("aBC"); - - assertEquals(0, commonsHashMap.size()); + Assert.assertEquals(commonsHashMap.get("aBc"), (Integer)2); } @Test public void givenLinkedCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ - Map linkedHashMap = new LinkedCaseInsensitiveMap<>(); + LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); linkedHashMap.put("abc", 3); linkedHashMap.remove("aBC"); - assertEquals(0, linkedHashMap.size()); + Assert.assertEquals(linkedHashMap.size(), 0); } } diff --git a/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java deleted file mode 100644 index a2171aa326..0000000000 --- a/java-collections-maps/src/test/java/com/baeldung/map/CaseInsensitiveMapUnitTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.baeldung.map; - -import org.apache.commons.collections4.map.CaseInsensitiveMap; -import org.junit.Test; -import org.springframework.util.LinkedCaseInsensitiveMap; -import static org.junit.Assert.*; - -import java.util.TreeMap; - -public class CaseInsensitiveMapUnitTest { - @Test - public void givenCaseInsensitiveTreeMap_whenTwoEntriesAdded_thenSizeIsOne(){ - TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - treeMap.put("abc", 1); - treeMap.put("ABC", 2); - - assertEquals(treeMap.size(), 1); - } - - @Test - public void givenCommonsCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ - CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); - commonsHashMap.put("abc", 1); - commonsHashMap.put("ABC", 2); - - assertEquals(commonsHashMap.get("aBc"), (Integer)2); - } - - @Test - public void givenLinkedCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ - LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); - linkedHashMap.put("abc", 3); - linkedHashMap.remove("aBC"); - - assertEquals(linkedHashMap.size(), 0); - } -} From da97125e2068af38e4e3dd53ba196a644b195aa4 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Sat, 28 Mar 2020 17:58:34 +0300 Subject: [PATCH 120/194] tests has been added and split --- .../CaseInsensitiveMapUnitTest.java | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index b12080e368..b3653a97c2 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -15,7 +15,37 @@ public class CaseInsensitiveMapUnitTest { treeMap.put("abc", 1); treeMap.put("ABC", 2); - assertEquals(treeMap.size(), 1); + assertEquals(1, treeMap.size()); + + } + + @Test + public void givenCommonsCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ + CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + commonsHashMap.put("abc", 1); + commonsHashMap.put("ABC", 2); + + assertEquals(1, commonsHashMap.size()); + + } + + @Test + public void givenLinkedCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ + LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + linkedHashMap.put("abc", 1); + linkedHashMap.put("ABC", 2); + + assertEquals(1, linkedHashMap.size()); + + } + + @Test + public void givenCaseInsensitiveTreeMap_whenSameEntryAdded_thenValueUpdated(){ + TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + treeMap.put("abc", 1); + treeMap.put("ABC", 2); + + Assert.assertEquals((Integer)2, treeMap.get("aBc")); } @Test @@ -24,7 +54,34 @@ public class CaseInsensitiveMapUnitTest { commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2); - Assert.assertEquals(commonsHashMap.get("aBc"), (Integer)2); + Assert.assertEquals((Integer)2, commonsHashMap.get("aBc")); + } + + @Test + public void givenLinkedCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ + LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + linkedHashMap.put("abc", 1); + linkedHashMap.put("ABC", 2); + + Assert.assertEquals((Integer)2, linkedHashMap.get("aBc")); + } + + @Test + public void givenCaseInsensitiveTreeMap_whenEntryRemoved_thenSizeIsZero(){ + TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + treeMap.put("abc", 3); + treeMap.remove("aBC"); + + Assert.assertEquals(0, treeMap.size()); + } + + @Test + public void givenCommonsCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ + CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + commonsHashMap.put("abc", 3); + commonsHashMap.remove("aBC"); + + Assert.assertEquals(0, commonsHashMap.size()); } @Test @@ -33,6 +90,6 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("abc", 3); linkedHashMap.remove("aBC"); - Assert.assertEquals(linkedHashMap.size(), 0); + Assert.assertEquals(0, linkedHashMap.size()); } } From ac21dcc346f1c3debe4b8bd370f937c5aa6f7ba0 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Sat, 28 Mar 2020 22:41:07 +0300 Subject: [PATCH 121/194] tests has been added and split --- .../CaseInsensitiveMapUnitTest.java | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index b3653a97c2..82feef869a 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -1,17 +1,16 @@ package com.baeldung.map.caseinsensitivekeys; import org.apache.commons.collections4.map.CaseInsensitiveMap; -import org.junit.Assert; import org.junit.Test; import org.springframework.util.LinkedCaseInsensitiveMap; -import static org.junit.Assert.*; - +import java.util.Map; import java.util.TreeMap; +import static org.junit.Assert.*; public class CaseInsensitiveMapUnitTest { @Test public void givenCaseInsensitiveTreeMap_whenTwoEntriesAdded_thenSizeIsOne(){ - TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); treeMap.put("abc", 1); treeMap.put("ABC", 2); @@ -21,7 +20,7 @@ public class CaseInsensitiveMapUnitTest { @Test public void givenCommonsCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ - CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + Map commonsHashMap = new CaseInsensitiveMap<>(); commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2); @@ -41,20 +40,20 @@ public class CaseInsensitiveMapUnitTest { @Test public void givenCaseInsensitiveTreeMap_whenSameEntryAdded_thenValueUpdated(){ - TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); treeMap.put("abc", 1); treeMap.put("ABC", 2); - Assert.assertEquals((Integer)2, treeMap.get("aBc")); + assertEquals((Integer)2, treeMap.get("aBc")); } @Test public void givenCommonsCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ - CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + Map commonsHashMap = new CaseInsensitiveMap<>(); commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2); - Assert.assertEquals((Integer)2, commonsHashMap.get("aBc")); + assertEquals((Integer)2, commonsHashMap.get("aBc")); } @Test @@ -63,25 +62,25 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("abc", 1); linkedHashMap.put("ABC", 2); - Assert.assertEquals((Integer)2, linkedHashMap.get("aBc")); + assertEquals((Integer)2, linkedHashMap.get("aBc")); } @Test public void givenCaseInsensitiveTreeMap_whenEntryRemoved_thenSizeIsZero(){ - TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + Map treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); treeMap.put("abc", 3); treeMap.remove("aBC"); - Assert.assertEquals(0, treeMap.size()); + assertEquals(0, treeMap.size()); } @Test public void givenCommonsCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ - CaseInsensitiveMap commonsHashMap = new CaseInsensitiveMap<>(); + Map commonsHashMap = new CaseInsensitiveMap<>(); commonsHashMap.put("abc", 3); commonsHashMap.remove("aBC"); - Assert.assertEquals(0, commonsHashMap.size()); + assertEquals(0, commonsHashMap.size()); } @Test @@ -90,6 +89,6 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("abc", 3); linkedHashMap.remove("aBC"); - Assert.assertEquals(0, linkedHashMap.size()); + assertEquals(0, linkedHashMap.size()); } } From dac08f02db475176443be050cc929b1c40699913 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Sat, 28 Mar 2020 22:50:07 +0300 Subject: [PATCH 122/194] varius get cases --- .../map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index 82feef869a..60dd1da9c0 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -45,6 +45,7 @@ public class CaseInsensitiveMapUnitTest { treeMap.put("ABC", 2); assertEquals((Integer)2, treeMap.get("aBc")); + assertEquals((Integer)2, treeMap.get("ABc")); } @Test @@ -54,6 +55,7 @@ public class CaseInsensitiveMapUnitTest { commonsHashMap.put("ABC", 2); assertEquals((Integer)2, commonsHashMap.get("aBc")); + assertEquals((Integer)2, commonsHashMap.get("ABc")); } @Test @@ -63,6 +65,7 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("ABC", 2); assertEquals((Integer)2, linkedHashMap.get("aBc")); + assertEquals((Integer)2, linkedHashMap.get("ABc")); } @Test From 22a94cd61c2b5f936e85aeecf6c52c7a5f9153d7 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Mon, 30 Mar 2020 13:28:29 +0300 Subject: [PATCH 123/194] changed README, assert has changed --- .../CaseInsensitiveMapUnitTest.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index 60dd1da9c0..37d9af7535 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -25,7 +25,6 @@ public class CaseInsensitiveMapUnitTest { commonsHashMap.put("ABC", 2); assertEquals(1, commonsHashMap.size()); - } @Test @@ -35,7 +34,6 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("ABC", 2); assertEquals(1, linkedHashMap.size()); - } @Test @@ -44,8 +42,8 @@ public class CaseInsensitiveMapUnitTest { treeMap.put("abc", 1); treeMap.put("ABC", 2); - assertEquals((Integer)2, treeMap.get("aBc")); - assertEquals((Integer)2, treeMap.get("ABc")); + assertEquals(2, treeMap.get("aBc").intValue()); + assertEquals(2, treeMap.get("ABc").intValue()); } @Test @@ -54,8 +52,8 @@ public class CaseInsensitiveMapUnitTest { commonsHashMap.put("abc", 1); commonsHashMap.put("ABC", 2); - assertEquals((Integer)2, commonsHashMap.get("aBc")); - assertEquals((Integer)2, commonsHashMap.get("ABc")); + assertEquals(2, commonsHashMap.get("aBc").intValue()); + assertEquals(2, commonsHashMap.get("ABc").intValue()); } @Test @@ -64,8 +62,8 @@ public class CaseInsensitiveMapUnitTest { linkedHashMap.put("abc", 1); linkedHashMap.put("ABC", 2); - assertEquals((Integer)2, linkedHashMap.get("aBc")); - assertEquals((Integer)2, linkedHashMap.get("ABc")); + assertEquals(2, linkedHashMap.get("aBc").intValue()); + assertEquals(2, linkedHashMap.get("ABc").intValue()); } @Test From 7848c39d7b634f6b90d3e2832429bfad5be311dd Mon Sep 17 00:00:00 2001 From: omerfinger Date: Thu, 2 Apr 2020 10:06:43 +0300 Subject: [PATCH 124/194] changed LinkedHashMap to Map interface --- .../map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index 37d9af7535..c64738a266 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -29,7 +29,7 @@ public class CaseInsensitiveMapUnitTest { @Test public void givenLinkedCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ - LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + Map linkedHashMap = new LinkedCaseInsensitiveMap<>(); linkedHashMap.put("abc", 1); linkedHashMap.put("ABC", 2); @@ -58,7 +58,7 @@ public class CaseInsensitiveMapUnitTest { @Test public void givenLinkedCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ - LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + Map linkedHashMap = new LinkedCaseInsensitiveMap<>(); linkedHashMap.put("abc", 1); linkedHashMap.put("ABC", 2); @@ -86,7 +86,7 @@ public class CaseInsensitiveMapUnitTest { @Test public void givenLinkedCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ - LinkedCaseInsensitiveMap linkedHashMap = new LinkedCaseInsensitiveMap<>(); + Map linkedHashMap = new LinkedCaseInsensitiveMap<>(); linkedHashMap.put("abc", 3); linkedHashMap.remove("aBC"); From edb8e8b341e45de9c5aec23aedf309c3aeccec96 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Thu, 2 Apr 2020 12:18:03 +0300 Subject: [PATCH 125/194] changed LinkedHashMap to Map interface --- .../map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java index c64738a266..833807c692 100644 --- a/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/caseinsensitivekeys/CaseInsensitiveMapUnitTest.java @@ -15,7 +15,6 @@ public class CaseInsensitiveMapUnitTest { treeMap.put("ABC", 2); assertEquals(1, treeMap.size()); - } @Test From 33d6f3853c64ad9df288e39508753402a9e262dc Mon Sep 17 00:00:00 2001 From: Aitor Cuesta Date: Sun, 12 Apr 2020 10:46:36 +0200 Subject: [PATCH 126/194] BAEL-3075 - Undo whitespaces from pom.xml. README.md is replaced with the original version --- persistence-modules/spring-boot-persistence-2/README.md | 2 +- persistence-modules/spring-boot-persistence-2/pom.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/persistence-modules/spring-boot-persistence-2/README.md b/persistence-modules/spring-boot-persistence-2/README.md index fac8b75615..5d171fb2ca 100644 --- a/persistence-modules/spring-boot-persistence-2/README.md +++ b/persistence-modules/spring-boot-persistence-2/README.md @@ -1,3 +1,3 @@ ### Relevant Articles: -- [Using JDBI with Spring Boot](https://www.baeldung.com/spring-boot-jdbi) \ No newline at end of file +- [Using JDBI with Spring Boot](https://www.baeldung.com/spring-boot-jdbi) diff --git a/persistence-modules/spring-boot-persistence-2/pom.xml b/persistence-modules/spring-boot-persistence-2/pom.xml index c1afededb0..fd7cc467f9 100644 --- a/persistence-modules/spring-boot-persistence-2/pom.xml +++ b/persistence-modules/spring-boot-persistence-2/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung.boot.persistence spring-boot-persistence-2 From 7930d2c72e6e33d163a475abc7166e02cafb2d89 Mon Sep 17 00:00:00 2001 From: omerfinger Date: Sun, 12 Apr 2020 11:48:00 +0300 Subject: [PATCH 127/194] rebase parent pom on upstream --- pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pom.xml b/pom.xml index cb0c0cf5d7..24d9fd1d0b 100644 --- a/pom.xml +++ b/pom.xml @@ -453,8 +453,6 @@ java-collections-conversions java-collections-conversions-2 - java-collections-maps - java-collections-maps-2 java-collections-maps-3 @@ -968,8 +966,6 @@ java-collections-conversions java-collections-conversions-2 - java-collections-maps - java-collections-maps-2 java-collections-maps-3 From a0dd4a537db8332ab8790b0ee0dca3e7a42c3e5f Mon Sep 17 00:00:00 2001 From: gindex Date: Sun, 12 Apr 2020 13:01:52 +0200 Subject: [PATCH 128/194] Revert README.md to 1acadab1 --- reactor-core/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/reactor-core/README.md b/reactor-core/README.md index f2dbd77981..e3cca35f86 100644 --- a/reactor-core/README.md +++ b/reactor-core/README.md @@ -7,4 +7,3 @@ This module contains articles about Reactor Core. - [Intro To Reactor Core](https://www.baeldung.com/reactor-core) - [Combining Publishers in Project Reactor](https://www.baeldung.com/reactor-combine-streams) - [Programmatically Creating Sequences with Project Reactor](https://www.baeldung.com/flux-sequences-reactor) -- [How To Get String From Mono In Reactive Java](http://baeldung.com/string-from-mono/) \ No newline at end of file From 856c0473068fef84d5a68c532bd2ecd28884ea38 Mon Sep 17 00:00:00 2001 From: Eric Martin Date: Sun, 12 Apr 2020 13:53:06 -0500 Subject: [PATCH 129/194] Update terraform/best-practices/k8s-modules/SETUP.md Co-Authored-By: KevinGilmore --- terraform/best-practices/k8s-modules/SETUP.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/terraform/best-practices/k8s-modules/SETUP.md b/terraform/best-practices/k8s-modules/SETUP.md index b7e4c2764d..f00247a293 100644 --- a/terraform/best-practices/k8s-modules/SETUP.md +++ b/terraform/best-practices/k8s-modules/SETUP.md @@ -4,7 +4,7 @@ This sample deploys two services behind a Kubernetes ingress. # Setup instructions -1. Mak sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output. +1. Make sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output. If you get a list of nodes that contains at least one _ready_ module, you're good to go 2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere in the OS's PATH. @@ -18,4 +18,3 @@ This sample deploys two services behind a Kubernetes ingress. 6. Run _terraform destroy_ to remove the previously creates namespace. - From bf0ff591457cef341514a54764c1b944f87b7cd2 Mon Sep 17 00:00:00 2001 From: Eric Martin Date: Sun, 12 Apr 2020 13:53:19 -0500 Subject: [PATCH 130/194] Update terraform/best-practices/k8s-basic/SETUP.md Co-Authored-By: KevinGilmore --- terraform/best-practices/k8s-basic/SETUP.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/terraform/best-practices/k8s-basic/SETUP.md b/terraform/best-practices/k8s-basic/SETUP.md index 479bb75274..35e690d88e 100644 --- a/terraform/best-practices/k8s-basic/SETUP.md +++ b/terraform/best-practices/k8s-basic/SETUP.md @@ -1,6 +1,6 @@ # Setup instructions -1. Mak sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output. +1. Make sure you have a working Kubernetes environment. Use a simple command such as _kubectl get nodes_ and check its output. If you get a list of nodes that contains at least one _ready_ module, you're good to go 2. Download the Terraform package for your environment from Hashicorp's site. Unzip it and put the _terraform_ binary somewhere in the OS's PATH. @@ -12,4 +12,3 @@ ''' 5. Wait until Terraform create all resources and run _kubectl get namespaces_. The output should now have a new "hello-terraform" namespace. 6. Run _terraform destroy_ to remove the previously creates namespace. - From 02a4eee18c9a91af3aa64747cdf036f0a645f464 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 13 Apr 2020 15:09:40 +0530 Subject: [PATCH 131/194] JAVA-620: New module core-java-io-conversions-2 --- .../core-java-io-conversions-2/README.md | 9 + .../core-java-io-conversions-2/pom.xml | 37 +++ .../InputStreamToByteBufferUnitTest.java | 56 ++++ .../JavaInputStreamToXUnitTest.java | 248 ++++++++++++++++++ .../src/test/resources/sample.txt | 1 + .../src/test/resources/targetFile.tmp | 1 + 6 files changed, 352 insertions(+) create mode 100644 core-java-modules/core-java-io-conversions-2/README.md create mode 100644 core-java-modules/core-java-io-conversions-2/pom.xml create mode 100644 core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtobytes/InputStreamToByteBufferUnitTest.java create mode 100644 core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java create mode 100644 core-java-modules/core-java-io-conversions-2/src/test/resources/sample.txt create mode 100644 core-java-modules/core-java-io-conversions-2/src/test/resources/targetFile.tmp diff --git a/core-java-modules/core-java-io-conversions-2/README.md b/core-java-modules/core-java-io-conversions-2/README.md new file mode 100644 index 0000000000..404d4aa400 --- /dev/null +++ b/core-java-modules/core-java-io-conversions-2/README.md @@ -0,0 +1,9 @@ +## Core Java IO Conversions + +This module contains articles about core Java input/output(IO) conversions. + +### Relevant Articles: +- [Java InputStream to String](https://www.baeldung.com/convert-input-stream-to-string) +- [Java InputStream to Byte Array and ByteBuffer](https://www.baeldung.com/convert-input-stream-to-array-of-bytes) +- [Java – Write an InputStream to a File](https://www.baeldung.com/convert-input-stream-to-a-file) +- More articles: [[<-- prev]](/core-java-modules/core-java-io-conversions) diff --git a/core-java-modules/core-java-io-conversions-2/pom.xml b/core-java-modules/core-java-io-conversions-2/pom.xml new file mode 100644 index 0000000000..e95d1f4b67 --- /dev/null +++ b/core-java-modules/core-java-io-conversions-2/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + core-java-io-conversions-2 + 0.1.0-SNAPSHOT + core-java-io-conversions-2 + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + core-java-io-conversions + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtobytes/InputStreamToByteBufferUnitTest.java b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtobytes/InputStreamToByteBufferUnitTest.java new file mode 100644 index 0000000000..c10aaae22a --- /dev/null +++ b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtobytes/InputStreamToByteBufferUnitTest.java @@ -0,0 +1,56 @@ +package com.baeldung.inputstreamtobytes; + +import com.google.common.io.ByteSource; +import com.google.common.io.ByteStreams; +import org.apache.commons.io.IOUtils; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; + +import static java.nio.channels.Channels.newChannel; +import static org.junit.Assert.assertEquals; + +public class InputStreamToByteBufferUnitTest { + + @Test + public void givenUsingCoreClasses_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { + byte[] input = new byte[] { 0, 1, 2 }; + InputStream initialStream = new ByteArrayInputStream(input); + ByteBuffer byteBuffer = ByteBuffer.allocate(3); + while (initialStream.available() > 0) { + byteBuffer.put((byte) initialStream.read()); + } + + assertEquals(byteBuffer.position(), input.length); + } + + @Test + public void givenUsingGuava__whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { + InputStream initialStream = ByteSource + .wrap(new byte[] { 0, 1, 2 }) + .openStream(); + byte[] targetArray = ByteStreams.toByteArray(initialStream); + ByteBuffer bufferByte = ByteBuffer.wrap(targetArray); + while (bufferByte.hasRemaining()) { + bufferByte.get(); + } + + assertEquals(bufferByte.position(), targetArray.length); + } + + @Test + public void givenUsingCommonsIo_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { + byte[] input = new byte[] { 0, 1, 2 }; + InputStream initialStream = new ByteArrayInputStream(input); + ByteBuffer byteBuffer = ByteBuffer.allocate(3); + ReadableByteChannel channel = newChannel(initialStream); + IOUtils.readFully(channel, byteBuffer); + + assertEquals(byteBuffer.position(), input.length); + } + +} diff --git a/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java new file mode 100644 index 0000000000..eb8c39f2d9 --- /dev/null +++ b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java @@ -0,0 +1,248 @@ +package com.baeldung.inputstreamtostring; + +import com.google.common.base.Charsets; +import com.google.common.io.ByteSource; +import com.google.common.io.ByteStreams; +import com.google.common.io.CharStreams; +import com.google.common.io.Files; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Scanner; +import java.util.UUID; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +@SuppressWarnings("unused") +public class JavaInputStreamToXUnitTest { + protected final Logger logger = LoggerFactory.getLogger(getClass()); + private static final int DEFAULT_SIZE = 1500000; + + // tests - InputStream to String + + @Test + public final void givenUsingJava5_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { + final String originalString = randomAlphabetic(DEFAULT_SIZE); + final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); + + final StringBuilder textBuilder = new StringBuilder(); + try (Reader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) { + int c; + while ((c = reader.read()) != -1) { + textBuilder.append((char) c); + } + } + assertEquals(textBuilder.toString(), originalString); + } + + @Test + public final void givenUsingJava7_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { + final String originalString = randomAlphabetic(DEFAULT_SIZE); + final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); // exampleString.getBytes(StandardCharsets.UTF_8); + + // When + String text; + try (Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name())) { + text = scanner.useDelimiter("\\A").next(); + } + + assertThat(text, equalTo(originalString)); + } + + @Test + public final void givenUsingGuava_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { + final String originalString = randomAlphabetic(DEFAULT_SIZE); + final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); + + final ByteSource byteSource = new ByteSource() { + @Override + public final InputStream openStream() throws IOException { + return inputStream; + } + }; + + final String text = byteSource.asCharSource(Charsets.UTF_8).read(); + + assertThat(text, equalTo(originalString)); + } + + @Test + public final void givenUsingGuavaAndJava7_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { + final String originalString = randomAlphabetic(DEFAULT_SIZE); + final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); + + // When + String text; + try (final Reader reader = new InputStreamReader(inputStream)) { + text = CharStreams.toString(reader); + } + + assertThat(text, equalTo(originalString)); + } + + @Test + public final void givenUsingCommonsIo_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { + final String originalString = randomAlphabetic(DEFAULT_SIZE); + final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); + + // When + final String text = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name()); + assertThat(text, equalTo(originalString)); + } + + @Test + public final void givenUsingCommonsIoWithCopy_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { + final String originalString = randomAlphabetic(DEFAULT_SIZE); + final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); + + // When + final StringWriter writer = new StringWriter(); + final String encoding = StandardCharsets.UTF_8.name(); + IOUtils.copy(inputStream, writer, encoding); + + assertThat(writer.toString(), equalTo(originalString)); + } + + @Test + public final void givenUsingTempFile_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { + final String originalString = randomAlphabetic(DEFAULT_SIZE); + final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); + + // When + Path tempFile = java.nio.file.Files.createTempDirectory("").resolve(UUID.randomUUID().toString() + ".tmp"); + java.nio.file.Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING); + String result = new String(java.nio.file.Files.readAllBytes(tempFile)); + + assertThat(result, equalTo(originalString)); + } + + // tests - InputStream to byte[] + + @Test + public final void givenUsingPlainJavaOnFixedSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { + final InputStream initialStream = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); + final byte[] targetArray = new byte[initialStream.available()]; + initialStream.read(targetArray); + } + + @Test + public final void givenUsingPlainJavaOnUnknownSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { + final InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); + + final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + final byte[] data = new byte[1024]; + while ((nRead = is.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + + buffer.flush(); + final byte[] byteArray = buffer.toByteArray(); + } + + @Test + public final void givenUsingGuava_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { + final InputStream initialStream = ByteSource.wrap(new byte[] { 0, 1, 2 }).openStream(); + final byte[] targetArray = ByteStreams.toByteArray(initialStream); + } + + @Test + public final void givenUsingCommonsIO_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { + final InputStream initialStream = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); + final byte[] targetArray = IOUtils.toByteArray(initialStream); + } + + // tests - InputStream to File + + @Test + public final void whenConvertingToFile_thenCorrect() throws IOException { + final InputStream initialStream = new FileInputStream(new File("src/test/resources/sample.txt")); + final byte[] buffer = new byte[initialStream.available()]; + initialStream.read(buffer); + + final File targetFile = new File("src/test/resources/targetFile.tmp"); + final OutputStream outStream = new FileOutputStream(targetFile); + outStream.write(buffer); + + IOUtils.closeQuietly(initialStream); + IOUtils.closeQuietly(outStream); + } + + @Test + public final void whenConvertingInProgressToFile_thenCorrect() throws IOException { + final InputStream initialStream = new FileInputStream(new File("src/test/resources/sample.txt")); + final File targetFile = new File("src/test/resources/targetFile.tmp"); + final OutputStream outStream = new FileOutputStream(targetFile); + + final byte[] buffer = new byte[8 * 1024]; + int bytesRead; + while ((bytesRead = initialStream.read(buffer)) != -1) { + outStream.write(buffer, 0, bytesRead); + } + + IOUtils.closeQuietly(initialStream); + IOUtils.closeQuietly(outStream); + } + + @Test + public final void whenConvertingAnInProgressInputStreamToFile_thenCorrect2() throws IOException { + final InputStream initialStream = new FileInputStream(new File("src/test/resources/sample.txt")); + final File targetFile = new File("src/test/resources/targetFile.tmp"); + + java.nio.file.Files.copy(initialStream, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + + IOUtils.closeQuietly(initialStream); + } + + @Test + public final void whenConvertingInputStreamToFile_thenCorrect3() throws IOException { + final InputStream initialStream = new FileInputStream(new File("src/test/resources/sample.txt")); + final byte[] buffer = new byte[initialStream.available()]; + initialStream.read(buffer); + + final File targetFile = new File("src/test/resources/targetFile.tmp"); + Files.write(buffer, targetFile); + + IOUtils.closeQuietly(initialStream); + } + + @Test + public final void whenConvertingInputStreamToFile_thenCorrect4() throws IOException { + final InputStream initialStream = FileUtils.openInputStream(new File("src/test/resources/sample.txt")); + + final File targetFile = new File("src/test/resources/targetFile.tmp"); + + FileUtils.copyInputStreamToFile(initialStream, targetFile); + } + + @Test + public final void givenUsingPlainJava_whenConvertingAnInputStreamToString_thenCorrect() throws IOException { + String originalString = randomAlphabetic(8); + InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[1024]; + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + + buffer.flush(); + byte[] byteArray = buffer.toByteArray(); + + String text = new String(byteArray, StandardCharsets.UTF_8); + assertThat(text, equalTo(originalString)); + } + +} diff --git a/core-java-modules/core-java-io-conversions-2/src/test/resources/sample.txt b/core-java-modules/core-java-io-conversions-2/src/test/resources/sample.txt new file mode 100644 index 0000000000..5e1c309dae --- /dev/null +++ b/core-java-modules/core-java-io-conversions-2/src/test/resources/sample.txt @@ -0,0 +1 @@ +Hello World \ No newline at end of file diff --git a/core-java-modules/core-java-io-conversions-2/src/test/resources/targetFile.tmp b/core-java-modules/core-java-io-conversions-2/src/test/resources/targetFile.tmp new file mode 100644 index 0000000000..5e1c309dae --- /dev/null +++ b/core-java-modules/core-java-io-conversions-2/src/test/resources/targetFile.tmp @@ -0,0 +1 @@ +Hello World \ No newline at end of file From b2cf180785486bb722f6f014199b92f376eac415 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 13 Apr 2020 15:10:22 +0530 Subject: [PATCH 132/194] JAVA-620: Moved articles to new module --- .../core-java-io-conversions/README.md | 3 +- .../InputStreamToByteBufferUnitTest.java | 56 ---- .../JavaInputStreamToXUnitTest.java | 248 ------------------ .../src/test/resources/targetFile.tmp | 1 - 4 files changed, 1 insertion(+), 307 deletions(-) delete mode 100644 core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/inputstreamtobytes/InputStreamToByteBufferUnitTest.java delete mode 100644 core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java delete mode 100644 core-java-modules/core-java-io-conversions/src/test/resources/targetFile.tmp diff --git a/core-java-modules/core-java-io-conversions/README.md b/core-java-modules/core-java-io-conversions/README.md index cdb7df04d0..1f12c87241 100644 --- a/core-java-modules/core-java-io-conversions/README.md +++ b/core-java-modules/core-java-io-conversions/README.md @@ -3,10 +3,8 @@ This module contains articles about core Java input/output(IO) conversions. ### Relevant Articles: -- [Java InputStream to String](https://www.baeldung.com/convert-input-stream-to-string) - [Java – Convert File to InputStream](https://www.baeldung.com/convert-file-to-input-stream) - [Java – Byte Array to Writer](https://www.baeldung.com/java-convert-byte-array-to-writer) -- [Java InputStream to Byte Array and ByteBuffer](https://www.baeldung.com/convert-input-stream-to-array-of-bytes) - [Java – String to Reader](https://www.baeldung.com/java-convert-string-to-reader) - [Java – Byte Array to Reader](https://www.baeldung.com/java-convert-byte-array-to-reader) - [Java – File to Reader](https://www.baeldung.com/java-convert-file-to-reader) @@ -15,3 +13,4 @@ This module contains articles about core Java input/output(IO) conversions. - [Java – Write a Reader to File](https://www.baeldung.com/java-write-reader-to-file) - [Java – Reader to Byte Array](https://www.baeldung.com/java-convert-reader-to-byte-array) - [Java – Reader to InputStream](https://www.baeldung.com/java-convert-reader-to-inputstream) +- More articles: [[next -->]](/core-java-modules/core-java-io-conversions-2) diff --git a/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/inputstreamtobytes/InputStreamToByteBufferUnitTest.java b/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/inputstreamtobytes/InputStreamToByteBufferUnitTest.java deleted file mode 100644 index c10aaae22a..0000000000 --- a/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/inputstreamtobytes/InputStreamToByteBufferUnitTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.baeldung.inputstreamtobytes; - -import com.google.common.io.ByteSource; -import com.google.common.io.ByteStreams; -import org.apache.commons.io.IOUtils; -import org.junit.Test; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.channels.ReadableByteChannel; - -import static java.nio.channels.Channels.newChannel; -import static org.junit.Assert.assertEquals; - -public class InputStreamToByteBufferUnitTest { - - @Test - public void givenUsingCoreClasses_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { - byte[] input = new byte[] { 0, 1, 2 }; - InputStream initialStream = new ByteArrayInputStream(input); - ByteBuffer byteBuffer = ByteBuffer.allocate(3); - while (initialStream.available() > 0) { - byteBuffer.put((byte) initialStream.read()); - } - - assertEquals(byteBuffer.position(), input.length); - } - - @Test - public void givenUsingGuava__whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { - InputStream initialStream = ByteSource - .wrap(new byte[] { 0, 1, 2 }) - .openStream(); - byte[] targetArray = ByteStreams.toByteArray(initialStream); - ByteBuffer bufferByte = ByteBuffer.wrap(targetArray); - while (bufferByte.hasRemaining()) { - bufferByte.get(); - } - - assertEquals(bufferByte.position(), targetArray.length); - } - - @Test - public void givenUsingCommonsIo_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { - byte[] input = new byte[] { 0, 1, 2 }; - InputStream initialStream = new ByteArrayInputStream(input); - ByteBuffer byteBuffer = ByteBuffer.allocate(3); - ReadableByteChannel channel = newChannel(initialStream); - IOUtils.readFully(channel, byteBuffer); - - assertEquals(byteBuffer.position(), input.length); - } - -} diff --git a/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java b/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java deleted file mode 100644 index eb8c39f2d9..0000000000 --- a/core-java-modules/core-java-io-conversions/src/test/java/com/baeldung/inputstreamtostring/JavaInputStreamToXUnitTest.java +++ /dev/null @@ -1,248 +0,0 @@ -package com.baeldung.inputstreamtostring; - -import com.google.common.base.Charsets; -import com.google.common.io.ByteSource; -import com.google.common.io.ByteStreams; -import com.google.common.io.CharStreams; -import com.google.common.io.Files; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.util.Scanner; -import java.util.UUID; - -import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -@SuppressWarnings("unused") -public class JavaInputStreamToXUnitTest { - protected final Logger logger = LoggerFactory.getLogger(getClass()); - private static final int DEFAULT_SIZE = 1500000; - - // tests - InputStream to String - - @Test - public final void givenUsingJava5_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { - final String originalString = randomAlphabetic(DEFAULT_SIZE); - final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); - - final StringBuilder textBuilder = new StringBuilder(); - try (Reader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) { - int c; - while ((c = reader.read()) != -1) { - textBuilder.append((char) c); - } - } - assertEquals(textBuilder.toString(), originalString); - } - - @Test - public final void givenUsingJava7_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { - final String originalString = randomAlphabetic(DEFAULT_SIZE); - final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); // exampleString.getBytes(StandardCharsets.UTF_8); - - // When - String text; - try (Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name())) { - text = scanner.useDelimiter("\\A").next(); - } - - assertThat(text, equalTo(originalString)); - } - - @Test - public final void givenUsingGuava_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { - final String originalString = randomAlphabetic(DEFAULT_SIZE); - final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); - - final ByteSource byteSource = new ByteSource() { - @Override - public final InputStream openStream() throws IOException { - return inputStream; - } - }; - - final String text = byteSource.asCharSource(Charsets.UTF_8).read(); - - assertThat(text, equalTo(originalString)); - } - - @Test - public final void givenUsingGuavaAndJava7_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { - final String originalString = randomAlphabetic(DEFAULT_SIZE); - final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); - - // When - String text; - try (final Reader reader = new InputStreamReader(inputStream)) { - text = CharStreams.toString(reader); - } - - assertThat(text, equalTo(originalString)); - } - - @Test - public final void givenUsingCommonsIo_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { - final String originalString = randomAlphabetic(DEFAULT_SIZE); - final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); - - // When - final String text = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name()); - assertThat(text, equalTo(originalString)); - } - - @Test - public final void givenUsingCommonsIoWithCopy_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { - final String originalString = randomAlphabetic(DEFAULT_SIZE); - final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); - - // When - final StringWriter writer = new StringWriter(); - final String encoding = StandardCharsets.UTF_8.name(); - IOUtils.copy(inputStream, writer, encoding); - - assertThat(writer.toString(), equalTo(originalString)); - } - - @Test - public final void givenUsingTempFile_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { - final String originalString = randomAlphabetic(DEFAULT_SIZE); - final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); - - // When - Path tempFile = java.nio.file.Files.createTempDirectory("").resolve(UUID.randomUUID().toString() + ".tmp"); - java.nio.file.Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING); - String result = new String(java.nio.file.Files.readAllBytes(tempFile)); - - assertThat(result, equalTo(originalString)); - } - - // tests - InputStream to byte[] - - @Test - public final void givenUsingPlainJavaOnFixedSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { - final InputStream initialStream = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); - final byte[] targetArray = new byte[initialStream.available()]; - initialStream.read(targetArray); - } - - @Test - public final void givenUsingPlainJavaOnUnknownSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { - final InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); - - final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - int nRead; - final byte[] data = new byte[1024]; - while ((nRead = is.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - } - - buffer.flush(); - final byte[] byteArray = buffer.toByteArray(); - } - - @Test - public final void givenUsingGuava_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { - final InputStream initialStream = ByteSource.wrap(new byte[] { 0, 1, 2 }).openStream(); - final byte[] targetArray = ByteStreams.toByteArray(initialStream); - } - - @Test - public final void givenUsingCommonsIO_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { - final InputStream initialStream = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); - final byte[] targetArray = IOUtils.toByteArray(initialStream); - } - - // tests - InputStream to File - - @Test - public final void whenConvertingToFile_thenCorrect() throws IOException { - final InputStream initialStream = new FileInputStream(new File("src/test/resources/sample.txt")); - final byte[] buffer = new byte[initialStream.available()]; - initialStream.read(buffer); - - final File targetFile = new File("src/test/resources/targetFile.tmp"); - final OutputStream outStream = new FileOutputStream(targetFile); - outStream.write(buffer); - - IOUtils.closeQuietly(initialStream); - IOUtils.closeQuietly(outStream); - } - - @Test - public final void whenConvertingInProgressToFile_thenCorrect() throws IOException { - final InputStream initialStream = new FileInputStream(new File("src/test/resources/sample.txt")); - final File targetFile = new File("src/test/resources/targetFile.tmp"); - final OutputStream outStream = new FileOutputStream(targetFile); - - final byte[] buffer = new byte[8 * 1024]; - int bytesRead; - while ((bytesRead = initialStream.read(buffer)) != -1) { - outStream.write(buffer, 0, bytesRead); - } - - IOUtils.closeQuietly(initialStream); - IOUtils.closeQuietly(outStream); - } - - @Test - public final void whenConvertingAnInProgressInputStreamToFile_thenCorrect2() throws IOException { - final InputStream initialStream = new FileInputStream(new File("src/test/resources/sample.txt")); - final File targetFile = new File("src/test/resources/targetFile.tmp"); - - java.nio.file.Files.copy(initialStream, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - - IOUtils.closeQuietly(initialStream); - } - - @Test - public final void whenConvertingInputStreamToFile_thenCorrect3() throws IOException { - final InputStream initialStream = new FileInputStream(new File("src/test/resources/sample.txt")); - final byte[] buffer = new byte[initialStream.available()]; - initialStream.read(buffer); - - final File targetFile = new File("src/test/resources/targetFile.tmp"); - Files.write(buffer, targetFile); - - IOUtils.closeQuietly(initialStream); - } - - @Test - public final void whenConvertingInputStreamToFile_thenCorrect4() throws IOException { - final InputStream initialStream = FileUtils.openInputStream(new File("src/test/resources/sample.txt")); - - final File targetFile = new File("src/test/resources/targetFile.tmp"); - - FileUtils.copyInputStreamToFile(initialStream, targetFile); - } - - @Test - public final void givenUsingPlainJava_whenConvertingAnInputStreamToString_thenCorrect() throws IOException { - String originalString = randomAlphabetic(8); - InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); - - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - int nRead; - byte[] data = new byte[1024]; - while ((nRead = inputStream.read(data, 0, data.length)) != -1) { - buffer.write(data, 0, nRead); - } - - buffer.flush(); - byte[] byteArray = buffer.toByteArray(); - - String text = new String(byteArray, StandardCharsets.UTF_8); - assertThat(text, equalTo(originalString)); - } - -} diff --git a/core-java-modules/core-java-io-conversions/src/test/resources/targetFile.tmp b/core-java-modules/core-java-io-conversions/src/test/resources/targetFile.tmp deleted file mode 100644 index 5e1c309dae..0000000000 --- a/core-java-modules/core-java-io-conversions/src/test/resources/targetFile.tmp +++ /dev/null @@ -1 +0,0 @@ -Hello World \ No newline at end of file From effbd4cb6e080136046ece92f38554d576c2f389 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 13 Apr 2020 15:10:47 +0530 Subject: [PATCH 133/194] JAVA-620: parent pom changes to include new module --- core-java-modules/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 3fc978a68c..00ef24be92 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -69,6 +69,7 @@ core-java-io-2 core-java-io-apis core-java-io-conversions + core-java-io-conversions-2 core-java-jar core-java-jndi From dc0f9adabdba48b450814d8022f43361858e989e Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 13 Apr 2020 15:19:27 +0530 Subject: [PATCH 134/194] JAVA-620: Updated README --- core-java-modules/core-java-io-conversions-2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-io-conversions-2/README.md b/core-java-modules/core-java-io-conversions-2/README.md index 404d4aa400..4a28bf37c5 100644 --- a/core-java-modules/core-java-io-conversions-2/README.md +++ b/core-java-modules/core-java-io-conversions-2/README.md @@ -1,4 +1,4 @@ -## Core Java IO Conversions +## Core Java IO Conversions (Part 2) This module contains articles about core Java input/output(IO) conversions. From a6b0996346beedb9066b1aa0ab334c65ee79080a Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 13 Apr 2020 22:34:36 +0530 Subject: [PATCH 135/194] BAEL-3909: Update README to include article in correct module --- core-java-modules/core-java-string-operations-2/README.md | 1 + core-java-modules/core-java-string-operations/README.md | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-string-operations-2/README.md b/core-java-modules/core-java-string-operations-2/README.md index 5e92738f5c..bc00c6a915 100644 --- a/core-java-modules/core-java-string-operations-2/README.md +++ b/core-java-modules/core-java-string-operations-2/README.md @@ -11,4 +11,5 @@ This module contains articles about string operations. - [Case-Insensitive String Matching in Java](https://www.baeldung.com/java-case-insensitive-string-matching) - [L-Trim and R-Trim in Java](https://www.baeldung.com/l-trim-and-r-trim-in-java) - [L-Trim and R-Trim Alternatives in Java](https://www.baeldung.com/java-trim-alternatives) +- [Java Convert PDF to Base64](https://www.baeldung.com/java-convert-pdf-to-base64) - More articles: [[<-- prev]](../core-java-string-operations) diff --git a/core-java-modules/core-java-string-operations/README.md b/core-java-modules/core-java-string-operations/README.md index c40e56bc46..18a2649a6a 100644 --- a/core-java-modules/core-java-string-operations/README.md +++ b/core-java-modules/core-java-string-operations/README.md @@ -13,5 +13,4 @@ This module contains articles about string operations. - [Adding a Newline Character to a String in Java](https://www.baeldung.com/java-string-newline) - [Check If a String Contains a Substring](https://www.baeldung.com/java-string-contains-substring) - [Java Base64 Encoding and Decoding](https://www.baeldung.com/java-base64-encode-and-decode) -- [Java Convert PDF to Base64](https://www.baeldung.com/java-convert-pdf-to-base64) - More articles: [[next -->]](../core-java-string-operations-2) From 676738e7cbe702b85cf11c84b526d18e5b47b503 Mon Sep 17 00:00:00 2001 From: Krzysiek Date: Mon, 13 Apr 2020 21:21:19 +0200 Subject: [PATCH 136/194] JAVA-1295: Fix node.left -> node.right --- data-structures/src/main/java/com/baeldung/tree/BinaryTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-structures/src/main/java/com/baeldung/tree/BinaryTree.java b/data-structures/src/main/java/com/baeldung/tree/BinaryTree.java index bb62714006..7469e8ba64 100644 --- a/data-structures/src/main/java/com/baeldung/tree/BinaryTree.java +++ b/data-structures/src/main/java/com/baeldung/tree/BinaryTree.java @@ -142,7 +142,7 @@ public class BinaryTree { nodes.add(node.left); } - if (node.left != null) { + if (node.right != null) { nodes.add(node.right); } } From 123485714d03e71beb5f313746fc082b0e755a82 Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Tue, 14 Apr 2020 01:28:10 +0430 Subject: [PATCH 137/194] Renaming the Class to Reflect the Article Update --- .../concurrent/threadsafety/application/Application.java | 8 ++++---- .../callables/ExtrinsicLockCounterCallable.java | 6 +++--- .../{ExtrinsicLockCounter.java => ObjectLockCounter.java} | 4 ++-- ...ounterUnitTest.java => ObjectLockCounterUnitTest.java} | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) rename core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/{ExtrinsicLockCounter.java => ObjectLockCounter.java} (84%) rename core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/threadsafety/{ExtrinsicLockCounterUnitTest.java => ObjectLockCounterUnitTest.java} (82%) diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/application/Application.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/application/Application.java index 5fcb28cd2a..ebd027ea68 100644 --- a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/application/Application.java +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/application/Application.java @@ -9,7 +9,7 @@ import com.baeldung.concurrent.threadsafety.callables.ReentranReadWriteLockCount import com.baeldung.concurrent.threadsafety.callables.ReentrantLockCounterCallable; import com.baeldung.concurrent.threadsafety.services.AtomicCounter; import com.baeldung.concurrent.threadsafety.services.Counter; -import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter; +import com.baeldung.concurrent.threadsafety.services.ObjectLockCounter; import com.baeldung.concurrent.threadsafety.services.MessageService; import com.baeldung.concurrent.threadsafety.services.ReentrantLockCounter; import com.baeldung.concurrent.threadsafety.services.ReentrantReadWriteLockCounter; @@ -48,9 +48,9 @@ public class Application { System.out.println(future3.get()); System.out.println(future4.get()); - ExtrinsicLockCounter extrinsicLockCounter = new ExtrinsicLockCounter(); - Future future5 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(extrinsicLockCounter)); - Future future6 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(extrinsicLockCounter)); + ObjectLockCounter objectLockCounter = new ObjectLockCounter(); + Future future5 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(objectLockCounter)); + Future future6 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(objectLockCounter)); System.out.println(future5.get()); System.out.println(future6.get()); diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ExtrinsicLockCounterCallable.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ExtrinsicLockCounterCallable.java index 370e5d1f00..dcc929d3c4 100644 --- a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ExtrinsicLockCounterCallable.java +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/callables/ExtrinsicLockCounterCallable.java @@ -1,13 +1,13 @@ package com.baeldung.concurrent.threadsafety.callables; -import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter; +import com.baeldung.concurrent.threadsafety.services.ObjectLockCounter; import java.util.concurrent.Callable; public class ExtrinsicLockCounterCallable implements Callable { - private final ExtrinsicLockCounter counter; + private final ObjectLockCounter counter; - public ExtrinsicLockCounterCallable(ExtrinsicLockCounter counter) { + public ExtrinsicLockCounterCallable(ObjectLockCounter counter) { this.counter = counter; } diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ExtrinsicLockCounter.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ObjectLockCounter.java similarity index 84% rename from core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ExtrinsicLockCounter.java rename to core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ObjectLockCounter.java index 0a6ff3f60e..f31cf899ba 100644 --- a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ExtrinsicLockCounter.java +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/threadsafety/services/ObjectLockCounter.java @@ -1,11 +1,11 @@ package com.baeldung.concurrent.threadsafety.services; -public class ExtrinsicLockCounter { +public class ObjectLockCounter { private int counter; private final Object lock = new Object(); - public ExtrinsicLockCounter() { + public ObjectLockCounter() { this.counter = 0; } diff --git a/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/threadsafety/ExtrinsicLockCounterUnitTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/threadsafety/ObjectLockCounterUnitTest.java similarity index 82% rename from core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/threadsafety/ExtrinsicLockCounterUnitTest.java rename to core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/threadsafety/ObjectLockCounterUnitTest.java index 0fc3dd3a54..b0ac80a3aa 100644 --- a/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/threadsafety/ExtrinsicLockCounterUnitTest.java +++ b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/threadsafety/ObjectLockCounterUnitTest.java @@ -1,7 +1,7 @@ package com.baeldung.concurrent.threadsafety; import com.baeldung.concurrent.threadsafety.callables.ExtrinsicLockCounterCallable; -import com.baeldung.concurrent.threadsafety.services.ExtrinsicLockCounter; +import com.baeldung.concurrent.threadsafety.services.ObjectLockCounter; import org.junit.Test; import java.util.concurrent.ExecutorService; @@ -10,12 +10,12 @@ import java.util.concurrent.Future; import static org.assertj.core.api.Assertions.assertThat; -public class ExtrinsicLockCounterUnitTest { +public class ObjectLockCounterUnitTest { @Test public void whenCalledIncrementCounter_thenCorrect() throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(2); - ExtrinsicLockCounter counter = new ExtrinsicLockCounter(); + ObjectLockCounter counter = new ObjectLockCounter(); Future future1 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(counter)); Future future2 = (Future) executorService.submit(new ExtrinsicLockCounterCallable(counter)); From bc872d37428127eed4088f141205d1583588159c Mon Sep 17 00:00:00 2001 From: Benjamin Caure Date: Tue, 14 Apr 2020 07:08:04 +0200 Subject: [PATCH 138/194] BAEL-3943 Bson to json (#9079) --- persistence-modules/java-mongodb/README.md | 1 + .../com/baeldung/morphia/domain/Book.java | 88 ++++++++--- .../bsontojson/BsonToJsonIntegrationTest.java | 142 ++++++++++++++++++ .../bsontojson/JsonDateTimeConverter.java | 30 ++++ 4 files changed, 243 insertions(+), 18 deletions(-) create mode 100644 persistence-modules/java-mongodb/src/test/java/com/baeldung/bsontojson/BsonToJsonIntegrationTest.java create mode 100644 persistence-modules/java-mongodb/src/test/java/com/baeldung/bsontojson/JsonDateTimeConverter.java diff --git a/persistence-modules/java-mongodb/README.md b/persistence-modules/java-mongodb/README.md index a8539e644f..5c3c448b03 100644 --- a/persistence-modules/java-mongodb/README.md +++ b/persistence-modules/java-mongodb/README.md @@ -10,3 +10,4 @@ This module contains articles about MongoDB in Java. - [Geospatial Support in MongoDB](https://www.baeldung.com/mongodb-geospatial-support) - [Introduction to Morphia – Java ODM for MongoDB](https://www.baeldung.com/mongodb-morphia) - [MongoDB Aggregations Using Java](https://www.baeldung.com/java-mongodb-aggregations) +- [MongoDB BSON to JSON](https://www.baeldung.com/bson-to-json) diff --git a/persistence-modules/java-mongodb/src/main/java/com/baeldung/morphia/domain/Book.java b/persistence-modules/java-mongodb/src/main/java/com/baeldung/morphia/domain/Book.java index 172c916ad9..4ed2ab8580 100644 --- a/persistence-modules/java-mongodb/src/main/java/com/baeldung/morphia/domain/Book.java +++ b/persistence-modules/java-mongodb/src/main/java/com/baeldung/morphia/domain/Book.java @@ -1,5 +1,7 @@ package com.baeldung.morphia.domain; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.HashSet; import java.util.Set; @@ -29,28 +31,13 @@ public class Book { private double cost; @Reference private Set companionBooks; + @Property + private LocalDateTime publishDate; public Book() { } - public String getTitle() { - return title; - } - - public String getAuthor() { - return author; - } - - public double getCost() { - return cost; - } - - public void addCompanionBooks(Book book) { - if (companionBooks != null) - this.companionBooks.add(book); - } - public Book(String isbn, String title, String author, double cost, Publisher publisher) { this.isbn = isbn; this.title = title; @@ -60,6 +47,71 @@ public class Book { this.companionBooks = new HashSet<>(); } + // Getters and setters ... + public String getIsbn() { + return isbn; + } + + public Book setIsbn(String isbn) { + this.isbn = isbn; + return this; + } + + public String getTitle() { + return title; + } + + public Book setTitle(String title) { + this.title = title; + return this; + } + + public String getAuthor() { + return author; + } + + public Book setAuthor(String author) { + this.author = author; + return this; + } + + public Publisher getPublisher() { + return publisher; + } + + public Book setPublisher(Publisher publisher) { + this.publisher = publisher; + return this; + } + + public double getCost() { + return cost; + } + + public Book setCost(double cost) { + this.cost = cost; + return this; + } + + public LocalDateTime getPublishDate() { + return publishDate; + } + + public Book setPublishDate(LocalDateTime publishDate) { + this.publishDate = publishDate; + return this; + } + + public Set getCompanionBooks() { + return companionBooks; + } + + public Book addCompanionBooks(Book book) { + if (companionBooks != null) + this.companionBooks.add(book); + return this; + } + @Override public String toString() { return "Book [isbn=" + isbn + ", title=" + title + ", author=" + author + ", publisher=" + publisher + ", cost=" + cost + "]"; @@ -113,4 +165,4 @@ public class Book { return true; } -} \ No newline at end of file +} diff --git a/persistence-modules/java-mongodb/src/test/java/com/baeldung/bsontojson/BsonToJsonIntegrationTest.java b/persistence-modules/java-mongodb/src/test/java/com/baeldung/bsontojson/BsonToJsonIntegrationTest.java new file mode 100644 index 0000000000..e382ea4ab2 --- /dev/null +++ b/persistence-modules/java-mongodb/src/test/java/com/baeldung/bsontojson/BsonToJsonIntegrationTest.java @@ -0,0 +1,142 @@ +package com.baeldung.bsontojson; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.bson.Document; +import org.bson.json.Converter; +import org.bson.json.JsonMode; +import org.bson.json.JsonWriterSettings; +import org.bson.json.StrictJsonWriter; +import org.bson.types.ObjectId; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.morphia.domain.Book; +import com.baeldung.morphia.domain.Publisher; +import com.mongodb.MongoClient; +import com.mongodb.client.MongoDatabase; + +import dev.morphia.Datastore; +import dev.morphia.Morphia; + +public class BsonToJsonIntegrationTest { + + private static final String DB_NAME = "library"; + private static Datastore datastore; + + @BeforeClass + public static void setUp() { + Morphia morphia = new Morphia(); + morphia.mapPackage("com.baeldung.morphia"); + datastore = morphia.createDatastore(new MongoClient(), DB_NAME); + datastore.ensureIndexes(); + + datastore.save(new Book() + .setIsbn("isbn") + .setTitle("title") + .setAuthor("author") + .setCost(3.95) + .setPublisher(new Publisher(new ObjectId("fffffffffffffffffffffffa"),"publisher")) + .setPublishDate(LocalDateTime.parse("2020-01-01T18:13:32Z", DateTimeFormatter.ISO_DATE_TIME)) + .addCompanionBooks(new Book().setIsbn("isbn2"))); + } + + @AfterClass + public static void tearDown() { + datastore.delete(datastore.createQuery(Book.class)); + } + + @Test + public void givenBsonDocument_whenUsingStandardJsonTransformation_thenJsonDateIsObjectEpochTime() { + + String json = null; + try (MongoClient mongoClient = new MongoClient()) { + MongoDatabase mongoDatabase = mongoClient.getDatabase(DB_NAME); + Document bson = mongoDatabase.getCollection("Books").find().first(); + json = bson.toJson(); + } + + String expectedJson = "{\"_id\": \"isbn\", " + + "\"className\": \"com.baeldung.morphia.domain.Book\", " + + "\"title\": \"title\", " + + "\"author\": \"author\", " + + "\"publisher\": {\"_id\": {\"$oid\": \"fffffffffffffffffffffffa\"}, " + + "\"name\": \"publisher\"}, " + + "\"price\": 3.95, " + + "\"publishDate\": {\"$date\": 1577898812000}}"; + + assertNotNull(json); + + assertEquals(expectedJson, json); + } + + + @Test + public void givenBsonDocument_whenUsingRelaxedJsonTransformation_thenJsonDateIsObjectIsoDate() { + + String json = null; + try (MongoClient mongoClient = new MongoClient()) { + MongoDatabase mongoDatabase = mongoClient.getDatabase(DB_NAME); + Document bson = mongoDatabase.getCollection("Books").find().first(); + json = bson.toJson(JsonWriterSettings + .builder() + .outputMode(JsonMode.RELAXED) + .build()); + } + + String expectedJson = "{\"_id\": \"isbn\", " + + "\"className\": \"com.baeldung.morphia.domain.Book\", " + + "\"title\": \"title\", " + + "\"author\": \"author\", " + + "\"publisher\": {\"_id\": {\"$oid\": \"fffffffffffffffffffffffa\"}, " + + "\"name\": \"publisher\"}, " + + "\"price\": 3.95, " + + "\"publishDate\": {\"$date\": \"2020-01-01T17:13:32Z\"}}"; + + assertNotNull(json); + + assertEquals(expectedJson, json); + } + + @Test + public void givenBsonDocument_whenUsingCustomJsonTransformation_thenJsonDateIsStringField() { + + String json = null; + try (MongoClient mongoClient = new MongoClient()) { + MongoDatabase mongoDatabase = mongoClient.getDatabase(DB_NAME); + Document bson = mongoDatabase.getCollection("Books").find().first(); + json = bson.toJson(JsonWriterSettings + .builder() + .dateTimeConverter(new JsonDateTimeConverter()) + .build()); + } + + String expectedJson = "{\"_id\": \"isbn\", " + + "\"className\": \"com.baeldung.morphia.domain.Book\", " + + "\"title\": \"title\", " + + "\"author\": \"author\", " + + "\"publisher\": {\"_id\": {\"$oid\": \"fffffffffffffffffffffffa\"}, " + + "\"name\": \"publisher\"}, " + + "\"price\": 3.95, " + + "\"publishDate\": \"2020-01-01T17:13:32Z\"}"; + + assertEquals(expectedJson, json); + + } + +} diff --git a/persistence-modules/java-mongodb/src/test/java/com/baeldung/bsontojson/JsonDateTimeConverter.java b/persistence-modules/java-mongodb/src/test/java/com/baeldung/bsontojson/JsonDateTimeConverter.java new file mode 100644 index 0000000000..46023e363f --- /dev/null +++ b/persistence-modules/java-mongodb/src/test/java/com/baeldung/bsontojson/JsonDateTimeConverter.java @@ -0,0 +1,30 @@ +package com.baeldung.bsontojson; + +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.TimeZone; + +import org.bson.json.Converter; +import org.bson.json.StrictJsonWriter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JsonDateTimeConverter implements Converter { + + private static final Logger LOGGER = LoggerFactory.getLogger(JsonDateTimeConverter.class); + static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ISO_INSTANT + .withZone(ZoneId.of("UTC")); + + @Override + public void convert(Long value, StrictJsonWriter writer) { + try { + Instant instant = new Date(value).toInstant(); + String s = DATE_TIME_FORMATTER.format(instant); + writer.writeString(s); + } catch (Exception e) { + LOGGER.error(String.format("Fail to convert offset %d to JSON date", value), e); + } + } +} From 405230e25bf2cf92932b16d6dcc64acff80b9846 Mon Sep 17 00:00:00 2001 From: Kumar Chandrakant Date: Tue, 14 Apr 2020 10:52:05 +0530 Subject: [PATCH 139/194] Testing multithreading (#9088) --- .../core-java-concurrency-testing/.gitignore | 26 --- .../core-java-concurrency-testing/pom.xml | 170 +++++++++--------- 2 files changed, 85 insertions(+), 111 deletions(-) delete mode 100644 core-java-modules/core-java-concurrency-testing/.gitignore diff --git a/core-java-modules/core-java-concurrency-testing/.gitignore b/core-java-modules/core-java-concurrency-testing/.gitignore deleted file mode 100644 index 3de4cc647e..0000000000 --- a/core-java-modules/core-java-concurrency-testing/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -*.class - -0.* - -#folders# -/target -/neoDb* -/data -/src/main/webapp/WEB-INF/classes -*/META-INF/* -.resourceCache - -# Packaged files # -*.jar -*.war -*.ear - -# Files generated by integration tests -*.txt -backup-pom.xml -/bin/ -/temp - -#IntelliJ specific -.idea/ -*.iml \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-testing/pom.xml b/core-java-modules/core-java-concurrency-testing/pom.xml index bb3e6f5152..51de83f67c 100644 --- a/core-java-modules/core-java-concurrency-testing/pom.xml +++ b/core-java-modules/core-java-concurrency-testing/pom.xml @@ -1,93 +1,93 @@ - 4.0.0 - core-java-concurrency-testing - 0.1.0-SNAPSHOT - core-java-concurrency-testing - jar + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + core-java-concurrency-testing + 0.1.0-SNAPSHOT + core-java-concurrency-testing + jar - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../../parent-java - + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + - - - junit - junit - 4.13 - test - - - com.googlecode.thread-weaver - threadweaver - 0.2 - test - - - com.google.code.tempus-fugit - tempus-fugit - 1.1 - test - - - com.googlecode.multithreadedtc - multithreadedtc - 1.01 - test - - - org.openjdk.jcstress - jcstress-core - 0.5 - - + + + junit + junit + 4.13 + test + + + com.googlecode.thread-weaver + threadweaver + 0.2 + test + + + com.google.code.tempus-fugit + tempus-fugit + 1.1 + test + + + com.googlecode.multithreadedtc + multithreadedtc + 1.01 + test + + + org.openjdk.jcstress + jcstress-core + 0.5 + + - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - ${javac.target} - ${javac.target} - ${javac.target} - - + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${javac.target} + ${javac.target} + ${javac.target} + + - - org.apache.maven.plugins - maven-shade-plugin - 2.2 - - - main - package - - shade - - - jcstress - - - org.openjdk.jcstress.Main - - - META-INF/TestList - - - - - - - - + + org.apache.maven.plugins + maven-shade-plugin + 2.2 + + + main + package + + shade + + + jcstress + + + org.openjdk.jcstress.Main + + + META-INF/TestList + + + + + + + + From 4556829955c8a4a6718ecf32776fc70f55a9ec25 Mon Sep 17 00:00:00 2001 From: mthomas Date: Tue, 14 Apr 2020 06:44:36 -0500 Subject: [PATCH 140/194] Rename classes --- .../{SafeAccount.java => StampedAccount.java} | 16 ++++++++-------- ...st.java => ThreadStampedAccountUnitTest.java} | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) rename core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/{SafeAccount.java => StampedAccount.java} (63%) rename core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/{ThreadSafeAccountUnitTest.java => ThreadStampedAccountUnitTest.java} (68%) diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/SafeAccount.java b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java similarity index 63% rename from core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/SafeAccount.java rename to core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java index fe41429e22..1a46e1ba52 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/SafeAccount.java +++ b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java @@ -3,32 +3,32 @@ package com.baeldung.atomicstampedreference; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicStampedReference; -public class SafeAccount { +public class StampedAccount { private AtomicInteger stamp = new AtomicInteger(0); - private AtomicStampedReference balance = new AtomicStampedReference<>(0, 0); + private AtomicStampedReference account = new AtomicStampedReference<>(0, 0); public int getBalance() { - return this.balance.get(new int[1]); + return this.account.get(new int[1]); } public int getStamp() { int[] stamps = new int[1]; - this.balance.get(stamps); + this.account.get(stamps); return stamps[0]; } public boolean deposit(int funds) { int[] stamps = new int[1]; - int current = this.balance.get(stamps); + int current = this.account.get(stamps); int newStamp = this.stamp.incrementAndGet(); - return this.balance.compareAndSet(current, current + funds, stamps[0], newStamp); + return this.account.compareAndSet(current, current + funds, stamps[0], newStamp); } public boolean withdrawal(int funds) { int[] stamps = new int[1]; - int current = this.balance.get(stamps); + int current = this.account.get(stamps); int newStamp = this.stamp.incrementAndGet(); - return this.balance.compareAndSet(current, current - funds, stamps[0], newStamp); + return this.account.compareAndSet(current, current - funds, stamps[0], newStamp); } } diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadStampedAccountUnitTest.java similarity index 68% rename from core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java rename to core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadStampedAccountUnitTest.java index bd33d5b4ec..ce83355073 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadSafeAccountUnitTest.java +++ b/core-java-modules/core-java-concurrency-advanced-3/src/test/java/com/baeldung/atomicstampedreference/ThreadStampedAccountUnitTest.java @@ -3,11 +3,11 @@ package com.baeldung.atomicstampedreference; import org.junit.Assert; import org.junit.Test; -public class ThreadSafeAccountUnitTest { +public class ThreadStampedAccountUnitTest { @Test - public void givenMultiThread_whenSafeAccount_thenSetBalance() throws InterruptedException { - SafeAccount account = new SafeAccount(); + public void givenMultiThread_whenStampedAccount_thenSetBalance() throws InterruptedException { + StampedAccount account = new StampedAccount(); Thread t = new Thread(() -> { while (!account.withdrawal(100)) Thread.yield(); From 7fdcf68ccb4ef95a7555095e5cccb46b25978f78 Mon Sep 17 00:00:00 2001 From: SippingCode <55111084+SippingCode@users.noreply.github.com> Date: Wed, 15 Apr 2020 07:26:52 +0200 Subject: [PATCH 141/194] BAEL 3970 - Manual logout with Spring Security (#9075) * Manual logout with Spring Security - Basic manual logout - logout with Clear Data Site Header * Add missing annotation for controller. Change mapping URL value. * Add intergration tests for manual logouts. * BAEL-3970 - Add asserts on test. Fix tests names. Remove unused imports. --- .../manuallogout/BasicAuthController.java | 32 +++++++++ .../manuallogout/ClearSiteDataController.java | 29 ++++++++ .../manuallogout/ManualLogoutApplication.java | 11 +++ .../SimpleSecurityConfiguration.java | 39 +++++++++++ .../ManualLogoutIntegrationTest.java | 70 +++++++++++++++++++ 5 files changed, 181 insertions(+) create mode 100644 spring-5-security/src/main/java/com/baeldung/manuallogout/BasicAuthController.java create mode 100644 spring-5-security/src/main/java/com/baeldung/manuallogout/ClearSiteDataController.java create mode 100644 spring-5-security/src/main/java/com/baeldung/manuallogout/ManualLogoutApplication.java create mode 100644 spring-5-security/src/main/java/com/baeldung/manuallogout/SimpleSecurityConfiguration.java create mode 100644 spring-5-security/src/test/java/com/baeldung/manuallogout/ManualLogoutIntegrationTest.java diff --git a/spring-5-security/src/main/java/com/baeldung/manuallogout/BasicAuthController.java b/spring-5-security/src/main/java/com/baeldung/manuallogout/BasicAuthController.java new file mode 100644 index 0000000000..8f01940dce --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/manuallogout/BasicAuthController.java @@ -0,0 +1,32 @@ +package com.baeldung.manuallogout; + +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +@Controller +public class BasicAuthController { + + @RequestMapping(value = {"/basiclogout"}, method = RequestMethod.POST) + public String logout(HttpServletRequest request, HttpServletResponse response) { + HttpSession session; + SecurityContextHolder.clearContext(); + session = request.getSession(false); + if (session != null) { + session.invalidate(); + } + for (Cookie cookie : request.getCookies()) { + String cookieName = cookie.getName(); + Cookie cookieToDelete = new Cookie(cookieName, null); + cookieToDelete.setMaxAge(0); + response.addCookie(cookieToDelete); + } + return "redirect:/login?logout"; + } +} diff --git a/spring-5-security/src/main/java/com/baeldung/manuallogout/ClearSiteDataController.java b/spring-5-security/src/main/java/com/baeldung/manuallogout/ClearSiteDataController.java new file mode 100644 index 0000000000..7eef397da3 --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/manuallogout/ClearSiteDataController.java @@ -0,0 +1,29 @@ +package com.baeldung.manuallogout; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.logout.HeaderWriterLogoutHandler; +import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter; +import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Controller +public class ClearSiteDataController { + + Directive[] SOURCE = {Directive.COOKIES, Directive.STORAGE, Directive.EXECUTION_CONTEXTS, Directive.CACHE}; + + @RequestMapping(value = {"/csdlogout"}, method = RequestMethod.POST) + public String logout(HttpServletRequest request, HttpServletResponse response) { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth != null) { + ClearSiteDataHeaderWriter csdHeaderWriter = new ClearSiteDataHeaderWriter(SOURCE); + new HeaderWriterLogoutHandler(csdHeaderWriter).logout(request, response, auth); + } + return "redirect:/login?logout"; + } +} diff --git a/spring-5-security/src/main/java/com/baeldung/manuallogout/ManualLogoutApplication.java b/spring-5-security/src/main/java/com/baeldung/manuallogout/ManualLogoutApplication.java new file mode 100644 index 0000000000..50ea356f03 --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/manuallogout/ManualLogoutApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.manuallogout; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ManualLogoutApplication { + public static void main(String[] args) { + SpringApplication.run(ManualLogoutApplication.class, args); + } +} diff --git a/spring-5-security/src/main/java/com/baeldung/manuallogout/SimpleSecurityConfiguration.java b/spring-5-security/src/main/java/com/baeldung/manuallogout/SimpleSecurityConfiguration.java new file mode 100644 index 0000000000..6f14f6fca2 --- /dev/null +++ b/spring-5-security/src/main/java/com/baeldung/manuallogout/SimpleSecurityConfiguration.java @@ -0,0 +1,39 @@ +package com.baeldung.manuallogout; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class SimpleSecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.formLogin() + .loginProcessingUrl("/login") + .loginPage("/login") + .usernameParameter("username") + .passwordParameter("password") + .defaultSuccessUrl("/") + .failureUrl("/login?error"); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("user") + .password("password") + .roles("USER") + .and() + .withUser("manager") + .password("password") + .credentialsExpired(true) + .accountExpired(true) + .accountLocked(true) + .authorities("WRITE_PRIVILEGES", "READ_PRIVILEGES") + .roles("MANAGER"); + } +} diff --git a/spring-5-security/src/test/java/com/baeldung/manuallogout/ManualLogoutIntegrationTest.java b/spring-5-security/src/test/java/com/baeldung/manuallogout/ManualLogoutIntegrationTest.java new file mode 100644 index 0000000000..a64cb82910 --- /dev/null +++ b/spring-5-security/src/test/java/com/baeldung/manuallogout/ManualLogoutIntegrationTest.java @@ -0,0 +1,70 @@ +package com.baeldung.manuallogout; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpSession; + +import static org.junit.Assert.assertNull; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@RunWith(SpringRunner.class) +@WebMvcTest() +public class ManualLogoutIntegrationTest { + + private static final String CLEAR_SITE_DATA_HEADER = "Clear-Site-Data"; + public static final int EXPIRY = 60 * 10; + public static final String COOKIE_NAME = "customerName"; + public static final String COOKIE_VALUE = "myName"; + public static final String ATTRIBUTE_NAME = "att"; + public static final String ATTRIBUTE_VALUE = "attvalue"; + + @Autowired + private MockMvc mockMvc; + + @WithMockUser(value = "spring") + @Test + public void givenLoggedUserWhenUserLogoutThenSessionCleared() throws Exception { + + MockHttpSession session = new MockHttpSession(); + session.setAttribute(ATTRIBUTE_NAME, ATTRIBUTE_VALUE); + + Cookie randomCookie = new Cookie(COOKIE_NAME, COOKIE_VALUE); + randomCookie.setMaxAge(EXPIRY); // 10 minutes + + MockHttpServletRequest requestStateAfterLogout = this.mockMvc.perform(post("/basiclogout").secure(true).with(csrf()).session(session).cookie(randomCookie)) + .andExpect(status().is3xxRedirection()) + .andExpect(unauthenticated()) + .andExpect(cookie().maxAge(COOKIE_NAME, 0)) + .andReturn() + .getRequest(); + + HttpSession sessionStateAfterLogout = requestStateAfterLogout.getSession(); + assertNull(sessionStateAfterLogout.getAttribute(ATTRIBUTE_NAME)); + + + } + + @WithMockUser(value = "spring") + @Test + public void givenLoggedUserWhenUserLogoutThenClearDataSiteHeaderPresent() throws Exception { + + this.mockMvc.perform(post("/csdlogout").secure(true).with(csrf())) + .andDo(print()) + .andExpect(status().is3xxRedirection()) + .andExpect(header().exists(CLEAR_SITE_DATA_HEADER)) + .andReturn(); + } +} \ No newline at end of file From 8c77609793091995b2bf77f4dd3e14ada27a7997 Mon Sep 17 00:00:00 2001 From: Aitor Cuesta Date: Wed, 15 Apr 2020 08:01:26 +0200 Subject: [PATCH 142/194] BAEL-3075 - Removing byte-buddy dependency --- persistence-modules/spring-boot-persistence-2/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/persistence-modules/spring-boot-persistence-2/pom.xml b/persistence-modules/spring-boot-persistence-2/pom.xml index fd7cc467f9..9f456fa8af 100644 --- a/persistence-modules/spring-boot-persistence-2/pom.xml +++ b/persistence-modules/spring-boot-persistence-2/pom.xml @@ -51,11 +51,6 @@ spring-boot-starter-data-jpa - - net.bytebuddy - byte-buddy - - org.jdbi jdbi3-spring4 From 86c4eea3dd95a0e98e6bb882e482fe0702adbd20 Mon Sep 17 00:00:00 2001 From: Belma Jakupovic Date: Wed, 15 Apr 2020 21:15:59 +0200 Subject: [PATCH 143/194] additional answers mockito change repository method (#9082) --- .../mockito/additionalanswers/BookRepository.java | 15 +++++++++++---- .../mockito/additionalanswers/BookService.java | 4 ++-- .../additionalanswers/BookServiceUnitTest.java | 12 ++++++------ 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/additionalanswers/BookRepository.java b/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/additionalanswers/BookRepository.java index 78187e3f01..677ee502b4 100644 --- a/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/additionalanswers/BookRepository.java +++ b/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/additionalanswers/BookRepository.java @@ -1,5 +1,9 @@ package com.baeldung.mockito.additionalanswers; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + public class BookRepository { public Book getByBookId(Long bookId) { return new Book(bookId, "To Kill a Mocking Bird", "Harper Lee", 256); @@ -9,9 +13,12 @@ public class BookRepository { return new Book(book.getBookId(), book.getTitle(), book.getAuthor(), book.getNumberOfPages()); } - public Book checkIfEquals(Book bookOne, Book bookTwo, Book bookThree) { - if (bookOne.equals(bookTwo) && bookTwo.equals(bookThree) && bookThree.equals(bookOne)) { - return bookOne; - } else return bookTwo; + public Book selectRandomBook(Book bookOne, Book bookTwo, Book bookThree) { + List selection = new ArrayList<>(); + selection.add(bookOne); + selection.add(bookTwo); + selection.add(bookThree); + Random random = new Random(); + return selection.get(random.nextInt(selection.size())); } } diff --git a/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/additionalanswers/BookService.java b/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/additionalanswers/BookService.java index 92c01f8a70..4499a6524b 100644 --- a/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/additionalanswers/BookService.java +++ b/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/additionalanswers/BookService.java @@ -15,8 +15,8 @@ public class BookService { return bookRepository.save(book); } - public Book checkifEquals(Book book1, Book book2, Book book3) { - return bookRepository.checkIfEquals(book1, book2, book3); + public Book selectRandomBook(Book book1, Book book2, Book book3) { + return bookRepository.selectRandomBook(book1, book2, book3); } } diff --git a/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/additionalanswers/BookServiceUnitTest.java b/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/additionalanswers/BookServiceUnitTest.java index c9527ec0ec..ee32bcf70c 100644 --- a/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/additionalanswers/BookServiceUnitTest.java +++ b/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/additionalanswers/BookServiceUnitTest.java @@ -34,9 +34,9 @@ public class BookServiceUnitTest { Book book2 = new Book(2L, "Animal Farm", "George Orwell", 300); Book book3 = new Book(3L, "Romeo and Juliet", "William Shakespeare", 200); - Mockito.when(bookRepository.checkIfEquals(any(Book.class), any(Book.class), any(Book.class))).then(AdditionalAnswers.returnsSecondArg()); + Mockito.when(bookRepository.selectRandomBook(any(Book.class), any(Book.class), any(Book.class))).then(AdditionalAnswers.returnsSecondArg()); - Book secondBook = bookService.checkifEquals(book1, book2, book3); + Book secondBook = bookService.selectRandomBook(book1, book2, book3); assertEquals(secondBook, book2); } @@ -47,9 +47,9 @@ public class BookServiceUnitTest { Book book2 = new Book(2L, "Animal Farm", "George Orwell", 300); Book book3 = new Book(3L, "Romeo and Juliet", "William Shakespeare", 200); - Mockito.when(bookRepository.checkIfEquals(any(Book.class), any(Book.class), any(Book.class))).then(AdditionalAnswers.returnsLastArg()); + Mockito.when(bookRepository.selectRandomBook(any(Book.class), any(Book.class), any(Book.class))).then(AdditionalAnswers.returnsLastArg()); - Book lastBook = bookService.checkifEquals(book1, book2, book3); + Book lastBook = bookService.selectRandomBook(book1, book2, book3); assertEquals(lastBook, book3); } @@ -59,9 +59,9 @@ public class BookServiceUnitTest { Book book2 = new Book(2L, "Animal Farm", "George Orwell", 300); Book book3 = new Book(3L, "Romeo and Juliet", "William Shakespeare", 200); - Mockito.when(bookRepository.checkIfEquals(any(Book.class), any(Book.class), any(Book.class))).then(AdditionalAnswers.returnsArgAt(1)); + Mockito.when(bookRepository.selectRandomBook(any(Book.class), any(Book.class), any(Book.class))).then(AdditionalAnswers.returnsArgAt(1)); - Book bookOnIndex = bookService.checkifEquals(book1, book2, book3); + Book bookOnIndex = bookService.selectRandomBook(book1, book2, book3); assertEquals(bookOnIndex, book2); } From 23099cff16320fcd96c677b824c10b3caa723574 Mon Sep 17 00:00:00 2001 From: kwoyke Date: Wed, 15 Apr 2020 21:19:02 +0200 Subject: [PATCH 144/194] BAEL-3994: Add example of chaining methods returning Optionals (#9102) * BAEL-3994: Add example of chaining methods returning Optionals * BAEL-3994: Update --- .../orelseoptional/ItemsProvider.java | 21 +++++++++++++++ .../OrElseOptionalUnitTest.java | 26 +++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 core-java-modules/core-java-optional/src/main/java/com/baeldung/orelseoptional/ItemsProvider.java diff --git a/core-java-modules/core-java-optional/src/main/java/com/baeldung/orelseoptional/ItemsProvider.java b/core-java-modules/core-java-optional/src/main/java/com/baeldung/orelseoptional/ItemsProvider.java new file mode 100644 index 0000000000..480dc782e4 --- /dev/null +++ b/core-java-modules/core-java-optional/src/main/java/com/baeldung/orelseoptional/ItemsProvider.java @@ -0,0 +1,21 @@ +package com.baeldung.orelseoptional; + +import java.util.Optional; + +public class ItemsProvider { + + Optional getEmptyItem() { + System.out.println("Returning an empty item"); + return Optional.empty(); + } + + Optional getNail() { + System.out.println("Returning a nail"); + return Optional.of("nail"); + } + + Optional getHammer() { + System.out.println("Returning a hammer"); + return Optional.of("hammer"); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-optional/src/test/java/com/baeldung/orelseoptional/OrElseOptionalUnitTest.java b/core-java-modules/core-java-optional/src/test/java/com/baeldung/orelseoptional/OrElseOptionalUnitTest.java index 91aebbeebd..e3bdedcd82 100644 --- a/core-java-modules/core-java-optional/src/test/java/com/baeldung/orelseoptional/OrElseOptionalUnitTest.java +++ b/core-java-modules/core-java-optional/src/test/java/com/baeldung/orelseoptional/OrElseOptionalUnitTest.java @@ -1,10 +1,10 @@ package com.baeldung.orelseoptional; -import static org.junit.Assert.assertEquals; +import org.junit.Test; import java.util.Optional; -import org.junit.Test; +import static org.junit.Assert.assertEquals; public class OrElseOptionalUnitTest { @@ -25,6 +25,28 @@ public class OrElseOptionalUnitTest { assertEquals(fallbackOptionalString, OptionalUtils.or(optionalString, fallbackOptionalString)); } + @Test + public void givenTwoOptionalMethods_whenFirstEmpty_thenSecondEvaluated() { + ItemsProvider itemsProvider = new ItemsProvider(); + + Optional item = itemsProvider.getEmptyItem() + .map(Optional::of) + .orElseGet(itemsProvider::getNail); + + assertEquals(Optional.of("nail"), item); + } + + @Test + public void givenTwoOptionalMethods_whenFirstNonEmpty_thenSecondNotEvaluated() { + ItemsProvider itemsProvider = new ItemsProvider(); + + Optional item = itemsProvider.getNail() + .map(Optional::of) + .orElseGet(itemsProvider::getHammer); + + assertEquals(Optional.of("nail"), item); + } + // Uncomment code when code base is compatible with Java 9 // @Test // public void givenOptional_whenEmptyValue_thenCustomMessage() { From ddf9da34bfcee9a28c3384a72967cd37b8073016 Mon Sep 17 00:00:00 2001 From: mikr Date: Wed, 15 Apr 2020 22:29:52 +0200 Subject: [PATCH 145/194] JAVA-617 Split or move core-java-datetime-java8 module --- .../core-java-datetime-java8-2/README.md | 2 ++ .../com/baeldung/random/LegacyRandomDateTimes.java | 0 .../java/com/baeldung/random/RandomDateTimes.java | 0 .../main/java/com/baeldung/random/RandomDates.java | 0 .../main/java/com/baeldung/random/RandomTimes.java | 0 .../baeldung/localdate/LocalDateExampleUnitTest.java | 12 ++++++------ .../random/LegacyRandomDateTimesUnitTest.java | 0 .../com/baeldung/random/RandomDateTimesUnitTest.java | 0 .../com/baeldung/random/RandomDatesUnitTest.java | 0 .../com/baeldung/random/RandomTimesUnitTest.java | 0 core-java-modules/core-java-datetime-java8/README.md | 2 +- 11 files changed, 9 insertions(+), 7 deletions(-) rename core-java-modules/{core-java-datetime-java8 => core-java-datetime-java8-2}/src/main/java/com/baeldung/random/LegacyRandomDateTimes.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-datetime-java8-2}/src/main/java/com/baeldung/random/RandomDateTimes.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-datetime-java8-2}/src/main/java/com/baeldung/random/RandomDates.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-datetime-java8-2}/src/main/java/com/baeldung/random/RandomTimes.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-datetime-java8-2}/src/test/java/com/baeldung/random/LegacyRandomDateTimesUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-datetime-java8-2}/src/test/java/com/baeldung/random/RandomDateTimesUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-datetime-java8-2}/src/test/java/com/baeldung/random/RandomDatesUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-datetime-java8-2}/src/test/java/com/baeldung/random/RandomTimesUnitTest.java (100%) diff --git a/core-java-modules/core-java-datetime-java8-2/README.md b/core-java-modules/core-java-datetime-java8-2/README.md index e53d0236c2..f16563aacc 100644 --- a/core-java-modules/core-java-datetime-java8-2/README.md +++ b/core-java-modules/core-java-datetime-java8-2/README.md @@ -1,3 +1,5 @@ ### Relevant Articles: +- [Generating Random Dates in Java](https://www.baeldung.com/java-random-dates) - [Creating a LocalDate with Values in Java](https://www.baeldung.com/java-creating-localdate-with-values) +- [[<-- Prev]](/core-java-modules/core-java-datetime-java8-1) \ No newline at end of file diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/random/LegacyRandomDateTimes.java b/core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/LegacyRandomDateTimes.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/random/LegacyRandomDateTimes.java rename to core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/LegacyRandomDateTimes.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/random/RandomDateTimes.java b/core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomDateTimes.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/random/RandomDateTimes.java rename to core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomDateTimes.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/random/RandomDates.java b/core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomDates.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/random/RandomDates.java rename to core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomDates.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/random/RandomTimes.java b/core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomTimes.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/random/RandomTimes.java rename to core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomTimes.java diff --git a/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/localdate/LocalDateExampleUnitTest.java b/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/localdate/LocalDateExampleUnitTest.java index dff15486a4..d65118ba3a 100644 --- a/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/localdate/LocalDateExampleUnitTest.java +++ b/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/localdate/LocalDateExampleUnitTest.java @@ -11,31 +11,31 @@ public class LocalDateExampleUnitTest { @Test public void givenValues_whenUsingOfMethod_thenLocalDate() { - assertEquals("2020-01-08", date.getCustomDateOne(2020, 1, 8)); + assertEquals("2020-01-08", date.getCustomDateOne(2020, 1, 8).toString()); } @Test public void givenValuesWithMonthEnum_whenUsingOfMethod_thenLocalDate() { - assertEquals("2020-01-08", date.getCustomDateTwo(2020, Month.JANUARY, 8)); + assertEquals("2020-01-08", date.getCustomDateTwo(2020, Month.JANUARY, 8).toString()); } @Test public void givenValues_whenUsingEpochDay_thenLocalDate() { - assertEquals("2020-01-08", date.getDateFromEpochDay(18269)); + assertEquals("2020-01-08", date.getDateFromEpochDay(18269).toString()); } @Test public void givenValues_whenUsingYearDay_thenLocalDate() { - assertEquals("2020-01-08", date.getDateFromYearAndDayOfYear(2020, 8)); + assertEquals("2020-01-08", date.getDateFromYearAndDayOfYear(2020, 8).toString()); } @Test public void givenValues_whenUsingParse_thenLocalDate() { - assertEquals("2020-01-08", date.getDateFromString("2020-01-08")); + assertEquals("2020-01-08", date.getDateFromString("2020-01-08").toString()); } @Test public void givenValuesWithFormatter_whenUsingParse_thenLocalDate() { - assertEquals("2020-01-08", date.getDateFromStringAndFormatter("8-Jan-2020", "d-MMM-yyyy")); + assertEquals("2020-01-08", date.getDateFromStringAndFormatter("8-Jan-2020", "d-MMM-yyyy").toString()); } } diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/random/LegacyRandomDateTimesUnitTest.java b/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/LegacyRandomDateTimesUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/random/LegacyRandomDateTimesUnitTest.java rename to core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/LegacyRandomDateTimesUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/random/RandomDateTimesUnitTest.java b/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomDateTimesUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/random/RandomDateTimesUnitTest.java rename to core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomDateTimesUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/random/RandomDatesUnitTest.java b/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomDatesUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/random/RandomDatesUnitTest.java rename to core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomDatesUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/random/RandomTimesUnitTest.java b/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomTimesUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/random/RandomTimesUnitTest.java rename to core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomTimesUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/README.md b/core-java-modules/core-java-datetime-java8/README.md index dfbe9c997f..c35683a589 100644 --- a/core-java-modules/core-java-datetime-java8/README.md +++ b/core-java-modules/core-java-datetime-java8/README.md @@ -13,4 +13,4 @@ This module contains articles about the Date and Time API introduced with Java 8 - [How to Get the Start and the End of a Day using Java](http://www.baeldung.com/java-day-start-end) - [Set the Time Zone of a Date in Java](https://www.baeldung.com/java-set-date-time-zone) - [Comparing Dates in Java](https://www.baeldung.com/java-comparing-dates) -- [Generating Random Dates in Java](https://www.baeldung.com/java-random-dates) +- [[Next -->]](/core-java-modules/core-java-datetime-java8-2) From 926614e12944c6a12aae61c6af1e9be8c32f5efa Mon Sep 17 00:00:00 2001 From: mikr Date: Wed, 15 Apr 2020 23:04:39 +0200 Subject: [PATCH 146/194] JAVA-615 Split or move algorithms-sorting module --- algorithms-sorting-2/README.md | 4 ++++ .../algorithms}/bynumber/NaturalOrderComparators.java | 2 +- .../java/com/baeldung/algorithms/inoutsort/InOutSort.java | 0 .../com/baeldung/algorithms/stringsort/AnagramValidator.java | 0 .../bynumber/NaturalOrderComparatorsUnitTest.java | 3 +-- .../com/baeldung/algorithms/inoutsort/InOutSortUnitTest.java | 0 .../algorithms/stringsort/AnagramValidatorUnitTest.java | 0 .../baeldung/algorithms/stringsort/SortStringUnitTest.java | 0 algorithms-sorting/README.md | 5 +---- 9 files changed, 7 insertions(+), 7 deletions(-) rename {algorithms-sorting/src/main/java/com/baeldung/algorithms/sort => algorithms-sorting-2/src/main/java/com/baeldung/algorithms}/bynumber/NaturalOrderComparators.java (94%) rename {algorithms-sorting => algorithms-sorting-2}/src/main/java/com/baeldung/algorithms/inoutsort/InOutSort.java (100%) rename {algorithms-sorting => algorithms-sorting-2}/src/main/java/com/baeldung/algorithms/stringsort/AnagramValidator.java (100%) rename {algorithms-sorting/src/test/java/com/baeldung/algorithms/sort => algorithms-sorting-2/src/test/java/com/baeldung/algorithms}/bynumber/NaturalOrderComparatorsUnitTest.java (95%) rename {algorithms-sorting => algorithms-sorting-2}/src/test/java/com/baeldung/algorithms/inoutsort/InOutSortUnitTest.java (100%) rename {algorithms-sorting => algorithms-sorting-2}/src/test/java/com/baeldung/algorithms/stringsort/AnagramValidatorUnitTest.java (100%) rename {algorithms-sorting => algorithms-sorting-2}/src/test/java/com/baeldung/algorithms/stringsort/SortStringUnitTest.java (100%) diff --git a/algorithms-sorting-2/README.md b/algorithms-sorting-2/README.md index 897621bc41..71c9b8f86c 100644 --- a/algorithms-sorting-2/README.md +++ b/algorithms-sorting-2/README.md @@ -1,3 +1,7 @@ ### Relevant Articles: +- [Sorting a String Alphabetically in Java](https://www.baeldung.com/java-sort-string-alphabetically) +- [Sorting Strings by Contained Numbers in Java](https://www.baeldung.com/java-sort-strings-contained-numbers) +- [How an In-Place Sorting Algorithm Works](https://www.baeldung.com/java-in-place-sorting) - [Partitioning and Sorting Arrays with Many Repeated Entries](https://www.baeldung.com/java-sorting-arrays-with-repeated-entries) +- More articles: [[<-- prev]](/algorithms-sorting) diff --git a/algorithms-sorting/src/main/java/com/baeldung/algorithms/sort/bynumber/NaturalOrderComparators.java b/algorithms-sorting-2/src/main/java/com/baeldung/algorithms/bynumber/NaturalOrderComparators.java similarity index 94% rename from algorithms-sorting/src/main/java/com/baeldung/algorithms/sort/bynumber/NaturalOrderComparators.java rename to algorithms-sorting-2/src/main/java/com/baeldung/algorithms/bynumber/NaturalOrderComparators.java index b177bd60fc..148a9a21f9 100644 --- a/algorithms-sorting/src/main/java/com/baeldung/algorithms/sort/bynumber/NaturalOrderComparators.java +++ b/algorithms-sorting-2/src/main/java/com/baeldung/algorithms/bynumber/NaturalOrderComparators.java @@ -1,4 +1,4 @@ -package com.baeldung.algorithms.sort.bynumber; +package com.baeldung.algorithms.bynumber; import java.util.Comparator; diff --git a/algorithms-sorting/src/main/java/com/baeldung/algorithms/inoutsort/InOutSort.java b/algorithms-sorting-2/src/main/java/com/baeldung/algorithms/inoutsort/InOutSort.java similarity index 100% rename from algorithms-sorting/src/main/java/com/baeldung/algorithms/inoutsort/InOutSort.java rename to algorithms-sorting-2/src/main/java/com/baeldung/algorithms/inoutsort/InOutSort.java diff --git a/algorithms-sorting/src/main/java/com/baeldung/algorithms/stringsort/AnagramValidator.java b/algorithms-sorting-2/src/main/java/com/baeldung/algorithms/stringsort/AnagramValidator.java similarity index 100% rename from algorithms-sorting/src/main/java/com/baeldung/algorithms/stringsort/AnagramValidator.java rename to algorithms-sorting-2/src/main/java/com/baeldung/algorithms/stringsort/AnagramValidator.java diff --git a/algorithms-sorting/src/test/java/com/baeldung/algorithms/sort/bynumber/NaturalOrderComparatorsUnitTest.java b/algorithms-sorting-2/src/test/java/com/baeldung/algorithms/bynumber/NaturalOrderComparatorsUnitTest.java similarity index 95% rename from algorithms-sorting/src/test/java/com/baeldung/algorithms/sort/bynumber/NaturalOrderComparatorsUnitTest.java rename to algorithms-sorting-2/src/test/java/com/baeldung/algorithms/bynumber/NaturalOrderComparatorsUnitTest.java index 2f05f62147..aaa5de87e1 100644 --- a/algorithms-sorting/src/test/java/com/baeldung/algorithms/sort/bynumber/NaturalOrderComparatorsUnitTest.java +++ b/algorithms-sorting-2/src/test/java/com/baeldung/algorithms/bynumber/NaturalOrderComparatorsUnitTest.java @@ -1,6 +1,5 @@ -package com.baeldung.algorithms.sort.bynumber; +package com.baeldung.algorithms.bynumber; -import com.baeldung.algorithms.sort.bynumber.NaturalOrderComparators; import org.junit.Test; import java.util.ArrayList; diff --git a/algorithms-sorting/src/test/java/com/baeldung/algorithms/inoutsort/InOutSortUnitTest.java b/algorithms-sorting-2/src/test/java/com/baeldung/algorithms/inoutsort/InOutSortUnitTest.java similarity index 100% rename from algorithms-sorting/src/test/java/com/baeldung/algorithms/inoutsort/InOutSortUnitTest.java rename to algorithms-sorting-2/src/test/java/com/baeldung/algorithms/inoutsort/InOutSortUnitTest.java diff --git a/algorithms-sorting/src/test/java/com/baeldung/algorithms/stringsort/AnagramValidatorUnitTest.java b/algorithms-sorting-2/src/test/java/com/baeldung/algorithms/stringsort/AnagramValidatorUnitTest.java similarity index 100% rename from algorithms-sorting/src/test/java/com/baeldung/algorithms/stringsort/AnagramValidatorUnitTest.java rename to algorithms-sorting-2/src/test/java/com/baeldung/algorithms/stringsort/AnagramValidatorUnitTest.java diff --git a/algorithms-sorting/src/test/java/com/baeldung/algorithms/stringsort/SortStringUnitTest.java b/algorithms-sorting-2/src/test/java/com/baeldung/algorithms/stringsort/SortStringUnitTest.java similarity index 100% rename from algorithms-sorting/src/test/java/com/baeldung/algorithms/stringsort/SortStringUnitTest.java rename to algorithms-sorting-2/src/test/java/com/baeldung/algorithms/stringsort/SortStringUnitTest.java diff --git a/algorithms-sorting/README.md b/algorithms-sorting/README.md index 15a5ec6e02..b4b90bf954 100644 --- a/algorithms-sorting/README.md +++ b/algorithms-sorting/README.md @@ -11,10 +11,7 @@ This module contains articles about sorting algorithms. - [Heap Sort in Java](https://www.baeldung.com/java-heap-sort) - [Shell Sort in Java](https://www.baeldung.com/java-shell-sort) - [Counting Sort in Java](https://www.baeldung.com/java-counting-sort) -- [Sorting Strings by Contained Numbers in Java](https://www.baeldung.com/java-sort-strings-contained-numbers) -- [How an In-Place Sorting Algorithm Works](https://www.baeldung.com/java-in-place-sorting) - [Selection Sort in Java](https://www.baeldung.com/java-selection-sort) -- [Sorting Strings by Contained Numbers in Java](https://www.baeldung.com/java-sort-strings-contained-numbers) - [Radix Sort in Java](https://www.baeldung.com/java-radix-sort) -- [Sorting a String Alphabetically in Java](https://www.baeldung.com/java-sort-string-alphabetically) - [Bucket Sort in Java](https://www.baeldung.com/java-bucket-sort) +- More articles: [[next -->]](/algorithms-sorintg-2) From 1239da8e6d88af335f060ae4f04e0ecade4a8fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20G=C5=82=C3=B3wka?= Date: Thu, 16 Apr 2020 21:23:23 +0200 Subject: [PATCH 147/194] BAEL-3505: Added util class to check server connection (#9013) * BAEL-3505: Added util class to check server connection * fixed formatting * removed unnecessary sout --- .../connectexception/ConnectionChecker.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 core-java-modules/core-java-networking-2/src/main/java/com/baeldung/connectexception/ConnectionChecker.java diff --git a/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/connectexception/ConnectionChecker.java b/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/connectexception/ConnectionChecker.java new file mode 100644 index 0000000000..360fb6ecaa --- /dev/null +++ b/core-java-modules/core-java-networking-2/src/main/java/com/baeldung/connectexception/ConnectionChecker.java @@ -0,0 +1,24 @@ +package com.baeldung.connectexception; + +import java.net.ConnectException; +import java.net.Socket; + +public class ConnectionChecker { + public static void main(String[] args) { + String host = "localhost"; + int port = 5000; + + try { + Socket clientSocket = new Socket(host, port); + + // successfully connected to host, do something with opened socket + + clientSocket.close(); + } catch (ConnectException e) { + // host and port combination not valid + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} From 2815700ebffd2e4caf655aed04afb90dc7fffb44 Mon Sep 17 00:00:00 2001 From: vatsalgosar Date: Fri, 17 Apr 2020 01:10:04 +0530 Subject: [PATCH 148/194] BAEL-3919 (#9072) BAEL-3919 code --- .../ComputeIfAbsentUnitTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/computeifabsent/ComputeIfAbsentUnitTest.java diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/computeifabsent/ComputeIfAbsentUnitTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/computeifabsent/ComputeIfAbsentUnitTest.java new file mode 100644 index 0000000000..391a059f05 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/computeifabsent/ComputeIfAbsentUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.map.computeifabsent; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class ComputeIfAbsentUnitTest { + + @Test + public void whenKeyIsPresent_thenFetchTheValue() { + Map stringLength = new HashMap<>(); + stringLength.put("John", 5); + assertEquals((long)stringLength.computeIfAbsent("John", s -> s.length()), 5); + } + + @Test + public void whenKeyIsNotPresent_thenComputeTheValueUsingMappingFunctionAndStore() { + Map stringLength = new HashMap<>(); + assertEquals((long)stringLength.computeIfAbsent("John", s -> s.length()), 4); + assertEquals((long)stringLength.get("John"), 4); + } + + @Test + public void whenMappingFunctionReturnsNull_thenDoNotRecordMapping() { + Map stringLength = new HashMap<>(); + assertEquals(stringLength.computeIfAbsent("John", s -> null), null); + assertNull(stringLength.get("John")); + } + + @Test(expected = RuntimeException.class) + public void whenMappingFunctionThrowsException_thenExceptionIsRethrown() { + Map stringLength = new HashMap<>(); + stringLength.computeIfAbsent("John", s -> {throw new RuntimeException();}); + } +} From 6ceff529ad9ed33614e52198018d31ac38961050 Mon Sep 17 00:00:00 2001 From: Mona Mohamadinia Date: Fri, 17 Apr 2020 00:17:10 +0430 Subject: [PATCH 149/194] Added a few code snippets (#9084) --- .../closure/StreamClosureSnippets.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/closure/StreamClosureSnippets.java diff --git a/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/closure/StreamClosureSnippets.java b/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/closure/StreamClosureSnippets.java new file mode 100644 index 0000000000..10e5716e31 --- /dev/null +++ b/core-java-modules/core-java-streams-3/src/main/java/com/baeldung/streams/closure/StreamClosureSnippets.java @@ -0,0 +1,30 @@ +package com.baeldung.streams.closure; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.stream.Stream; + +/** + * Contains a couple of simple stream API usages. + */ +public class StreamClosureSnippets { + + public static void main(String[] args) throws IOException { + // Collection based streams shouldn't be closed + Arrays.asList("Red", "Blue", "Green") + .stream() + .filter(c -> c.length() > 4) + .map(String::toUpperCase) + .forEach(System.out::print); + + String[] colors = {"Red", "Blue", "Green"}; + Arrays.stream(colors).map(String::toUpperCase).forEach(System.out::println); + + // IO-Based Streams Should be Closed via Try with Resources + try (Stream lines = Files.lines(Paths.get("/path/tp/file"))) { + // lines will be closed after exiting the try block + } + } +} From e41a34fc057d591a67276c566f2c9db579103797 Mon Sep 17 00:00:00 2001 From: Dhrubajyoti Bhattacharjee Date: Fri, 17 Apr 2020 08:15:36 +0200 Subject: [PATCH 150/194] Bael 2980 move c ra sh article to new module (#9103) --- pom.xml | 1 + spring-mvc-crash/.gitignore | 13 ++ spring-mvc-crash/README.md | 11 ++ spring-mvc-crash/pom.xml | 176 ++++++++++++++++++ .../com/baeldung/spring/ClientWebConfig.java | 16 ++ .../baeldung/spring/ClientWebConfigJava.java | 33 ++++ .../spring/controller/WelcomeController.java | 18 ++ .../contentManagementWebMvcConfig.xml | 42 +++++ .../src/main/resources/logback.xml | 19 ++ .../src/main/resources/messages.properties | 2 + .../src/main/resources/webMvcConfig.xml | 38 ++++ .../WEB-INF/crash/commands/message.groovy | 14 ++ .../WEB-INF/crash/commands/message2.java | 14 ++ .../webapp/WEB-INF/crash/crash.properties | 1 + .../webapp/WEB-INF/crash/telnet.properties | 65 +++++++ .../src/main/webapp/WEB-INF/mvc-servlet.xml | 52 ++++++ .../src/main/webapp/WEB-INF/view/error.jsp | 20 ++ .../main/webapp/WEB-INF/view/errorPage.jsp | 10 + .../src/main/webapp/WEB-INF/view/welcome.jsp | 15 ++ .../src/main/webapp/WEB-INF/web.xml | 70 +++++++ spring-mvc-crash/src/main/webapp/index.jsp | 20 ++ .../src/main/webapp/jsp/ExampleThree.jsp | 10 + .../src/main/webapp/jsp/ExampleTwo.jsp | 13 ++ .../src/main/webapp/jsp/index.jsp | 12 ++ .../java/com/baeldung/SpringContextTest.java | 19 ++ spring-mvc-xml/README.md | 1 - 26 files changed, 704 insertions(+), 1 deletion(-) create mode 100644 spring-mvc-crash/.gitignore create mode 100644 spring-mvc-crash/README.md create mode 100644 spring-mvc-crash/pom.xml create mode 100644 spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfig.java create mode 100644 spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfigJava.java create mode 100644 spring-mvc-crash/src/main/java/com/baeldung/spring/controller/WelcomeController.java create mode 100644 spring-mvc-crash/src/main/resources/contentManagementWebMvcConfig.xml create mode 100644 spring-mvc-crash/src/main/resources/logback.xml create mode 100644 spring-mvc-crash/src/main/resources/messages.properties create mode 100644 spring-mvc-crash/src/main/resources/webMvcConfig.xml create mode 100644 spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message.groovy create mode 100644 spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message2.java create mode 100644 spring-mvc-crash/src/main/webapp/WEB-INF/crash/crash.properties create mode 100644 spring-mvc-crash/src/main/webapp/WEB-INF/crash/telnet.properties create mode 100644 spring-mvc-crash/src/main/webapp/WEB-INF/mvc-servlet.xml create mode 100644 spring-mvc-crash/src/main/webapp/WEB-INF/view/error.jsp create mode 100644 spring-mvc-crash/src/main/webapp/WEB-INF/view/errorPage.jsp create mode 100644 spring-mvc-crash/src/main/webapp/WEB-INF/view/welcome.jsp create mode 100644 spring-mvc-crash/src/main/webapp/WEB-INF/web.xml create mode 100644 spring-mvc-crash/src/main/webapp/index.jsp create mode 100644 spring-mvc-crash/src/main/webapp/jsp/ExampleThree.jsp create mode 100644 spring-mvc-crash/src/main/webapp/jsp/ExampleTwo.jsp create mode 100644 spring-mvc-crash/src/main/webapp/jsp/index.jsp create mode 100644 spring-mvc-crash/src/test/java/com/baeldung/SpringContextTest.java diff --git a/pom.xml b/pom.xml index 99d0943582..9e3b354d74 100644 --- a/pom.xml +++ b/pom.xml @@ -1202,6 +1202,7 @@ spring-mvc-views spring-mvc-webflow spring-mvc-xml + spring-mvc-crash spring-protobuf spring-quartz diff --git a/spring-mvc-crash/.gitignore b/spring-mvc-crash/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-mvc-crash/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-mvc-crash/README.md b/spring-mvc-crash/README.md new file mode 100644 index 0000000000..f158a947b6 --- /dev/null +++ b/spring-mvc-crash/README.md @@ -0,0 +1,11 @@ +## Spring MVC XML + +This module contains articles about Spring MVC with XML configuration + +### Relevant Articles: + +- [Getting Started with CRaSH](https://www.baeldung.com/jvm-crash-shell) + +## Spring MVC with XML Configuration Example Project + +- access a sample jsp page at: `http://localhost:8080/spring-mvc-crash/welcome.htm \ No newline at end of file diff --git a/spring-mvc-crash/pom.xml b/spring-mvc-crash/pom.xml new file mode 100644 index 0000000000..d23e18361b --- /dev/null +++ b/spring-mvc-crash/pom.xml @@ -0,0 +1,176 @@ + + + 4.0.0 + spring-mvc-crash + 0.1-SNAPSHOT + spring-mvc-xml + war + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + + + + org.springframework + spring-web + ${org.springframework.version} + + + org.springframework + spring-webmvc + ${org.springframework.version} + + + + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + provided + + + + javax.servlet + jstl + ${jstl.version} + runtime + + + + org.hibernate.validator + hibernate-validator + ${hibernate-validator.version} + + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + + commons-io + commons-io + ${commons-io.version} + + + com.maxmind.geoip2 + geoip2 + ${geoip2.version} + + + com.fasterxml.jackson.core + jackson-databind + + + commons-logging + commons-logging + + + + + org.glassfish + javax.el + ${javax.el.version} + + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + test + + + + + org.crashub + crash.embed.spring + ${crash.version} + + + org.crashub + crash.cli + ${crash.version} + + + org.crashub + crash.connectors.telnet + ${crash.version} + + + log4j + log4j + + + + + + + org.codehaus.groovy + groovy + ${groovy.version} + + + + + spring-mvc-xml + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + + + + + + + 5.0.2.RELEASE + 1.5.10.RELEASE + + + 5.1.40 + + + 4.4.5 + 4.5.2 + + + 6.0.10.Final + 3.0.1-b08 + + + 19.0 + 2.8.0 + + + 1.6.1 + + 1.3.2 + 3.0.0-rc-3 + + + + diff --git a/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfig.java b/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfig.java new file mode 100644 index 0000000000..cc60a1ff8f --- /dev/null +++ b/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.spring; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@ImportResource("classpath:webMvcConfig.xml") +@Configuration +@ComponentScan +public class ClientWebConfig implements WebMvcConfigurer { + + public ClientWebConfig() { + super(); + } +} \ No newline at end of file diff --git a/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfigJava.java b/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfigJava.java new file mode 100644 index 0000000000..55af23034f --- /dev/null +++ b/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfigJava.java @@ -0,0 +1,33 @@ +package com.baeldung.spring; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; + +@ComponentScan("com.baeldung.spring") +public class ClientWebConfigJava implements WebMvcConfigurer { + + public ClientWebConfigJava() { + super(); + } + + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/view/"); + bean.setSuffix(".jsp"); + + return bean; + } + + @Bean + public MethodValidationPostProcessor methodValidationPostProcessor() { + return new MethodValidationPostProcessor(); + } +} \ No newline at end of file diff --git a/spring-mvc-crash/src/main/java/com/baeldung/spring/controller/WelcomeController.java b/spring-mvc-crash/src/main/java/com/baeldung/spring/controller/WelcomeController.java new file mode 100644 index 0000000000..526833611b --- /dev/null +++ b/spring-mvc-crash/src/main/java/com/baeldung/spring/controller/WelcomeController.java @@ -0,0 +1,18 @@ +package com.baeldung.spring.controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.AbstractController; + +public class WelcomeController extends AbstractController { + @Override + protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { + + ModelAndView model = new ModelAndView("welcome"); + model.addObject("msg", "Welcome to Introduction to CRaSH article from Baeldung"); + + return model; + } +} \ No newline at end of file diff --git a/spring-mvc-crash/src/main/resources/contentManagementWebMvcConfig.xml b/spring-mvc-crash/src/main/resources/contentManagementWebMvcConfig.xml new file mode 100644 index 0000000000..8a0671ca87 --- /dev/null +++ b/spring-mvc-crash/src/main/resources/contentManagementWebMvcConfig.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-mvc-crash/src/main/resources/logback.xml b/spring-mvc-crash/src/main/resources/logback.xml new file mode 100644 index 0000000000..56af2d397e --- /dev/null +++ b/spring-mvc-crash/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-mvc-crash/src/main/resources/messages.properties b/spring-mvc-crash/src/main/resources/messages.properties new file mode 100644 index 0000000000..2a3cccf76c --- /dev/null +++ b/spring-mvc-crash/src/main/resources/messages.properties @@ -0,0 +1,2 @@ +required.name = Name is required! +NotEmpty.person.password = Password is required! \ No newline at end of file diff --git a/spring-mvc-crash/src/main/resources/webMvcConfig.xml b/spring-mvc-crash/src/main/resources/webMvcConfig.xml new file mode 100644 index 0000000000..4bdb405237 --- /dev/null +++ b/spring-mvc-crash/src/main/resources/webMvcConfig.xml @@ -0,0 +1,38 @@ + + + + + + + + + image/jpeg + image/png + + + + + + + + + + + + + + + + + + + diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message.groovy b/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message.groovy new file mode 100644 index 0000000000..d66ab13d96 --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message.groovy @@ -0,0 +1,14 @@ +import org.crsh.cli.Command; +import org.crsh.cli.Usage; +import org.crsh.cli.Option; + +class message { + + @Usage("show my own message") + @Command + Object main(@Usage("custom message") @Option(names=["m","message"]) String message) { + if (message == null) + message = "No message given..."; + return message; + } +} \ No newline at end of file diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message2.java b/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message2.java new file mode 100644 index 0000000000..d1ead88024 --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message2.java @@ -0,0 +1,14 @@ +import org.crsh.command.BaseCommand; +import org.crsh.cli.Usage; +import org.crsh.cli.Command; +import org.crsh.cli.Option; + +public class message2 extends BaseCommand { + @Usage("show my own message using java") + @Command + public Object main(@Usage("custom message") @Option(names = { "m", "message" }) String message) { + if (message == null) + message = "No message given..."; + return message; + } +} \ No newline at end of file diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/crash/crash.properties b/spring-mvc-crash/src/main/webapp/WEB-INF/crash/crash.properties new file mode 100644 index 0000000000..f9ad0d7cf6 --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/WEB-INF/crash/crash.properties @@ -0,0 +1 @@ +crash.telnet.port=50001 diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/crash/telnet.properties b/spring-mvc-crash/src/main/webapp/WEB-INF/crash/telnet.properties new file mode 100644 index 0000000000..99071d09ff --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/WEB-INF/crash/telnet.properties @@ -0,0 +1,65 @@ +############################ +# Telnet daemon properties # +############################ + +##################### +# Terminals Section # +##################### + +# List of terminals available and defined below +terminals=vt100,ansi,windoof,xterm + +# vt100 implementation and aliases +term.vt100.class=net.wimpi.telnetd.io.terminal.vt100 +term.vt100.aliases=default,vt100-am,vt102,dec-vt100 + +# ansi implementation and aliases +term.ansi.class=net.wimpi.telnetd.io.terminal.ansi +term.ansi.aliases=color-xterm,xterm-color,vt320,vt220,linux,screen + +# windoof implementation and aliases +term.windoof.class=net.wimpi.telnetd.io.terminal.Windoof +term.windoof.aliases= + +# xterm implementation and aliases +term.xterm.class=net.wimpi.telnetd.io.terminal.xterm +term.xterm.aliases= + +################## +# Shells Section # +################## + +# List of shells available and defined below +shells=simple + +# shell implementations +shell.simple.class=org.crsh.telnet.term.TelnetHandler + +##################### +# Listeners Section # +##################### +listeners=std + + +# std listener specific properties + +#Basic listener and connection management settings (port is commented because CRaSH configures it) +# std.port=5000 +std.floodprotection=5 +std.maxcon=25 + + +# Timeout Settings for connections (ms) +std.time_to_warning=3600000 +std.time_to_timedout=60000 + +# Housekeeping thread active every 1 secs +std.housekeepinginterval=1000 + +std.inputmode=character + +# Login shell +std.loginshell=simple + +# Connection filter class +std.connectionfilter=none \ No newline at end of file diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-mvc-crash/src/main/webapp/WEB-INF/mvc-servlet.xml new file mode 100644 index 0000000000..46b159d984 --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/WEB-INF/mvc-servlet.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + welcomeController + welcomeController + + + + + + + + + + + + + + 5000 + + + + diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/view/error.jsp b/spring-mvc-crash/src/main/webapp/WEB-INF/view/error.jsp new file mode 100644 index 0000000000..8f3d83af17 --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/WEB-INF/view/error.jsp @@ -0,0 +1,20 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +SpringMVCExample + + + +

Pleas enter the correct details

+ + + + +
Retry
+ + + + \ No newline at end of file diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/view/errorPage.jsp b/spring-mvc-crash/src/main/webapp/WEB-INF/view/errorPage.jsp new file mode 100644 index 0000000000..ba8a836285 --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/WEB-INF/view/errorPage.jsp @@ -0,0 +1,10 @@ +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> +<%@ page session="false"%> + + + Home + + +

${errorMsg}

+ + diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/view/welcome.jsp b/spring-mvc-crash/src/main/webapp/WEB-INF/view/welcome.jsp new file mode 100644 index 0000000000..348ca652ff --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/WEB-INF/view/welcome.jsp @@ -0,0 +1,15 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Welcome Page + + +

Welcome to ${msg}

+
+

+ Go to spring handler mappings homepage + + \ No newline at end of file diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/web.xml b/spring-mvc-crash/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..4a3d6cb321 --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,70 @@ + + + Spring MVC XML Application + + + + contextClass + + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + + contextConfigLocation + com.baeldung.spring + + + + org.springframework.web.context.ContextLoaderListener + + + org.crsh.plugin.WebPluginLifeCycle + + + + + mvc + org.springframework.web.servlet.DispatcherServlet + 1 + + + mvc + / + + + + + + ExampleOne + com.baeldung.jsp.ExampleOne + + + ExampleOne + /jsp/ExampleOne + + + ExampleThree + com.baeldung.jsp.ExampleThree + + + ExampleThree + /jsp/ExampleThree + + + + + + 10 + + + index.jsp + + + + /errors + + diff --git a/spring-mvc-crash/src/main/webapp/index.jsp b/spring-mvc-crash/src/main/webapp/index.jsp new file mode 100644 index 0000000000..149fc5fe0b --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/index.jsp @@ -0,0 +1,20 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Spring MVC Examples + + + +

Spring MVC Examples

+ + + + \ No newline at end of file diff --git a/spring-mvc-crash/src/main/webapp/jsp/ExampleThree.jsp b/spring-mvc-crash/src/main/webapp/jsp/ExampleThree.jsp new file mode 100644 index 0000000000..665eb86a30 --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/jsp/ExampleThree.jsp @@ -0,0 +1,10 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Java Binding Example + + +

Bound Value

+

You said: ${text}

+ + \ No newline at end of file diff --git a/spring-mvc-crash/src/main/webapp/jsp/ExampleTwo.jsp b/spring-mvc-crash/src/main/webapp/jsp/ExampleTwo.jsp new file mode 100644 index 0000000000..7b2247638d --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/jsp/ExampleTwo.jsp @@ -0,0 +1,13 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Java in Static Page Example + + +

Java in Static Page Example

+ <% String[] arr = {"What's up?", "Hello", "It's a nice day today!"}; + String greetings = arr[(int)(Math.random() * arr.length)]; + %> +

<%= greetings %>

+ + \ No newline at end of file diff --git a/spring-mvc-crash/src/main/webapp/jsp/index.jsp b/spring-mvc-crash/src/main/webapp/jsp/index.jsp new file mode 100644 index 0000000000..58c464125d --- /dev/null +++ b/spring-mvc-crash/src/main/webapp/jsp/index.jsp @@ -0,0 +1,12 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + JSP Examples + + +

Simple JSP Examples

+

Invoke HTML rendered by Servlet: here

+

Java in static page: here

+

Java injected by Servlet: here

+ + \ No newline at end of file diff --git a/spring-mvc-crash/src/test/java/com/baeldung/SpringContextTest.java b/spring-mvc-crash/src/test/java/com/baeldung/SpringContextTest.java new file mode 100644 index 0000000000..62e34859ee --- /dev/null +++ b/spring-mvc-crash/src/test/java/com/baeldung/SpringContextTest.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import com.baeldung.spring.ClientWebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ClientWebConfig.class) +@WebAppConfiguration +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-mvc-xml/README.md b/spring-mvc-xml/README.md index 685e7686b1..0adf127aaa 100644 --- a/spring-mvc-xml/README.md +++ b/spring-mvc-xml/README.md @@ -17,7 +17,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [A Java Web Application Without a web.xml](https://www.baeldung.com/java-web-app-without-web-xml) - [Validating RequestParams and PathVariables in Spring](https://www.baeldung.com/spring-validate-requestparam-pathvariable) - [Debugging the Spring MVC 404 “No mapping found for HTTP request” Error](https://www.baeldung.com/spring-mvc-404-error) -- [Getting Started with CRaSH](https://www.baeldung.com/jvm-crash-shell) ## Spring MVC with XML Configuration Example Project From c72b6ce0114d63180adfaa8f2b056032b5bd8144 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Fri, 17 Apr 2020 12:29:42 +0530 Subject: [PATCH 151/194] JAVA-916: Migrate jhipster to parent-boot-2 --- hystrix/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hystrix/pom.xml b/hystrix/pom.xml index 8c505c9104..1cf8713b91 100644 --- a/hystrix/pom.xml +++ b/hystrix/pom.xml @@ -8,9 +8,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 From dc0a41fd8ef0e6ad9c16c2267466416f0a87f195 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Fri, 17 Apr 2020 12:37:42 +0530 Subject: [PATCH 152/194] JAVA-915: Migrate hystrix to parent-boot-2 --- hystrix/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hystrix/pom.xml b/hystrix/pom.xml index 8c505c9104..1cf8713b91 100644 --- a/hystrix/pom.xml +++ b/hystrix/pom.xml @@ -8,9 +8,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 From 29a2f0ece167b56f060bb7cbedc0cb73bbe07fb6 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Thu, 9 Apr 2020 08:24:04 +0200 Subject: [PATCH 153/194] [JAVA-616] core-java-arrays-sorting * Creation * Moved code from https://www.baeldung.com/java-sorting-arrays * Moved code from https://www.baeldung.com/java-check-sorted-array * Moved code from https://www.baeldung.com/java-invert-array * Moved code from https://www.baeldung.com/java-arrays-sort-vs-parallelsort --- .../core-java-arrays-2/README.md | 1 - .../core-java-arrays-sorting/README.md | 9 ++ .../core-java-arrays-sorting/pom.xml | 87 +++++++++++++++++++ .../com/baeldung/array/ArrayInverter.java | 0 .../baeldung/array/SortedArrayChecker.java | 2 - .../arraysort/ArraySortingBenchmark.java | 0 .../main/java/com/baeldung/sort/Employee.java | 48 ++++++++++ .../baeldung/array/ArrayInverterUnitTest.java | 0 .../array/SortedArrayCheckerUnitTest.java | 2 +- .../arraysort/SortComparisonUnitTest.java | 0 .../com/baeldung/sort/ArraySortUnitTest.java | 2 - core-java-modules/core-java-arrays/README.md | 3 - core-java-modules/pom.xml | 1 + 13 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 core-java-modules/core-java-arrays-sorting/README.md create mode 100644 core-java-modules/core-java-arrays-sorting/pom.xml rename core-java-modules/{core-java-arrays => core-java-arrays-sorting}/src/main/java/com/baeldung/array/ArrayInverter.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-sorting}/src/main/java/com/baeldung/array/SortedArrayChecker.java (97%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-sorting}/src/main/java/com/baeldung/arraysort/ArraySortingBenchmark.java (100%) create mode 100644 core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/sort/Employee.java rename core-java-modules/{core-java-arrays => core-java-arrays-sorting}/src/test/java/com/baeldung/array/ArrayInverterUnitTest.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-sorting}/src/test/java/com/baeldung/array/SortedArrayCheckerUnitTest.java (98%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-sorting}/src/test/java/com/baeldung/arraysort/SortComparisonUnitTest.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-sorting}/src/test/java/com/baeldung/sort/ArraySortUnitTest.java (98%) diff --git a/core-java-modules/core-java-arrays-2/README.md b/core-java-modules/core-java-arrays-2/README.md index c4ae3f03f7..a78b3327b6 100644 --- a/core-java-modules/core-java-arrays-2/README.md +++ b/core-java-modules/core-java-arrays-2/README.md @@ -13,5 +13,4 @@ This module contains articles about Java arrays - [Removing an Element from an Array in Java](https://www.baeldung.com/java-array-remove-element) - [Removing the First Element of an Array](https://www.baeldung.com/java-array-remove-first-element) - [Adding an Element to a Java Array vs an ArrayList](https://www.baeldung.com/java-add-element-to-array-vs-list) -- [Arrays.sort vs Arrays.parallelSort](https://www.baeldung.com/java-arrays-sort-vs-parallelsort) - [[<-- Prev]](/core-java-modules/core-java-arrays) diff --git a/core-java-modules/core-java-arrays-sorting/README.md b/core-java-modules/core-java-arrays-sorting/README.md new file mode 100644 index 0000000000..f83dd43526 --- /dev/null +++ b/core-java-modules/core-java-arrays-sorting/README.md @@ -0,0 +1,9 @@ +## Core Java Arrays - Sorting + +This module contains articles about sorting arrays in Java + +### Relevant Articles: +- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays) +- [Checking If an Array Is Sorted in Java](https://www.baeldung.com/java-check-sorted-array) +- [How to Reverse an Array in Java](http://www.baeldung.com/java-invert-array) +- [Arrays.sort vs Arrays.parallelSort](https://www.baeldung.com/java-arrays-sort-vs-parallelsort) diff --git a/core-java-modules/core-java-arrays-sorting/pom.xml b/core-java-modules/core-java-arrays-sorting/pom.xml new file mode 100644 index 0000000000..127d921b2a --- /dev/null +++ b/core-java-modules/core-java-arrays-sorting/pom.xml @@ -0,0 +1,87 @@ + + + + core-java-modules + com.baeldung.core-java-modules + 1.0.0-SNAPSHOT + ../pom.xml + + 4.0.0 + + core-java-arrays-sorting + core-java-arrays-sorting + jar + + + + + org.apache.maven.plugins + maven-shade-plugin + ${shade.plugin.version} + + + package + + shade + + + benchmarks + + + org.openjdk.jmh.Main + + + + + + + + + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + com.google.guava + guava + ${guava.version} + + + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + + + 3.2.0 + + 3.9 + 28.2-jre + + 1.19 + + 3.10.0 + + \ No newline at end of file diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayInverter.java b/core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/array/ArrayInverter.java similarity index 100% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayInverter.java rename to core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/array/ArrayInverter.java diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SortedArrayChecker.java b/core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/array/SortedArrayChecker.java similarity index 97% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SortedArrayChecker.java rename to core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/array/SortedArrayChecker.java index 78a9a8f4d1..8fa64972f2 100644 --- a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SortedArrayChecker.java +++ b/core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/array/SortedArrayChecker.java @@ -1,7 +1,5 @@ package com.baeldung.array; -import com.baeldung.arraycopy.model.Employee; - import java.util.Comparator; public class SortedArrayChecker { diff --git a/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/arraysort/ArraySortingBenchmark.java b/core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/arraysort/ArraySortingBenchmark.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/arraysort/ArraySortingBenchmark.java rename to core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/arraysort/ArraySortingBenchmark.java diff --git a/core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/sort/Employee.java b/core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/sort/Employee.java new file mode 100644 index 0000000000..e9c737b74b --- /dev/null +++ b/core-java-modules/core-java-arrays-sorting/src/main/java/com/baeldung/sort/Employee.java @@ -0,0 +1,48 @@ +package com.baeldung.sort; + +import java.io.Serializable; + +public class Employee implements Serializable { + private static final long serialVersionUID = -2454619097207585825L; + private int id; + private String name; + private int age; + + public Employee() { + } + + public Employee(int id, String name) { + this.id = id; + this.name = name; + } + + public Employee(int id, String name, int age) { + this.id = id; + this.name = name; + this.age = age; + } + + public int getAge() { + return age; + } + + public int getId() { + return id; + } + + public void setAge(int age) { + this.age = age; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/ArrayInverterUnitTest.java b/core-java-modules/core-java-arrays-sorting/src/test/java/com/baeldung/array/ArrayInverterUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/ArrayInverterUnitTest.java rename to core-java-modules/core-java-arrays-sorting/src/test/java/com/baeldung/array/ArrayInverterUnitTest.java diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/SortedArrayCheckerUnitTest.java b/core-java-modules/core-java-arrays-sorting/src/test/java/com/baeldung/array/SortedArrayCheckerUnitTest.java similarity index 98% rename from core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/SortedArrayCheckerUnitTest.java rename to core-java-modules/core-java-arrays-sorting/src/test/java/com/baeldung/array/SortedArrayCheckerUnitTest.java index 7971e0eab7..5411dcba72 100644 --- a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/SortedArrayCheckerUnitTest.java +++ b/core-java-modules/core-java-arrays-sorting/src/test/java/com/baeldung/array/SortedArrayCheckerUnitTest.java @@ -1,6 +1,6 @@ package com.baeldung.array; -import com.baeldung.arraycopy.model.Employee; +import com.baeldung.sort.Employee; import org.junit.Before; import org.junit.Test; diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/arraysort/SortComparisonUnitTest.java b/core-java-modules/core-java-arrays-sorting/src/test/java/com/baeldung/arraysort/SortComparisonUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/arraysort/SortComparisonUnitTest.java rename to core-java-modules/core-java-arrays-sorting/src/test/java/com/baeldung/arraysort/SortComparisonUnitTest.java diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/sort/ArraySortUnitTest.java b/core-java-modules/core-java-arrays-sorting/src/test/java/com/baeldung/sort/ArraySortUnitTest.java similarity index 98% rename from core-java-modules/core-java-arrays/src/test/java/com/baeldung/sort/ArraySortUnitTest.java rename to core-java-modules/core-java-arrays-sorting/src/test/java/com/baeldung/sort/ArraySortUnitTest.java index 59035738fe..b89a870c51 100644 --- a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/sort/ArraySortUnitTest.java +++ b/core-java-modules/core-java-arrays-sorting/src/test/java/com/baeldung/sort/ArraySortUnitTest.java @@ -1,6 +1,5 @@ package com.baeldung.sort; -import com.baeldung.arraycopy.model.Employee; import org.junit.Before; import org.junit.Test; @@ -86,5 +85,4 @@ public class ArraySortUnitTest { assertArrayEquals(new Employee[]{david, john, mary}, employees); } - } diff --git a/core-java-modules/core-java-arrays/README.md b/core-java-modules/core-java-arrays/README.md index 9d9db9ab81..94351bbad6 100644 --- a/core-java-modules/core-java-arrays/README.md +++ b/core-java-modules/core-java-arrays/README.md @@ -10,7 +10,4 @@ This module contains articles about Java arrays - [Multi-Dimensional Arrays In Java](https://www.baeldung.com/java-jagged-arrays) - [Find Sum and Average in a Java Array](https://www.baeldung.com/java-array-sum-average) - [Arrays in Java: A Reference Guide](https://www.baeldung.com/java-arrays-guide) -- [How to Reverse an Array in Java](http://www.baeldung.com/java-invert-array) -- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays) -- [Checking If an Array Is Sorted in Java](https://www.baeldung.com/java-check-sorted-array) - [[More -->]](/core-java-modules/core-java-arrays-2) diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 00ef24be92..aba97f4826 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -122,6 +122,7 @@ pre-jpms + core-java-arrays-sorting
From 0593fce8a3def726abc84d91fec72f5941d66b86 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Fri, 10 Apr 2020 20:54:17 +0200 Subject: [PATCH 154/194] [JAVA-616] core-java-arrays-guides * Creation * Moved code from https://www.baeldung.com/java-arrays-guide * Moved code from https://www.baeldung.com/java-util-arrays --- .../core-java-arrays-guides/README.md | 7 ++++ .../core-java-arrays-guides/pom.xml | 32 +++++++++++++++++++ .../baeldung/array/ArrayReferenceGuide.java | 0 .../arrays/ParallelPrefixBenchmark.java | 0 .../com/baeldung/arrays/ArraysUnitTest.java | 0 core-java-modules/core-java-arrays/README.md | 2 -- core-java-modules/pom.xml | 1 + 7 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 core-java-modules/core-java-arrays-guides/README.md create mode 100644 core-java-modules/core-java-arrays-guides/pom.xml rename core-java-modules/{core-java-arrays => core-java-arrays-guides}/src/main/java/com/baeldung/array/ArrayReferenceGuide.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-guides}/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-guides}/src/test/java/com/baeldung/arrays/ArraysUnitTest.java (100%) diff --git a/core-java-modules/core-java-arrays-guides/README.md b/core-java-modules/core-java-arrays-guides/README.md new file mode 100644 index 0000000000..2e66080002 --- /dev/null +++ b/core-java-modules/core-java-arrays-guides/README.md @@ -0,0 +1,7 @@ +## Core Java Arrays - Guides + +This module contains complete guides about arrays in Java + +### Relevant Articles: +- [Arrays in Java: A Reference Guide](https://www.baeldung.com/java-arrays-guide) +- [Guide to the java.util.Arrays Class](https://www.baeldung.com/java-util-arrays) \ No newline at end of file diff --git a/core-java-modules/core-java-arrays-guides/pom.xml b/core-java-modules/core-java-arrays-guides/pom.xml new file mode 100644 index 0000000000..ef718d5117 --- /dev/null +++ b/core-java-modules/core-java-arrays-guides/pom.xml @@ -0,0 +1,32 @@ + + + + core-java-modules + com.baeldung.core-java-modules + 1.0.0-SNAPSHOT + + 4.0.0 + + core-java-arrays-guides + core-java-arrays-guides + jar + + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + + + 1.19 + + \ No newline at end of file diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayReferenceGuide.java b/core-java-modules/core-java-arrays-guides/src/main/java/com/baeldung/array/ArrayReferenceGuide.java similarity index 100% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayReferenceGuide.java rename to core-java-modules/core-java-arrays-guides/src/main/java/com/baeldung/array/ArrayReferenceGuide.java diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java b/core-java-modules/core-java-arrays-guides/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java similarity index 100% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java rename to core-java-modules/core-java-arrays-guides/src/main/java/com/baeldung/arrays/ParallelPrefixBenchmark.java diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java b/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/arrays/ArraysUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays/src/test/java/com/baeldung/arrays/ArraysUnitTest.java rename to core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/arrays/ArraysUnitTest.java diff --git a/core-java-modules/core-java-arrays/README.md b/core-java-modules/core-java-arrays/README.md index 94351bbad6..05c316cf7e 100644 --- a/core-java-modules/core-java-arrays/README.md +++ b/core-java-modules/core-java-arrays/README.md @@ -6,8 +6,6 @@ This module contains articles about Java arrays - [How to Copy an Array in Java](https://www.baeldung.com/java-array-copy) - [Check if a Java Array Contains a Value](https://www.baeldung.com/java-array-contains-value) - [Initializing Arrays in Java](https://www.baeldung.com/java-initialize-array) -- [Guide to the java.util.Arrays Class](https://www.baeldung.com/java-util-arrays) - [Multi-Dimensional Arrays In Java](https://www.baeldung.com/java-jagged-arrays) - [Find Sum and Average in a Java Array](https://www.baeldung.com/java-array-sum-average) -- [Arrays in Java: A Reference Guide](https://www.baeldung.com/java-arrays-guide) - [[More -->]](/core-java-modules/core-java-arrays-2) diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index aba97f4826..b23b7ba8f4 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -123,6 +123,7 @@ pre-jpms core-java-arrays-sorting + core-java-arrays-guides
From 6af4961a79bc5d493f8bf36b86718600b8908d0b Mon Sep 17 00:00:00 2001 From: dupirefr Date: Fri, 10 Apr 2020 21:01:14 +0200 Subject: [PATCH 155/194] [JAVA-616] core-java-arrays-multidimensional * Creation * Moved code from https://www.baeldung.com/java-jagged-arrays * Moved code from https://www.baeldung.com/java-loop-diagonal-array --- core-java-modules/core-java-arrays-2/README.md | 1 - .../core-java-arrays-multidimensional/README.md | 7 +++++++ .../core-java-arrays-multidimensional/pom.xml | 15 +++++++++++++++ .../com/baeldung/array/MultiDimensionalArray.java | 0 .../baeldung/array/looping/LoopDiagonally.java | 0 .../array/MultiDimensionalArrayUnitTest.java | 0 .../array/looping/LoopDiagonallyUnitTest.java | 0 core-java-modules/core-java-arrays/README.md | 1 - core-java-modules/pom.xml | 1 + 9 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 core-java-modules/core-java-arrays-multidimensional/README.md create mode 100644 core-java-modules/core-java-arrays-multidimensional/pom.xml rename core-java-modules/{core-java-arrays => core-java-arrays-multidimensional}/src/main/java/com/baeldung/array/MultiDimensionalArray.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-multidimensional}/src/main/java/com/baeldung/array/looping/LoopDiagonally.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-multidimensional}/src/test/java/com/baeldung/array/MultiDimensionalArrayUnitTest.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-multidimensional}/src/test/java/com/baeldung/array/looping/LoopDiagonallyUnitTest.java (100%) diff --git a/core-java-modules/core-java-arrays-2/README.md b/core-java-modules/core-java-arrays-2/README.md index a78b3327b6..07c171dcd5 100644 --- a/core-java-modules/core-java-arrays-2/README.md +++ b/core-java-modules/core-java-arrays-2/README.md @@ -5,7 +5,6 @@ This module contains articles about Java arrays ## Relevant Articles - [Extending an Array’s Length](https://www.baeldung.com/java-array-add-element-at-the-end) -- [Looping Diagonally Through a 2d Java Array](https://www.baeldung.com/java-loop-diagonal-array) - [Converting Between Stream and Array in Java](https://www.baeldung.com/java-stream-to-array) - [Convert a Float to a Byte Array in Java](https://www.baeldung.com/java-convert-float-to-byte-array) - [Array Operations in Java](https://www.baeldung.com/java-common-array-operations) diff --git a/core-java-modules/core-java-arrays-multidimensional/README.md b/core-java-modules/core-java-arrays-multidimensional/README.md new file mode 100644 index 0000000000..d92747a4fb --- /dev/null +++ b/core-java-modules/core-java-arrays-multidimensional/README.md @@ -0,0 +1,7 @@ +## Core Java Arrays - Multidimensional + +This module contains articles about multidimensional arrays in Java + +### Relevant Articles: +- [Multi-Dimensional Arrays In Java](https://www.baeldung.com/java-jagged-arrays) +- [Looping Diagonally Through a 2d Java Array](https://www.baeldung.com/java-loop-diagonal-array) \ No newline at end of file diff --git a/core-java-modules/core-java-arrays-multidimensional/pom.xml b/core-java-modules/core-java-arrays-multidimensional/pom.xml new file mode 100644 index 0000000000..6e49a20521 --- /dev/null +++ b/core-java-modules/core-java-arrays-multidimensional/pom.xml @@ -0,0 +1,15 @@ + + + + core-java-modules + com.baeldung.core-java-modules + 1.0.0-SNAPSHOT + + 4.0.0 + + core-java-arrays-multidimensional + core-java-arrays-multidimensional + jar + \ No newline at end of file diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/MultiDimensionalArray.java b/core-java-modules/core-java-arrays-multidimensional/src/main/java/com/baeldung/array/MultiDimensionalArray.java similarity index 100% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/MultiDimensionalArray.java rename to core-java-modules/core-java-arrays-multidimensional/src/main/java/com/baeldung/array/MultiDimensionalArray.java diff --git a/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/looping/LoopDiagonally.java b/core-java-modules/core-java-arrays-multidimensional/src/main/java/com/baeldung/array/looping/LoopDiagonally.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/looping/LoopDiagonally.java rename to core-java-modules/core-java-arrays-multidimensional/src/main/java/com/baeldung/array/looping/LoopDiagonally.java diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/MultiDimensionalArrayUnitTest.java b/core-java-modules/core-java-arrays-multidimensional/src/test/java/com/baeldung/array/MultiDimensionalArrayUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/MultiDimensionalArrayUnitTest.java rename to core-java-modules/core-java-arrays-multidimensional/src/test/java/com/baeldung/array/MultiDimensionalArrayUnitTest.java diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/looping/LoopDiagonallyUnitTest.java b/core-java-modules/core-java-arrays-multidimensional/src/test/java/com/baeldung/array/looping/LoopDiagonallyUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/looping/LoopDiagonallyUnitTest.java rename to core-java-modules/core-java-arrays-multidimensional/src/test/java/com/baeldung/array/looping/LoopDiagonallyUnitTest.java diff --git a/core-java-modules/core-java-arrays/README.md b/core-java-modules/core-java-arrays/README.md index 05c316cf7e..7b5f21a1e6 100644 --- a/core-java-modules/core-java-arrays/README.md +++ b/core-java-modules/core-java-arrays/README.md @@ -6,6 +6,5 @@ This module contains articles about Java arrays - [How to Copy an Array in Java](https://www.baeldung.com/java-array-copy) - [Check if a Java Array Contains a Value](https://www.baeldung.com/java-array-contains-value) - [Initializing Arrays in Java](https://www.baeldung.com/java-initialize-array) -- [Multi-Dimensional Arrays In Java](https://www.baeldung.com/java-jagged-arrays) - [Find Sum and Average in a Java Array](https://www.baeldung.com/java-array-sum-average) - [[More -->]](/core-java-modules/core-java-arrays-2) diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index b23b7ba8f4..20a2add836 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -124,6 +124,7 @@ pre-jpms core-java-arrays-sorting core-java-arrays-guides + core-java-arrays-multidimensional
From dcd863f5d67dea7c0533cbd04a234507ede70725 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Fri, 10 Apr 2020 21:08:02 +0200 Subject: [PATCH 156/194] [JAVA-616] core-java-arrays-convert * Creation * Moved code from https://www.baeldung.com/java-convert-float-to-byte-array * Moved code from https://www.baeldung.com/java-stream-to-array --- .../core-java-arrays-2/README.md | 2 -- .../core-java-arrays-convert/README.md | 7 +++++ .../core-java-arrays-convert/pom.xml | 27 +++++++++++++++++++ .../array/conversions/FloatToByteArray.java | 0 .../conversions/StreamArrayConversion.java | 0 .../conversions/FloatToByteArrayUnitTest.java | 0 .../StreamArrayConversionUnitTest.java | 0 core-java-modules/pom.xml | 1 + 8 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 core-java-modules/core-java-arrays-convert/README.md create mode 100644 core-java-modules/core-java-arrays-convert/pom.xml rename core-java-modules/{core-java-arrays-2 => core-java-arrays-convert}/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-convert}/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-convert}/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-convert}/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java (100%) diff --git a/core-java-modules/core-java-arrays-2/README.md b/core-java-modules/core-java-arrays-2/README.md index 07c171dcd5..eefc6aa787 100644 --- a/core-java-modules/core-java-arrays-2/README.md +++ b/core-java-modules/core-java-arrays-2/README.md @@ -5,8 +5,6 @@ This module contains articles about Java arrays ## Relevant Articles - [Extending an Array’s Length](https://www.baeldung.com/java-array-add-element-at-the-end) -- [Converting Between Stream and Array in Java](https://www.baeldung.com/java-stream-to-array) -- [Convert a Float to a Byte Array in Java](https://www.baeldung.com/java-convert-float-to-byte-array) - [Array Operations in Java](https://www.baeldung.com/java-common-array-operations) - [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection) - [Removing an Element from an Array in Java](https://www.baeldung.com/java-array-remove-element) diff --git a/core-java-modules/core-java-arrays-convert/README.md b/core-java-modules/core-java-arrays-convert/README.md new file mode 100644 index 0000000000..4bd060a246 --- /dev/null +++ b/core-java-modules/core-java-arrays-convert/README.md @@ -0,0 +1,7 @@ +## Core Java Arrays - Conversions + +This module contains articles about arrays conversion in Java + +## Relevant Articles +- [Convert a Float to a Byte Array in Java](https://www.baeldung.com/java-convert-float-to-byte-array) +- [Converting Between Stream and Array in Java](https://www.baeldung.com/java-stream-to-array) diff --git a/core-java-modules/core-java-arrays-convert/pom.xml b/core-java-modules/core-java-arrays-convert/pom.xml new file mode 100644 index 0000000000..bd50289f47 --- /dev/null +++ b/core-java-modules/core-java-arrays-convert/pom.xml @@ -0,0 +1,27 @@ + + + + core-java-modules + com.baeldung.core-java-modules + 1.0.0-SNAPSHOT + + 4.0.0 + + core-java-arrays-convert + core-java-arrays-convert + jar + + + + com.google.guava + guava + ${guava.version} + + + + + 28.2-jre + + \ No newline at end of file diff --git a/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java b/core-java-modules/core-java-arrays-convert/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java rename to core-java-modules/core-java-arrays-convert/src/main/java/com/baeldung/array/conversions/FloatToByteArray.java diff --git a/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java b/core-java-modules/core-java-arrays-convert/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java rename to core-java-modules/core-java-arrays-convert/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java b/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java rename to core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/FloatToByteArrayUnitTest.java diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java b/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java rename to core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 20a2add836..9926e7781a 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -125,6 +125,7 @@ core-java-arrays-sorting core-java-arrays-guides core-java-arrays-multidimensional + core-java-arrays-convert
From e36771a76366ab2fcfcd19c0a5ce8cfb97446fc4 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Fri, 10 Apr 2020 21:16:30 +0200 Subject: [PATCH 157/194] [JAVA-616] core-java-arrays-operations-basic * Creation * Moved code from https://www.baeldung.com/java-initialize-array * Moved code from https://www.baeldung.com/java-common-array-operations * Moved code from https://www.baeldung.com/java-add-element-to-array-vs-list * Moved code from https://www.baeldung.com/java-array-contains-value * Moved code from https://www.baeldung.com/java-array-remove-element * Moved code from https://www.baeldung.com/java-array-remove-first-element * Moved code from https://www.baeldung.com/java-array-add-element-at-the-end --- .../core-java-arrays-2/README.md | 5 -- .../ArraysIntersectionOperations.java | 27 +++++++ .../operations/IntersectionUnitTest.java | 2 +- .../README.md | 19 +++++ .../core-java-arrays-operations-basic/pom.xml | 78 +++++++++++++++++++ .../array/AddElementToEndOfArray.java | 0 .../baeldung/array/ArrayBenchmarkRunner.java | 2 +- .../com/baeldung/array/ArrayInitializer.java | 0 .../array/RemoveElementFromAnArray.java | 0 .../baeldung/array/SearchArrayBenchmark.java} | 2 +- .../array/operations/ArrayOperations.java | 0 .../operations/ArrayListOperations.java | 0 .../array/AddElementToEndOfArrayUnitTest.java | 0 .../array/ArrayInitializerUnitTest.java | 0 .../RemoveElementFromAnArrayUnitTest.java | 0 .../operations/ArrayOperationsUnitTest.java | 0 .../RemoveFirstElementUnitTest.java | 0 .../ArrayListOperationsUnitTest.java | 0 core-java-modules/core-java-arrays/README.md | 2 - core-java-modules/pom.xml | 1 + 20 files changed, 128 insertions(+), 10 deletions(-) create mode 100644 core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/operations/ArraysIntersectionOperations.java create mode 100644 core-java-modules/core-java-arrays-operations-basic/README.md create mode 100644 core-java-modules/core-java-arrays-operations-basic/pom.xml rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-basic}/src/main/java/com/baeldung/array/AddElementToEndOfArray.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-operations-basic}/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java (86%) rename core-java-modules/{core-java-arrays => core-java-arrays-operations-basic}/src/main/java/com/baeldung/array/ArrayInitializer.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-basic}/src/main/java/com/baeldung/array/RemoveElementFromAnArray.java (100%) rename core-java-modules/{core-java-arrays/src/main/java/com/baeldung/array/SearchArrayUnitTest.java => core-java-arrays-operations-basic/src/main/java/com/baeldung/array/SearchArrayBenchmark.java} (98%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-basic}/src/main/java/com/baeldung/array/operations/ArrayOperations.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-basic}/src/main/java/com/baeldung/arraylist/operations/ArrayListOperations.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-basic}/src/test/java/com/baeldung/array/AddElementToEndOfArrayUnitTest.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-operations-basic}/src/test/java/com/baeldung/array/ArrayInitializerUnitTest.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-basic}/src/test/java/com/baeldung/array/RemoveElementFromAnArrayUnitTest.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-basic}/src/test/java/com/baeldung/array/operations/ArrayOperationsUnitTest.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-basic}/src/test/java/com/baeldung/array/removefirst/RemoveFirstElementUnitTest.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-basic}/src/test/java/com/baeldung/arraylist/operations/ArrayListOperationsUnitTest.java (100%) diff --git a/core-java-modules/core-java-arrays-2/README.md b/core-java-modules/core-java-arrays-2/README.md index eefc6aa787..bde6c6cc1e 100644 --- a/core-java-modules/core-java-arrays-2/README.md +++ b/core-java-modules/core-java-arrays-2/README.md @@ -4,10 +4,5 @@ This module contains articles about Java arrays ## Relevant Articles -- [Extending an Array’s Length](https://www.baeldung.com/java-array-add-element-at-the-end) -- [Array Operations in Java](https://www.baeldung.com/java-common-array-operations) - [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection) -- [Removing an Element from an Array in Java](https://www.baeldung.com/java-array-remove-element) -- [Removing the First Element of an Array](https://www.baeldung.com/java-array-remove-first-element) -- [Adding an Element to a Java Array vs an ArrayList](https://www.baeldung.com/java-add-element-to-array-vs-list) - [[<-- Prev]](/core-java-modules/core-java-arrays) diff --git a/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/operations/ArraysIntersectionOperations.java b/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/operations/ArraysIntersectionOperations.java new file mode 100644 index 0000000000..6c4ce837ad --- /dev/null +++ b/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/operations/ArraysIntersectionOperations.java @@ -0,0 +1,27 @@ +package com.baeldung.array.operations; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.stream.Stream; + +public class ArraysIntersectionOperations { + + public static Integer[] intersectionSimple(final Integer[] a, final Integer[] b) { + return Stream.of(a) + .filter(Arrays.asList(b)::contains) + .toArray(Integer[]::new); + } + + public static Integer[] intersectionSet(final Integer[] a, final Integer[] b) { + return Stream.of(a) + .filter(Arrays.asList(b)::contains) + .distinct() + .toArray(Integer[]::new); + } + + public static Integer[] intersectionMultiSet(final Integer[] a, final Integer[] b) { + return Stream.of(a) + .filter(new LinkedList<>(Arrays.asList(b))::remove) + .toArray(Integer[]::new); + } +} diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java b/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java index 1560cc5701..b0d4a80b06 100644 --- a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java +++ b/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java @@ -2,7 +2,7 @@ package com.baeldung.array.operations; import org.junit.jupiter.api.Test; -import static com.baeldung.array.operations.ArrayOperations.*; +import static com.baeldung.array.operations.ArraysIntersectionOperations.*; import static org.assertj.core.api.Assertions.assertThat; class IntersectionUnitTest { diff --git a/core-java-modules/core-java-arrays-operations-basic/README.md b/core-java-modules/core-java-arrays-operations-basic/README.md new file mode 100644 index 0000000000..914d5a71bd --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-basic/README.md @@ -0,0 +1,19 @@ +## Core Java Arrays - Basic Operations + +This module contains articles about basic operations on arrays in Java + +Basic operations would cover anything elementary we should expect to be able to achieve on a collection type: + +- Adding/Removing elements +- Getting elements +- Iterating + +### Relevant Articles: +- [Initializing Arrays in Java](https://www.baeldung.com/java-initialize-array) +- [Array Operations in Java](https://www.baeldung.com/java-common-array-operations) +- [Adding an Element to a Java Array vs an ArrayList](https://www.baeldung.com/java-add-element-to-array-vs-list) +- [Check if a Java Array Contains a Value](https://www.baeldung.com/java-array-contains-value) +- [Removing an Element from an Array in Java](https://www.baeldung.com/java-array-remove-element) +- [Removing the First Element of an Array](https://www.baeldung.com/java-array-remove-first-element) +- [Extending an Array’s Length](https://www.baeldung.com/java-array-add-element-at-the-end) +- [[More advanced operations -->]](/core-java-modules/core-java-arrays-operations-advanced) diff --git a/core-java-modules/core-java-arrays-operations-basic/pom.xml b/core-java-modules/core-java-arrays-operations-basic/pom.xml new file mode 100644 index 0000000000..4480c14bb2 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-basic/pom.xml @@ -0,0 +1,78 @@ + + + + core-java-modules + com.baeldung.core-java-modules + 1.0.0-SNAPSHOT + + 4.0.0 + + core-java-arrays-operations-basic + core-java-arrays-operations-basic + jar + + + + + org.apache.maven.plugins + maven-shade-plugin + ${shade.plugin.version} + + + package + + shade + + + benchmarks + + + org.openjdk.jmh.Main + + + + + + + + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + + + 3.2.0 + + 3.9 + + 1.19 + + 3.10.0 + + \ No newline at end of file diff --git a/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/AddElementToEndOfArray.java b/core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/AddElementToEndOfArray.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/AddElementToEndOfArray.java rename to core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/AddElementToEndOfArray.java diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java b/core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java similarity index 86% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java rename to core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java index f35064b783..30c3978a3a 100644 --- a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java +++ b/core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/ArrayBenchmarkRunner.java @@ -9,7 +9,7 @@ public class ArrayBenchmarkRunner { public static void main(String[] args) throws Exception { Options options = new OptionsBuilder() - .include(SearchArrayUnitTest.class.getSimpleName()).threads(1) + .include(SearchArrayBenchmark.class.getSimpleName()).threads(1) .forks(1).shouldFailOnError(true).shouldDoGC(true) .jvmArgs("-server").build(); diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayInitializer.java b/core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/ArrayInitializer.java similarity index 100% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/ArrayInitializer.java rename to core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/ArrayInitializer.java diff --git a/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/RemoveElementFromAnArray.java b/core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/RemoveElementFromAnArray.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/RemoveElementFromAnArray.java rename to core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/RemoveElementFromAnArray.java diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SearchArrayUnitTest.java b/core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/SearchArrayBenchmark.java similarity index 98% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SearchArrayUnitTest.java rename to core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/SearchArrayBenchmark.java index bed58356cb..fc4b513250 100644 --- a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SearchArrayUnitTest.java +++ b/core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/SearchArrayBenchmark.java @@ -8,7 +8,7 @@ import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5) @OutputTimeUnit(TimeUnit.MICROSECONDS) -public class SearchArrayUnitTest { +public class SearchArrayBenchmark { @State(Scope.Benchmark) public static class SearchData { diff --git a/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/operations/ArrayOperations.java b/core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/operations/ArrayOperations.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/operations/ArrayOperations.java rename to core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/array/operations/ArrayOperations.java diff --git a/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/arraylist/operations/ArrayListOperations.java b/core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/arraylist/operations/ArrayListOperations.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/arraylist/operations/ArrayListOperations.java rename to core-java-modules/core-java-arrays-operations-basic/src/main/java/com/baeldung/arraylist/operations/ArrayListOperations.java diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/AddElementToEndOfArrayUnitTest.java b/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/AddElementToEndOfArrayUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/AddElementToEndOfArrayUnitTest.java rename to core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/AddElementToEndOfArrayUnitTest.java diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/ArrayInitializerUnitTest.java b/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/ArrayInitializerUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/ArrayInitializerUnitTest.java rename to core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/ArrayInitializerUnitTest.java diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/RemoveElementFromAnArrayUnitTest.java b/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/RemoveElementFromAnArrayUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/RemoveElementFromAnArrayUnitTest.java rename to core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/RemoveElementFromAnArrayUnitTest.java diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/operations/ArrayOperationsUnitTest.java b/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/operations/ArrayOperationsUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/operations/ArrayOperationsUnitTest.java rename to core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/operations/ArrayOperationsUnitTest.java diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/removefirst/RemoveFirstElementUnitTest.java b/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/removefirst/RemoveFirstElementUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/removefirst/RemoveFirstElementUnitTest.java rename to core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/array/removefirst/RemoveFirstElementUnitTest.java diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/arraylist/operations/ArrayListOperationsUnitTest.java b/core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/arraylist/operations/ArrayListOperationsUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/arraylist/operations/ArrayListOperationsUnitTest.java rename to core-java-modules/core-java-arrays-operations-basic/src/test/java/com/baeldung/arraylist/operations/ArrayListOperationsUnitTest.java diff --git a/core-java-modules/core-java-arrays/README.md b/core-java-modules/core-java-arrays/README.md index 7b5f21a1e6..7c7e6d0add 100644 --- a/core-java-modules/core-java-arrays/README.md +++ b/core-java-modules/core-java-arrays/README.md @@ -4,7 +4,5 @@ This module contains articles about Java arrays ### Relevant Articles: - [How to Copy an Array in Java](https://www.baeldung.com/java-array-copy) -- [Check if a Java Array Contains a Value](https://www.baeldung.com/java-array-contains-value) -- [Initializing Arrays in Java](https://www.baeldung.com/java-initialize-array) - [Find Sum and Average in a Java Array](https://www.baeldung.com/java-array-sum-average) - [[More -->]](/core-java-modules/core-java-arrays-2) diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 9926e7781a..cf6e4c69cf 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -126,6 +126,7 @@ core-java-arrays-guides core-java-arrays-multidimensional core-java-arrays-convert + core-java-arrays-operations-basic
From 50530b81b499cf4ed9248b0baed519230572c40f Mon Sep 17 00:00:00 2001 From: dupirefr Date: Fri, 10 Apr 2020 21:45:37 +0200 Subject: [PATCH 158/194] [JAVA-616] core-java-arrays-operations-advanced * Creation * Moved code from https://www.baeldung.com/java-array-copy * Moved code from https://www.baeldung.com/java-arrays-deepequals * Moved code from https://www.baeldung.com/java-array-sum-average * Moved code from https://www.baeldung.com/java-array-intersection --- .../core-java-arrays-2/README.md | 1 - .../core-java-arrays-3/README.md | 1 - .../README.md | 16 +++++++++ .../pom.xml | 36 +++++++++++++++++++ .../baeldung/array/SumAndAverageInArray.java | 0 .../ArraysIntersectionOperations.java | 0 .../com/baeldung/arraycopy/model/Address.java | 0 .../baeldung/arraycopy/model/Employee.java | 0 .../array/SumAndAverageInArrayUnitTest.java | 0 .../operations/IntersectionUnitTest.java | 0 .../arraycopy/ArrayCopyUtilUnitTest.java | 0 .../deepequals/ArraysDeepEqualsUnitTest.java | 0 core-java-modules/core-java-arrays/README.md | 2 -- core-java-modules/pom.xml | 1 + 14 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 core-java-modules/core-java-arrays-operations-advanced/README.md create mode 100644 core-java-modules/core-java-arrays-operations-advanced/pom.xml rename core-java-modules/{core-java-arrays => core-java-arrays-operations-advanced}/src/main/java/com/baeldung/array/SumAndAverageInArray.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-advanced}/src/main/java/com/baeldung/array/operations/ArraysIntersectionOperations.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-operations-advanced}/src/main/java/com/baeldung/arraycopy/model/Address.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-operations-advanced}/src/main/java/com/baeldung/arraycopy/model/Employee.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-operations-advanced}/src/test/java/com/baeldung/array/SumAndAverageInArrayUnitTest.java (100%) rename core-java-modules/{core-java-arrays-2 => core-java-arrays-operations-advanced}/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java (100%) rename core-java-modules/{core-java-arrays => core-java-arrays-operations-advanced}/src/test/java/com/baeldung/arraycopy/ArrayCopyUtilUnitTest.java (100%) rename core-java-modules/{core-java-arrays-3 => core-java-arrays-operations-advanced}/src/test/java/com/baeldung/arrays/deepequals/ArraysDeepEqualsUnitTest.java (100%) diff --git a/core-java-modules/core-java-arrays-2/README.md b/core-java-modules/core-java-arrays-2/README.md index bde6c6cc1e..20a2ddec9f 100644 --- a/core-java-modules/core-java-arrays-2/README.md +++ b/core-java-modules/core-java-arrays-2/README.md @@ -4,5 +4,4 @@ This module contains articles about Java arrays ## Relevant Articles -- [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection) - [[<-- Prev]](/core-java-modules/core-java-arrays) diff --git a/core-java-modules/core-java-arrays-3/README.md b/core-java-modules/core-java-arrays-3/README.md index 255d3d097d..a96ddccabb 100644 --- a/core-java-modules/core-java-arrays-3/README.md +++ b/core-java-modules/core-java-arrays-3/README.md @@ -1,3 +1,2 @@ ### Relevant Articles: -- [Arrays.deepEquals](https://www.baeldung.com/java-arrays-deepequals) diff --git a/core-java-modules/core-java-arrays-operations-advanced/README.md b/core-java-modules/core-java-arrays-operations-advanced/README.md new file mode 100644 index 0000000000..71f9ce0ac6 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced/README.md @@ -0,0 +1,16 @@ +## Core Java Arrays - Advanced Operations + +This module contains articles about advanced operations on arrays in Java + +Advanced operations would be much logic or interactions with other arrays, such as: + +- Sum, average of elements +- Intersections +- ... + +### Relevant Articles: +- [How to Copy an Array in Java](https://www.baeldung.com/java-array-copy) +- [Arrays.deepEquals](https://www.baeldung.com/java-arrays-deepequals) +- [Find Sum and Average in a Java Array](https://www.baeldung.com/java-array-sum-average) +- [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection) +- [[More basic operations-->]](/core-java-modules/core-java-operations-basic) diff --git a/core-java-modules/core-java-arrays-operations-advanced/pom.xml b/core-java-modules/core-java-arrays-operations-advanced/pom.xml new file mode 100644 index 0000000000..8989e91189 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced/pom.xml @@ -0,0 +1,36 @@ + + + + core-java-modules + com.baeldung.core-java-modules + 1.0.0-SNAPSHOT + + 4.0.0 + + core-java-arrays-operations-advanced + core-java-arrays-operations-advanced + jar + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + + + 3.9 + + 3.10.0 + + \ No newline at end of file diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SumAndAverageInArray.java b/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/array/SumAndAverageInArray.java similarity index 100% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/array/SumAndAverageInArray.java rename to core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/array/SumAndAverageInArray.java diff --git a/core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/operations/ArraysIntersectionOperations.java b/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/array/operations/ArraysIntersectionOperations.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/main/java/com/baeldung/array/operations/ArraysIntersectionOperations.java rename to core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/array/operations/ArraysIntersectionOperations.java diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Address.java b/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraycopy/model/Address.java similarity index 100% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Address.java rename to core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraycopy/model/Address.java diff --git a/core-java-modules/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Employee.java b/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraycopy/model/Employee.java similarity index 100% rename from core-java-modules/core-java-arrays/src/main/java/com/baeldung/arraycopy/model/Employee.java rename to core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraycopy/model/Employee.java diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/SumAndAverageInArrayUnitTest.java b/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/array/SumAndAverageInArrayUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays/src/test/java/com/baeldung/array/SumAndAverageInArrayUnitTest.java rename to core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/array/SumAndAverageInArrayUnitTest.java diff --git a/core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java b/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-2/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java rename to core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java diff --git a/core-java-modules/core-java-arrays/src/test/java/com/baeldung/arraycopy/ArrayCopyUtilUnitTest.java b/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraycopy/ArrayCopyUtilUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays/src/test/java/com/baeldung/arraycopy/ArrayCopyUtilUnitTest.java rename to core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraycopy/ArrayCopyUtilUnitTest.java diff --git a/core-java-modules/core-java-arrays-3/src/test/java/com/baeldung/arrays/deepequals/ArraysDeepEqualsUnitTest.java b/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arrays/deepequals/ArraysDeepEqualsUnitTest.java similarity index 100% rename from core-java-modules/core-java-arrays-3/src/test/java/com/baeldung/arrays/deepequals/ArraysDeepEqualsUnitTest.java rename to core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arrays/deepequals/ArraysDeepEqualsUnitTest.java diff --git a/core-java-modules/core-java-arrays/README.md b/core-java-modules/core-java-arrays/README.md index 7c7e6d0add..efc6ab426d 100644 --- a/core-java-modules/core-java-arrays/README.md +++ b/core-java-modules/core-java-arrays/README.md @@ -3,6 +3,4 @@ This module contains articles about Java arrays ### Relevant Articles: -- [How to Copy an Array in Java](https://www.baeldung.com/java-array-copy) -- [Find Sum and Average in a Java Array](https://www.baeldung.com/java-array-sum-average) - [[More -->]](/core-java-modules/core-java-arrays-2) diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index cf6e4c69cf..414313f918 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -127,6 +127,7 @@ core-java-arrays-multidimensional core-java-arrays-convert core-java-arrays-operations-basic + core-java-arrays-operations-advanced From 91922d655394434ff244ad4d2a2d2a7699c53ee3 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Fri, 10 Apr 2020 22:02:20 +0200 Subject: [PATCH 159/194] [JAVA-616] Cleaning code * Removed core-java-arrays* modules * Updated core-java-module/pom.xml --- .../core-java-arrays-2/README.md | 7 - core-java-modules/core-java-arrays-2/pom.xml | 86 --------- .../core-java-arrays-3/README.md | 2 - core-java-modules/core-java-arrays-3/pom.xml | 32 ---- core-java-modules/core-java-arrays/README.md | 6 - core-java-modules/core-java-arrays/pom.xml | 180 ------------------ core-java-modules/pom.xml | 16 +- 7 files changed, 7 insertions(+), 322 deletions(-) delete mode 100644 core-java-modules/core-java-arrays-2/README.md delete mode 100644 core-java-modules/core-java-arrays-2/pom.xml delete mode 100644 core-java-modules/core-java-arrays-3/README.md delete mode 100644 core-java-modules/core-java-arrays-3/pom.xml delete mode 100644 core-java-modules/core-java-arrays/README.md delete mode 100644 core-java-modules/core-java-arrays/pom.xml diff --git a/core-java-modules/core-java-arrays-2/README.md b/core-java-modules/core-java-arrays-2/README.md deleted file mode 100644 index 20a2ddec9f..0000000000 --- a/core-java-modules/core-java-arrays-2/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## Core Java Arrays (Part 2) - -This module contains articles about Java arrays - -## Relevant Articles - -- [[<-- Prev]](/core-java-modules/core-java-arrays) diff --git a/core-java-modules/core-java-arrays-2/pom.xml b/core-java-modules/core-java-arrays-2/pom.xml deleted file mode 100644 index 1445a322d7..0000000000 --- a/core-java-modules/core-java-arrays-2/pom.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - 4.0.0 - core-java-arrays-2 - 0.1.0-SNAPSHOT - core-java-arrays-2 - jar - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../../parent-java - - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - org.openjdk.jmh - jmh-core - ${jmh.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh.version} - - - - org.assertj - assertj-core - ${assertj-core.version} - test - - - - - core-java-arrays-2 - - - src/main/resources - true - - - - - org.apache.maven.plugins - maven-shade-plugin - ${shade.plugin.version} - - - package - - shade - - - benchmarks - - - org.openjdk.jmh.Main - - - - - - - - - - - 1.19 - - 3.9 - - 3.10.0 - 3.2.0 - - - diff --git a/core-java-modules/core-java-arrays-3/README.md b/core-java-modules/core-java-arrays-3/README.md deleted file mode 100644 index a96ddccabb..0000000000 --- a/core-java-modules/core-java-arrays-3/README.md +++ /dev/null @@ -1,2 +0,0 @@ -### Relevant Articles: - diff --git a/core-java-modules/core-java-arrays-3/pom.xml b/core-java-modules/core-java-arrays-3/pom.xml deleted file mode 100644 index 210375b878..0000000000 --- a/core-java-modules/core-java-arrays-3/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - 4.0.0 - core-java-arrays-3 - 0.1.0-SNAPSHOT - core-java-arrays-3 - jar - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../../parent-java - - - - - org.assertj - assertj-core - ${assertj.version} - test - - - - - 3.14.0 - - - \ No newline at end of file diff --git a/core-java-modules/core-java-arrays/README.md b/core-java-modules/core-java-arrays/README.md deleted file mode 100644 index efc6ab426d..0000000000 --- a/core-java-modules/core-java-arrays/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Core Java Arrays - -This module contains articles about Java arrays - -### Relevant Articles: -- [[More -->]](/core-java-modules/core-java-arrays-2) diff --git a/core-java-modules/core-java-arrays/pom.xml b/core-java-modules/core-java-arrays/pom.xml deleted file mode 100644 index ea28eb25eb..0000000000 --- a/core-java-modules/core-java-arrays/pom.xml +++ /dev/null @@ -1,180 +0,0 @@ - - - 4.0.0 - core-java-arrays - 0.1.0-SNAPSHOT - core-java-arrays - jar - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../../parent-java - - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - - org.assertj - assertj-core - ${assertj-core.version} - test - - - org.openjdk.jmh - jmh-core - ${jmh-core.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh-generator-annprocess.version} - - - - - core-java-arrays - - - src/main/resources - true - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/libs - - - - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - java - com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed - - -Xmx300m - -XX:+UseParallelGC - -classpath - - com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven-javadoc-plugin.version} - - ${source.version} - ${target.version} - - - - - - - - integration - - - - org.apache.maven.plugins - maven-surefire-plugin - - - integration-test - - test - - - - **/*ManualTest.java - - - **/*IntegrationTest.java - **/*IntTest.java - - - - - - - json - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - run-benchmarks - - none - - exec - - - test - java - - -classpath - - org.openjdk.jmh.Main - .* - - - - - - - - - - - - - - 3.9 - - 1.19 - 1.19 - - - 3.10.0 - - - 3.0.0-M1 - 1.6.0 - 1.8 - 1.8 - - - diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 414313f918..b7454cc737 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -31,10 +31,14 @@ core-java-annotations - core-java-arrays - core-java-arrays-2 - core-java-arrays-3 + core-java-arrays-sorting + core-java-arrays-guides + core-java-arrays-multidimensional + core-java-arrays-convert + core-java-arrays-operations-basic + core-java-arrays-operations-advanced + core-java-collections core-java-collections-2 core-java-collections-3 @@ -122,12 +126,6 @@ pre-jpms - core-java-arrays-sorting - core-java-arrays-guides - core-java-arrays-multidimensional - core-java-arrays-convert - core-java-arrays-operations-basic - core-java-arrays-operations-advanced From 40fb82606a7a00044781ed96acf6132a88c6ee10 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Fri, 17 Apr 2020 21:05:33 +0200 Subject: [PATCH 160/194] [JAVA-616] Reworded operations modules descriptions --- .../core-java-arrays-operations-advanced/README.md | 9 +-------- .../core-java-arrays-operations-basic/README.md | 9 +-------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/core-java-modules/core-java-arrays-operations-advanced/README.md b/core-java-modules/core-java-arrays-operations-advanced/README.md index 71f9ce0ac6..af0c00641a 100644 --- a/core-java-modules/core-java-arrays-operations-advanced/README.md +++ b/core-java-modules/core-java-arrays-operations-advanced/README.md @@ -1,16 +1,9 @@ ## Core Java Arrays - Advanced Operations -This module contains articles about advanced operations on arrays in Java - -Advanced operations would be much logic or interactions with other arrays, such as: - -- Sum, average of elements -- Intersections -- ... +This module contains articles about advanced operations on arrays in Java. They assume some background knowledge with arrays in Java. ### Relevant Articles: - [How to Copy an Array in Java](https://www.baeldung.com/java-array-copy) - [Arrays.deepEquals](https://www.baeldung.com/java-arrays-deepequals) - [Find Sum and Average in a Java Array](https://www.baeldung.com/java-array-sum-average) - [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection) -- [[More basic operations-->]](/core-java-modules/core-java-operations-basic) diff --git a/core-java-modules/core-java-arrays-operations-basic/README.md b/core-java-modules/core-java-arrays-operations-basic/README.md index 914d5a71bd..ca81c23c98 100644 --- a/core-java-modules/core-java-arrays-operations-basic/README.md +++ b/core-java-modules/core-java-arrays-operations-basic/README.md @@ -1,12 +1,6 @@ ## Core Java Arrays - Basic Operations -This module contains articles about basic operations on arrays in Java - -Basic operations would cover anything elementary we should expect to be able to achieve on a collection type: - -- Adding/Removing elements -- Getting elements -- Iterating +This module contains articles about Java array fundamentals. They assume no previous background knowledge on working with arrays. ### Relevant Articles: - [Initializing Arrays in Java](https://www.baeldung.com/java-initialize-array) @@ -16,4 +10,3 @@ Basic operations would cover anything elementary we should expect to be able to - [Removing an Element from an Array in Java](https://www.baeldung.com/java-array-remove-element) - [Removing the First Element of an Array](https://www.baeldung.com/java-array-remove-first-element) - [Extending an Array’s Length](https://www.baeldung.com/java-array-add-element-at-the-end) -- [[More advanced operations -->]](/core-java-modules/core-java-arrays-operations-advanced) From 5e223df9d6468d2df6991974d63c9982f4b2f085 Mon Sep 17 00:00:00 2001 From: Krzysztof Woyke Date: Fri, 17 Apr 2020 22:11:57 +0200 Subject: [PATCH 161/194] BAEL-3992: Remove jnlp dependencies from the pom.xml --- jws/pom.xml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/jws/pom.xml b/jws/pom.xml index f867df8051..be42798fd1 100644 --- a/jws/pom.xml +++ b/jws/pom.xml @@ -14,21 +14,6 @@ 1.0.0-SNAPSHOT - - - OpenNMS Repository - https://repo.opennms.org/maven2/ - - - - - - javax.samples.jnlp - jnlp-servlet - ${jnlp-servlet.version} - - - ${project.artifactId} @@ -79,7 +64,6 @@ 3.0.2 - 1.6.0 From 1ec2d9a4ed2b57380462ef06d710c90dc434b371 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 18 Apr 2020 11:43:52 +0530 Subject: [PATCH 162/194] JAVA-627: Moved 2 articles from libraries-2 --- libraries-2/README.md | 2 - libraries-2/pom.xml | 26 +---- .../okhttp/ResponseDecoderUnitTest.java | 102 ------------------ .../com/baeldung/okhttp/SimpleEntity.java | 22 ---- 4 files changed, 1 insertion(+), 151 deletions(-) delete mode 100644 libraries-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java delete mode 100644 libraries-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java diff --git a/libraries-2/README.md b/libraries-2/README.md index eb45a3e426..edf513c6ee 100644 --- a/libraries-2/README.md +++ b/libraries-2/README.md @@ -14,11 +14,9 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m - [Guide to Java Parallel Collectors Library](https://www.baeldung.com/java-parallel-collectors) - [Templating with Handlebars](https://www.baeldung.com/handlebars) - [A Guide to Crawler4j](https://www.baeldung.com/crawler4j) -- [Decode an OkHttp JSON Response](https://www.baeldung.com/okhttp-json-response) - [Key Value Store with Chronicle Map](https://www.baeldung.com/java-chronicle-map) - [Guide to MapDB](https://www.baeldung.com/mapdb) - [A Guide to Apache Mesos](https://www.baeldung.com/apache-mesos) - [JasperReports with Spring](https://www.baeldung.com/spring-jasper) -- [Jetty ReactiveStreams HTTP Client](https://www.baeldung.com/jetty-reactivestreams-http-client) - More articles [[<-- prev]](/libraries) diff --git a/libraries-2/pom.xml b/libraries-2/pom.xml index 474ff563c2..3aa36c3f90 100644 --- a/libraries-2/pom.xml +++ b/libraries-2/pom.xml @@ -75,28 +75,7 @@ - - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - com.google.code.gson - gson - ${gson.version} - - - com.squareup.okhttp3 - mockwebserver - ${mockwebserver.version} - test - + edu.uci.ics crawler4j @@ -151,9 +130,6 @@ 2.1.4.RELEASE 0.28.3 1.1.0 - 3.14.2 - 2.8.5 - 3.14.2 4.1.2 6.6.0 5.1.9.RELEASE diff --git a/libraries-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java b/libraries-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java deleted file mode 100644 index 11a295031a..0000000000 --- a/libraries-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.baeldung.okhttp; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.Gson; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.ResponseBody; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import java.io.InputStreamReader; - -public class ResponseDecoderUnitTest { - - @Rule public ExpectedException exceptionRule = ExpectedException.none(); - - @Rule public MockWebServer server = new MockWebServer(); - - SimpleEntity sampleResponse; - - MockResponse mockResponse; - - OkHttpClient client; - - @Before - public void setUp() { - sampleResponse = new SimpleEntity("Baeldung"); - client = new OkHttpClient.Builder().build(); - mockResponse = new MockResponse() - .setResponseCode(200) - .setHeader("Content-Type", "application/json") - .setBody(new Gson().toJson(sampleResponse)); - } - - @Test - public void givenJacksonDecoder_whenGetStringOfResponse_thenExpectSimpleEntity() throws Exception { - server.enqueue(mockResponse); - Request request = new Request.Builder() - .url(server.url("")) - .build(); - ResponseBody responseBody = client - .newCall(request) - .execute() - .body(); - - Assert.assertNotNull(responseBody); - Assert.assertNotEquals(0, responseBody.contentLength()); - - ObjectMapper objectMapper = new ObjectMapper(); - SimpleEntity entity = objectMapper.readValue(responseBody.string(), SimpleEntity.class); - - Assert.assertNotNull(entity); - Assert.assertEquals(sampleResponse.getName(), entity.getName()); - } - - @Test - public void givenGsonDecoder_whenGetByteStreamOfResponse_thenExpectSimpleEntity() throws Exception { - server.enqueue(mockResponse); - Request request = new Request.Builder() - .url(server.url("")) - .build(); - ResponseBody responseBody = client - .newCall(request) - .execute() - .body(); - - Assert.assertNotNull(responseBody); - Assert.assertNotEquals(0, responseBody.contentLength()); - - Gson gson = new Gson(); - SimpleEntity entity = gson.fromJson(new InputStreamReader(responseBody.byteStream()), SimpleEntity.class); - - Assert.assertNotNull(entity); - Assert.assertEquals(sampleResponse.getName(), entity.getName()); - } - - @Test - public void givenGsonDecoder_whenGetStringOfResponse_thenExpectSimpleEntity() throws Exception { - server.enqueue(mockResponse); - Request request = new Request.Builder() - .url(server.url("")) - .build(); - ResponseBody responseBody = client - .newCall(request) - .execute() - .body(); - - Assert.assertNotNull(responseBody); - - Gson gson = new Gson(); - SimpleEntity entity = gson.fromJson(responseBody.string(), SimpleEntity.class); - - Assert.assertNotNull(entity); - Assert.assertEquals(sampleResponse.getName(), entity.getName()); - } - -} diff --git a/libraries-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java b/libraries-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java deleted file mode 100644 index 211e43e556..0000000000 --- a/libraries-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.okhttp; - -public class SimpleEntity { - protected String name; - - public SimpleEntity(String name) { - this.name = name; - } - - //no-arg constructor, getters and setters here - - public SimpleEntity() { - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} From c990a29bf76f956f4bfcbdbdc32d3eb843e1fea7 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 18 Apr 2020 11:44:19 +0530 Subject: [PATCH 163/194] JAVA-627: Moved 2 articles to libraries-http-2 --- libraries-http-2/README.md | 10 ++ libraries-http-2/pom.xml | 47 ++++++++ .../okhttp/ResponseDecoderUnitTest.java | 102 ++++++++++++++++++ .../com/baeldung/okhttp/SimpleEntity.java | 22 ++++ 4 files changed, 181 insertions(+) create mode 100644 libraries-http-2/README.md create mode 100644 libraries-http-2/pom.xml create mode 100644 libraries-http-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java create mode 100644 libraries-http-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java diff --git a/libraries-http-2/README.md b/libraries-http-2/README.md new file mode 100644 index 0000000000..5ba45eb4a9 --- /dev/null +++ b/libraries-http-2/README.md @@ -0,0 +1,10 @@ +## HTTP + +This module contains articles about HTTP libraries. + +### Relevant Articles: + +- [Jetty ReactiveStreams HTTP Client](https://www.baeldung.com/jetty-reactivestreams-http-client) +- [Decode an OkHttp JSON Response](https://www.baeldung.com/okhttp-json-response) +- More articles [[<-- prev]](/libraries-http) + diff --git a/libraries-http-2/pom.xml b/libraries-http-2/pom.xml new file mode 100644 index 0000000000..c0a4f6455d --- /dev/null +++ b/libraries-http-2/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + libraries-http-2 + libraries-http-2 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.google.code.gson + gson + ${gson.version} + + + com.squareup.okhttp3 + mockwebserver + ${mockwebserver.version} + test + + + + + 3.14.2 + 2.8.5 + 3.14.2 + 2.9.8 + + + diff --git a/libraries-http-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java b/libraries-http-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java new file mode 100644 index 0000000000..11a295031a --- /dev/null +++ b/libraries-http-2/src/test/java/com/baeldung/okhttp/ResponseDecoderUnitTest.java @@ -0,0 +1,102 @@ +package com.baeldung.okhttp; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.ResponseBody; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.InputStreamReader; + +public class ResponseDecoderUnitTest { + + @Rule public ExpectedException exceptionRule = ExpectedException.none(); + + @Rule public MockWebServer server = new MockWebServer(); + + SimpleEntity sampleResponse; + + MockResponse mockResponse; + + OkHttpClient client; + + @Before + public void setUp() { + sampleResponse = new SimpleEntity("Baeldung"); + client = new OkHttpClient.Builder().build(); + mockResponse = new MockResponse() + .setResponseCode(200) + .setHeader("Content-Type", "application/json") + .setBody(new Gson().toJson(sampleResponse)); + } + + @Test + public void givenJacksonDecoder_whenGetStringOfResponse_thenExpectSimpleEntity() throws Exception { + server.enqueue(mockResponse); + Request request = new Request.Builder() + .url(server.url("")) + .build(); + ResponseBody responseBody = client + .newCall(request) + .execute() + .body(); + + Assert.assertNotNull(responseBody); + Assert.assertNotEquals(0, responseBody.contentLength()); + + ObjectMapper objectMapper = new ObjectMapper(); + SimpleEntity entity = objectMapper.readValue(responseBody.string(), SimpleEntity.class); + + Assert.assertNotNull(entity); + Assert.assertEquals(sampleResponse.getName(), entity.getName()); + } + + @Test + public void givenGsonDecoder_whenGetByteStreamOfResponse_thenExpectSimpleEntity() throws Exception { + server.enqueue(mockResponse); + Request request = new Request.Builder() + .url(server.url("")) + .build(); + ResponseBody responseBody = client + .newCall(request) + .execute() + .body(); + + Assert.assertNotNull(responseBody); + Assert.assertNotEquals(0, responseBody.contentLength()); + + Gson gson = new Gson(); + SimpleEntity entity = gson.fromJson(new InputStreamReader(responseBody.byteStream()), SimpleEntity.class); + + Assert.assertNotNull(entity); + Assert.assertEquals(sampleResponse.getName(), entity.getName()); + } + + @Test + public void givenGsonDecoder_whenGetStringOfResponse_thenExpectSimpleEntity() throws Exception { + server.enqueue(mockResponse); + Request request = new Request.Builder() + .url(server.url("")) + .build(); + ResponseBody responseBody = client + .newCall(request) + .execute() + .body(); + + Assert.assertNotNull(responseBody); + + Gson gson = new Gson(); + SimpleEntity entity = gson.fromJson(responseBody.string(), SimpleEntity.class); + + Assert.assertNotNull(entity); + Assert.assertEquals(sampleResponse.getName(), entity.getName()); + } + +} diff --git a/libraries-http-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java b/libraries-http-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java new file mode 100644 index 0000000000..211e43e556 --- /dev/null +++ b/libraries-http-2/src/test/java/com/baeldung/okhttp/SimpleEntity.java @@ -0,0 +1,22 @@ +package com.baeldung.okhttp; + +public class SimpleEntity { + protected String name; + + public SimpleEntity(String name) { + this.name = name; + } + + //no-arg constructor, getters and setters here + + public SimpleEntity() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} From c2ce41c539760ed954581e545db596b7a8270f4d Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 18 Apr 2020 11:44:56 +0530 Subject: [PATCH 164/194] JAVA-627: Added next link in README for libraries-http --- libraries-http/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries-http/README.md b/libraries-http/README.md index 1f065a9d4a..61b2904cee 100644 --- a/libraries-http/README.md +++ b/libraries-http/README.md @@ -14,3 +14,4 @@ This module contains articles about HTTP libraries. - [Creating REST Microservices with Javalin](https://www.baeldung.com/javalin-rest-microservices) - [A Quick Guide to Timeouts in OkHttp](https://www.baeldung.com/okhttp-timeouts) - [A Quick Guide to Post Requests with OkHttp](https://www.baeldung.com/okhttp-post) +- More articles [[next -->]](/libraries-http-2) From 24fb2dcccf1743fd8d800f4b25f50896373031d2 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 18 Apr 2020 11:45:39 +0530 Subject: [PATCH 165/194] JAVA-627: Added new module libraries-http-2 to main pom --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 9e3b354d74..f6eabfa653 100644 --- a/pom.xml +++ b/pom.xml @@ -505,6 +505,7 @@ libraries-data-db libraries-data-io libraries-http + libraries-http-2 libraries-io libraries-primitive libraries-security @@ -1017,6 +1018,7 @@ libraries-data-db libraries-data-io libraries-http + libraries-http-2 libraries-io libraries-primitive libraries-security From 744d2b5733c7641da2f0f129e9d293ce58356efc Mon Sep 17 00:00:00 2001 From: mikr Date: Sat, 18 Apr 2020 14:22:10 +0200 Subject: [PATCH 166/194] JAVA-617 Rename core-java-datetime-java8 to core-java-8-datetime --- .../README.md | 0 .../pom.xml | 8 ++++---- .../java/com/baeldung/localdate/LocalDateExample.java | 0 .../java/com/baeldung/random/LegacyRandomDateTimes.java | 0 .../main/java/com/baeldung/random/RandomDateTimes.java | 0 .../src/main/java/com/baeldung/random/RandomDates.java | 0 .../src/main/java/com/baeldung/random/RandomTimes.java | 0 .../com/baeldung/localdate/LocalDateExampleUnitTest.java | 0 .../baeldung/random/LegacyRandomDateTimesUnitTest.java | 0 .../java/com/baeldung/random/RandomDateTimesUnitTest.java | 0 .../java/com/baeldung/random/RandomDatesUnitTest.java | 0 .../java/com/baeldung/random/RandomTimesUnitTest.java | 0 .../README.md | 0 .../pom.xml | 8 ++++---- .../baeldung/date/comparison/DateTimeComparisonUtils.java | 0 .../date/comparison/LegacyDateComparisonUtils.java | 0 .../java/com/baeldung/datetime/UseDateTimeFormatter.java | 0 .../src/main/java/com/baeldung/datetime/UseDuration.java | 0 .../src/main/java/com/baeldung/datetime/UseLocalDate.java | 0 .../main/java/com/baeldung/datetime/UseLocalDateTime.java | 0 .../src/main/java/com/baeldung/datetime/UseLocalTime.java | 0 .../java/com/baeldung/datetime/UseOffsetDateTime.java | 0 .../src/main/java/com/baeldung/datetime/UsePeriod.java | 0 .../src/main/java/com/baeldung/datetime/UseToInstant.java | 0 .../main/java/com/baeldung/datetime/UseZonedDateTime.java | 0 .../baeldung/temporaladjuster/CustomTemporalAdjuster.java | 0 .../date/comparison/DateTimeComparisonUtilsUnitTest.java | 0 .../Java8DateTimeApiGeneralComparisonsUnitTest.java | 0 .../comparison/LegacyDateComparisonUtilsUnitTest.java | 0 .../test/java/com/baeldung/dateapi/ConversionExample.java | 0 .../java/com/baeldung/dateapi/JavaDurationUnitTest.java | 0 .../java/com/baeldung/dateapi/JavaPeriodUnitTest.java | 0 .../java/com/baeldung/dateapi/JavaUtilTimeUnitTest.java | 0 .../baeldung/datetime/UseDateTimeFormatterUnitTest.java | 0 .../com/baeldung/datetime/UseLocalDateTimeUnitTest.java | 0 .../java/com/baeldung/datetime/UseLocalDateUnitTest.java | 0 .../java/com/baeldung/datetime/UseLocalTimeUnitTest.java | 0 .../com/baeldung/datetime/UseOffsetDateTimeUnitTest.java | 0 .../java/com/baeldung/datetime/UsePeriodUnitTest.java | 0 .../java/com/baeldung/datetime/UseTimeZoneUnitTest.java | 0 .../java/com/baeldung/datetime/UseToInstantUnitTest.java | 0 .../com/baeldung/datetime/UseZonedDateTimeUnitTest.java | 0 .../temporaladjusters/CustomTemporalAdjusterUnitTest.java | 0 .../temporaladjusters/TemporalAdjustersUnitTest.java | 0 44 files changed, 8 insertions(+), 8 deletions(-) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/README.md (100%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/pom.xml (91%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/src/main/java/com/baeldung/localdate/LocalDateExample.java (100%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/src/main/java/com/baeldung/random/LegacyRandomDateTimes.java (100%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/src/main/java/com/baeldung/random/RandomDateTimes.java (100%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/src/main/java/com/baeldung/random/RandomDates.java (100%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/src/main/java/com/baeldung/random/RandomTimes.java (100%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/src/test/java/com/baeldung/localdate/LocalDateExampleUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/src/test/java/com/baeldung/random/LegacyRandomDateTimesUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/src/test/java/com/baeldung/random/RandomDateTimesUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/src/test/java/com/baeldung/random/RandomDatesUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8-2 => core-java-8-datetime-2}/src/test/java/com/baeldung/random/RandomTimesUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/README.md (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/pom.xml (91%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/date/comparison/DateTimeComparisonUtils.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/date/comparison/LegacyDateComparisonUtils.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/datetime/UseDateTimeFormatter.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/datetime/UseDuration.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/datetime/UseLocalDate.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/datetime/UseLocalDateTime.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/datetime/UseLocalTime.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/datetime/UseOffsetDateTime.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/datetime/UsePeriod.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/datetime/UseToInstant.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/datetime/UseZonedDateTime.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/main/java/com/baeldung/temporaladjuster/CustomTemporalAdjuster.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/date/comparison/DateTimeComparisonUtilsUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/date/comparison/Java8DateTimeApiGeneralComparisonsUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/date/comparison/LegacyDateComparisonUtilsUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/dateapi/ConversionExample.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/dateapi/JavaDurationUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/dateapi/JavaPeriodUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/dateapi/JavaUtilTimeUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/datetime/UseDateTimeFormatterUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/datetime/UseLocalDateTimeUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/datetime/UseLocalDateUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/datetime/UseLocalTimeUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/datetime/UseOffsetDateTimeUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/datetime/UsePeriodUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/datetime/UseTimeZoneUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/datetime/UseToInstantUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/datetime/UseZonedDateTimeUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/temporaladjusters/CustomTemporalAdjusterUnitTest.java (100%) rename core-java-modules/{core-java-datetime-java8 => core-java-8-datetime}/src/test/java/com/baeldung/temporaladjusters/TemporalAdjustersUnitTest.java (100%) diff --git a/core-java-modules/core-java-datetime-java8-2/README.md b/core-java-modules/core-java-8-datetime-2/README.md similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/README.md rename to core-java-modules/core-java-8-datetime-2/README.md diff --git a/core-java-modules/core-java-datetime-java8-2/pom.xml b/core-java-modules/core-java-8-datetime-2/pom.xml similarity index 91% rename from core-java-modules/core-java-datetime-java8-2/pom.xml rename to core-java-modules/core-java-8-datetime-2/pom.xml index a15113bddc..ce98b72781 100644 --- a/core-java-modules/core-java-datetime-java8-2/pom.xml +++ b/core-java-modules/core-java-8-datetime-2/pom.xml @@ -4,9 +4,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - core-java-datetime-java8 + core-java-8-datetime ${project.parent.version} - core-java-datetime-java8 + core-java-8-datetime jar @@ -64,8 +64,8 @@ - 1.9 - 1.9 + 1.8 + 1.8 2.10 3.6.1 diff --git a/core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/localdate/LocalDateExample.java b/core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/localdate/LocalDateExample.java similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/localdate/LocalDateExample.java rename to core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/localdate/LocalDateExample.java diff --git a/core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/LegacyRandomDateTimes.java b/core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/random/LegacyRandomDateTimes.java similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/LegacyRandomDateTimes.java rename to core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/random/LegacyRandomDateTimes.java diff --git a/core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomDateTimes.java b/core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/random/RandomDateTimes.java similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomDateTimes.java rename to core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/random/RandomDateTimes.java diff --git a/core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomDates.java b/core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/random/RandomDates.java similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomDates.java rename to core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/random/RandomDates.java diff --git a/core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomTimes.java b/core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/random/RandomTimes.java similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/src/main/java/com/baeldung/random/RandomTimes.java rename to core-java-modules/core-java-8-datetime-2/src/main/java/com/baeldung/random/RandomTimes.java diff --git a/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/localdate/LocalDateExampleUnitTest.java b/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/localdate/LocalDateExampleUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/localdate/LocalDateExampleUnitTest.java rename to core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/localdate/LocalDateExampleUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/LegacyRandomDateTimesUnitTest.java b/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/random/LegacyRandomDateTimesUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/LegacyRandomDateTimesUnitTest.java rename to core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/random/LegacyRandomDateTimesUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomDateTimesUnitTest.java b/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/random/RandomDateTimesUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomDateTimesUnitTest.java rename to core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/random/RandomDateTimesUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomDatesUnitTest.java b/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/random/RandomDatesUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomDatesUnitTest.java rename to core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/random/RandomDatesUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomTimesUnitTest.java b/core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/random/RandomTimesUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8-2/src/test/java/com/baeldung/random/RandomTimesUnitTest.java rename to core-java-modules/core-java-8-datetime-2/src/test/java/com/baeldung/random/RandomTimesUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/README.md b/core-java-modules/core-java-8-datetime/README.md similarity index 100% rename from core-java-modules/core-java-datetime-java8/README.md rename to core-java-modules/core-java-8-datetime/README.md diff --git a/core-java-modules/core-java-datetime-java8/pom.xml b/core-java-modules/core-java-8-datetime/pom.xml similarity index 91% rename from core-java-modules/core-java-datetime-java8/pom.xml rename to core-java-modules/core-java-8-datetime/pom.xml index a15113bddc..ce98b72781 100644 --- a/core-java-modules/core-java-datetime-java8/pom.xml +++ b/core-java-modules/core-java-8-datetime/pom.xml @@ -4,9 +4,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - core-java-datetime-java8 + core-java-8-datetime ${project.parent.version} - core-java-datetime-java8 + core-java-8-datetime jar @@ -64,8 +64,8 @@ - 1.9 - 1.9 + 1.8 + 1.8 2.10 3.6.1 diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/date/comparison/DateTimeComparisonUtils.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/date/comparison/DateTimeComparisonUtils.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/date/comparison/DateTimeComparisonUtils.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/date/comparison/DateTimeComparisonUtils.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/date/comparison/LegacyDateComparisonUtils.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/date/comparison/LegacyDateComparisonUtils.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/date/comparison/LegacyDateComparisonUtils.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/date/comparison/LegacyDateComparisonUtils.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseDateTimeFormatter.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseDateTimeFormatter.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseDateTimeFormatter.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseDateTimeFormatter.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseDuration.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseDuration.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseDuration.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseDuration.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseLocalDate.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseLocalDate.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseLocalDate.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseLocalDate.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseLocalDateTime.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseLocalDateTime.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseLocalDateTime.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseLocalDateTime.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseLocalTime.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseLocalTime.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseLocalTime.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseLocalTime.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseOffsetDateTime.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseOffsetDateTime.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseOffsetDateTime.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseOffsetDateTime.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UsePeriod.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UsePeriod.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UsePeriod.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UsePeriod.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseToInstant.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseToInstant.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseToInstant.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseToInstant.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseZonedDateTime.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseZonedDateTime.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/datetime/UseZonedDateTime.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/datetime/UseZonedDateTime.java diff --git a/core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/temporaladjuster/CustomTemporalAdjuster.java b/core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/temporaladjuster/CustomTemporalAdjuster.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/main/java/com/baeldung/temporaladjuster/CustomTemporalAdjuster.java rename to core-java-modules/core-java-8-datetime/src/main/java/com/baeldung/temporaladjuster/CustomTemporalAdjuster.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/date/comparison/DateTimeComparisonUtilsUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/date/comparison/DateTimeComparisonUtilsUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/date/comparison/DateTimeComparisonUtilsUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/date/comparison/DateTimeComparisonUtilsUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/date/comparison/Java8DateTimeApiGeneralComparisonsUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/date/comparison/Java8DateTimeApiGeneralComparisonsUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/date/comparison/Java8DateTimeApiGeneralComparisonsUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/date/comparison/Java8DateTimeApiGeneralComparisonsUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/date/comparison/LegacyDateComparisonUtilsUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/date/comparison/LegacyDateComparisonUtilsUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/date/comparison/LegacyDateComparisonUtilsUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/date/comparison/LegacyDateComparisonUtilsUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/dateapi/ConversionExample.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/ConversionExample.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/dateapi/ConversionExample.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/ConversionExample.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/dateapi/JavaDurationUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/JavaDurationUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/dateapi/JavaDurationUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/JavaDurationUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/dateapi/JavaPeriodUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/JavaPeriodUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/dateapi/JavaPeriodUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/JavaPeriodUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/dateapi/JavaUtilTimeUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/JavaUtilTimeUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/dateapi/JavaUtilTimeUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/dateapi/JavaUtilTimeUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseDateTimeFormatterUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseDateTimeFormatterUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseDateTimeFormatterUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseDateTimeFormatterUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseLocalDateTimeUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseLocalDateTimeUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseLocalDateTimeUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseLocalDateTimeUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseLocalDateUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseLocalDateUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseLocalDateUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseLocalDateUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseLocalTimeUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseLocalTimeUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseLocalTimeUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseLocalTimeUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseOffsetDateTimeUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseOffsetDateTimeUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseOffsetDateTimeUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseOffsetDateTimeUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UsePeriodUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UsePeriodUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UsePeriodUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UsePeriodUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseTimeZoneUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseTimeZoneUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseTimeZoneUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseTimeZoneUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseToInstantUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseToInstantUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseToInstantUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseToInstantUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseZonedDateTimeUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseZonedDateTimeUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/datetime/UseZonedDateTimeUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/datetime/UseZonedDateTimeUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/temporaladjusters/CustomTemporalAdjusterUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/temporaladjusters/CustomTemporalAdjusterUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/temporaladjusters/CustomTemporalAdjusterUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/temporaladjusters/CustomTemporalAdjusterUnitTest.java diff --git a/core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/temporaladjusters/TemporalAdjustersUnitTest.java b/core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/temporaladjusters/TemporalAdjustersUnitTest.java similarity index 100% rename from core-java-modules/core-java-datetime-java8/src/test/java/com/baeldung/temporaladjusters/TemporalAdjustersUnitTest.java rename to core-java-modules/core-java-8-datetime/src/test/java/com/baeldung/temporaladjusters/TemporalAdjustersUnitTest.java From 47595b7ccc555d5eee4b18fb192e4b4e9e1e3bcc Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 18 Apr 2020 19:11:47 +0530 Subject: [PATCH 167/194] JAVA-914: Removed empty pom files --- cas/cas-server/pom.xml | 0 cas/pom.xml | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 cas/cas-server/pom.xml delete mode 100644 cas/pom.xml diff --git a/cas/cas-server/pom.xml b/cas/cas-server/pom.xml deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cas/pom.xml b/cas/pom.xml deleted file mode 100644 index e69de29bb2..0000000000 From 576bf0290361f26d7df8ea78d394239e8ff80c72 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 18 Apr 2020 19:12:36 +0530 Subject: [PATCH 168/194] JAVA-914: Updated module README to include relevant info --- cas/README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/cas/README.md b/cas/README.md index 16775a8a02..6ceeaea0c4 100644 --- a/cas/README.md +++ b/cas/README.md @@ -1,7 +1,18 @@ ## CAS -This module contains articles about the Central Authentication Service (CAS) +This module contains articles about the Central Authentication Service (CAS). + +The module consists of 2 submodules: +1. `cas-server` - it requires JDK11 and uses the Gradle War Overlay style to ease setup and deployment. To start the server, simply run: + +`./gradlew run + -Dorg.gradle.java.home=$JAVA11_HOME + -Pargs="-Dcas.standalone.configurationDirectory=/cas-server/src/main/resources/etc/cas/config"` + +The server starts at https://localhost:8443. `casuser`/`Mellon` are the username and password for logging in. + +2. `cas-secured-app` - A Maven based Springboot Application ### Relevant Articles: -- [CAS SSO With Spring Security](baeldung.com/spring-security-cas-sso) \ No newline at end of file +- [CAS SSO With Spring Security](https://www.baeldung.com/spring-security-cas-sso) \ No newline at end of file From e82bdc46d4c931cb14b03e8f69d433990d9df640 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 18 Apr 2020 19:13:22 +0530 Subject: [PATCH 169/194] JAVA-914: Updated main pom to include cas as commented module --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9e3b354d74..394a566011 100644 --- a/pom.xml +++ b/pom.xml @@ -387,7 +387,7 @@ bazel blade bootique - + cdi checker-plugin @@ -900,7 +900,7 @@ bazel blade bootique - + cdi checker-plugin From 55c978c44aeac47437b28fe6850a695df9b8f5a6 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 18 Apr 2020 19:17:28 +0530 Subject: [PATCH 170/194] Revert "JAVA-916: Migrate jhipster to parent-boot-2" This reverts commit c72b6ce0114d63180adfaa8f2b056032b5bd8144. --- hystrix/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hystrix/pom.xml b/hystrix/pom.xml index 1cf8713b91..8c505c9104 100644 --- a/hystrix/pom.xml +++ b/hystrix/pom.xml @@ -8,9 +8,9 @@ com.baeldung - parent-boot-2 + parent-boot-1 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-1 From d3f01d251cf8d9d1a8577ec32f367a24f7fa59f7 Mon Sep 17 00:00:00 2001 From: Krzysztof Woyke Date: Sat, 18 Apr 2020 16:51:27 +0200 Subject: [PATCH 171/194] BAEL-3992: Enable jws in the main pom.xml --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9e3b354d74..3f16c4ddd0 100644 --- a/pom.xml +++ b/pom.xml @@ -806,7 +806,7 @@ jenkins/plugins jhipster - + jws libraries @@ -1303,7 +1303,7 @@ jenkins/plugins jhipster - + jws libraries From 95967877e946125d6ca13fd6df3f1a1f46240b8d Mon Sep 17 00:00:00 2001 From: Ankur Gupta Date: Sat, 18 Apr 2020 20:41:31 +0530 Subject: [PATCH 172/194] ankurguptajec@gmail.com (#9064) * Java Example of Hexagonal Architecture * removing unnecessary maven files from pull request and spaces in code * Removing unnecessary lines * Example code for using Multiple Cache Manager in SpringBoot * BAEL-3963:Using multiple cache managers in Spring * removing new module created in last pull request * Fixes as per editor Suggestions Co-authored-by: Ankur Gupta --- spring-caching/pom.xml | 106 ++++++++++-------- .../caching/boot/CacheApplication.java | 4 + .../bo/CustomerDetailBO.java | 28 +++++ .../bo/OrderDetailBO.java | 25 +++++ .../config/MultipleCacheManagerConfig.java | 40 +++++++ .../config/MultipleCacheResolver.java | 38 +++++++ .../MultipleCacheManagerController.java | 43 +++++++ .../multiplecachemanager/entity/Customer.java | 24 ++++ .../multiplecachemanager/entity/Item.java | 34 ++++++ .../multiplecachemanager/entity/Order.java | 44 ++++++++ .../repository/CustomerDetailRepository.java | 49 ++++++++ .../repository/OrderDetailRepository.java | 53 +++++++++ .../src/main/resources/application.properties | 8 ++ spring-caching/src/main/resources/data.sql | 7 ++ spring-caching/src/main/resources/schema.sql | 19 ++++ ...ltipleCacheManagerIntegrationUnitTest.java | 64 +++++++++++ 16 files changed, 542 insertions(+), 44 deletions(-) create mode 100644 spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java create mode 100644 spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java create mode 100644 spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java create mode 100644 spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java create mode 100644 spring-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java create mode 100644 spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java create mode 100644 spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java create mode 100644 spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java create mode 100644 spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java create mode 100644 spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java create mode 100644 spring-caching/src/main/resources/application.properties create mode 100644 spring-caching/src/main/resources/data.sql create mode 100644 spring-caching/src/main/resources/schema.sql create mode 100644 spring-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationUnitTest.java diff --git a/spring-caching/pom.xml b/spring-caching/pom.xml index d33f24de1f..f56d3cf328 100644 --- a/spring-caching/pom.xml +++ b/spring-caching/pom.xml @@ -1,49 +1,67 @@ - - 4.0.0 - spring-caching - 0.1-SNAPSHOT - spring-caching - war + + 4.0.0 + spring-caching + 0.1-SNAPSHOT + spring-caching + war - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../parent-boot-2 - + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + - - - org.springframework - spring-context - - - org.springframework.boot - spring-boot-starter-cache - - - org.springframework - spring-web - - - org.springframework - spring-webmvc - - - org.ehcache - ehcache - - - org.springframework - spring-test - test - - + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework + spring-context + + + org.springframework.boot + spring-boot-starter-cache + + + org.springframework + spring-web + + + org.springframework + spring-webmvc + + + org.ehcache + ehcache + + + org.springframework + spring-test + test + + + com.github.ben-manes.caffeine + caffeine + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-jdbc + + + + + 3.5.2 + - - 3.5.2 - - \ No newline at end of file diff --git a/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java b/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java index 714dc443e0..afa1d0ec99 100644 --- a/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java +++ b/spring-caching/src/main/java/com/baeldung/caching/boot/CacheApplication.java @@ -3,9 +3,13 @@ package com.baeldung.caching.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; +//import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @EnableCaching +//to run any module like ehcache,caching or multiplecachemanager in local machine +//add it's package for ComponentScan like below +//@ComponentScan("com.baeldung.multiplecachemanager") public class CacheApplication { public static void main(String[] args) { diff --git a/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java new file mode 100644 index 0000000000..3da4c23e28 --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/CustomerDetailBO.java @@ -0,0 +1,28 @@ +package com.baeldung.multiplecachemanager.bo; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import com.baeldung.multiplecachemanager.entity.Customer; +import com.baeldung.multiplecachemanager.entity.Order; +import com.baeldung.multiplecachemanager.repository.CustomerDetailRepository; + +@Component +public class CustomerDetailBO { + + @Autowired + private CustomerDetailRepository customerDetailRepository; + + @Cacheable(cacheNames = "customers") + public Customer getCustomerDetail(Integer customerId) { + return customerDetailRepository.getCustomerDetail(customerId); + } + + @Cacheable(cacheNames = "customerOrders", cacheManager = "alternateCacheManager") + public List getCustomerOrders(Integer customerId) { + return customerDetailRepository.getCustomerOrders(customerId); + } +} diff --git a/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java new file mode 100644 index 0000000000..390881167f --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/bo/OrderDetailBO.java @@ -0,0 +1,25 @@ +package com.baeldung.multiplecachemanager.bo; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import com.baeldung.multiplecachemanager.entity.Order; +import com.baeldung.multiplecachemanager.repository.OrderDetailRepository; + +@Component +public class OrderDetailBO { + + @Autowired + private OrderDetailRepository orderDetailRepository; + + @Cacheable(cacheNames = "orders", cacheResolver = "cacheResolver") + public Order getOrderDetail(Integer orderId) { + return orderDetailRepository.getOrderDetail(orderId); + } + + @Cacheable(cacheNames = "orderprice", cacheResolver = "cacheResolver") + public double getOrderPrice(Integer orderId) { + return orderDetailRepository.getOrderPrice(orderId); + } +} diff --git a/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java new file mode 100644 index 0000000000..247a9b596b --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheManagerConfig.java @@ -0,0 +1,40 @@ +package com.baeldung.multiplecachemanager.config; + +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.caffeine.CaffeineCacheManager; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.cache.interceptor.CacheResolver; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +//import org.springframework.context.annotation.Primary; + +import com.github.benmanes.caffeine.cache.Caffeine; + +@Configuration +@EnableCaching +public class MultipleCacheManagerConfig extends CachingConfigurerSupport { + + @Bean + //@Primary + public CacheManager cacheManager() { + CaffeineCacheManager cacheManager = new CaffeineCacheManager("customers", "orders"); + cacheManager.setCaffeine(Caffeine.newBuilder() + .initialCapacity(200) + .maximumSize(500) + .weakKeys() + .recordStats()); + return cacheManager; + } + + @Bean + public CacheManager alternateCacheManager() { + return new ConcurrentMapCacheManager("customerOrders", "orderprice"); + } + + @Bean + public CacheResolver cacheResolver() { + return new MultipleCacheResolver(alternateCacheManager(), cacheManager()); + } +} diff --git a/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java new file mode 100644 index 0000000000..1bd869d98e --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/config/MultipleCacheResolver.java @@ -0,0 +1,38 @@ +package com.baeldung.multiplecachemanager.config; + +import java.util.ArrayList; +import java.util.Collection; + +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.interceptor.CacheOperationInvocationContext; +import org.springframework.cache.interceptor.CacheResolver; + +public class MultipleCacheResolver implements CacheResolver { + + private final CacheManager simpleCacheManager; + + private final CacheManager caffeineCacheManager; + + private static final String ORDER_CACHE = "orders"; + + private static final String ORDER_PRICE_CACHE = "orderprice"; + + public MultipleCacheResolver(CacheManager simpleCacheManager, CacheManager caffeineCacheManager) { + this.simpleCacheManager = simpleCacheManager; + this.caffeineCacheManager = caffeineCacheManager; + + } + + @Override + public Collection resolveCaches(CacheOperationInvocationContext context) { + Collection caches = new ArrayList(); + if ("getOrderDetail".equals(context.getMethod() + .getName())) { + caches.add(caffeineCacheManager.getCache(ORDER_CACHE)); + } else { + caches.add(simpleCacheManager.getCache(ORDER_PRICE_CACHE)); + } + return caches; + } +} diff --git a/spring-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java new file mode 100644 index 0000000000..17a73bb27a --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/controller/MultipleCacheManagerController.java @@ -0,0 +1,43 @@ +package com.baeldung.multiplecachemanager.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.multiplecachemanager.bo.CustomerDetailBO; +import com.baeldung.multiplecachemanager.bo.OrderDetailBO; +import com.baeldung.multiplecachemanager.entity.Customer; +import com.baeldung.multiplecachemanager.entity.Order; + +@RestController +public class MultipleCacheManagerController { + + @Autowired + private CustomerDetailBO customerDetailBO; + + @Autowired + private OrderDetailBO orderDetailBO; + + @GetMapping(value = "/getCustomer/{customerid}") + public Customer getCustomer(@PathVariable Integer customerid) { + return customerDetailBO.getCustomerDetail(customerid); + } + + @GetMapping(value = "/getCustomerOrders/{customerid}") + public List getCustomerOrders(@PathVariable Integer customerid) { + return customerDetailBO.getCustomerOrders(customerid); + } + + @GetMapping(value = "/getOrder/{orderid}") + public Order getOrder(@PathVariable Integer orderid) { + return orderDetailBO.getOrderDetail(orderid); + } + + @GetMapping(value = "/getOrderPrice/{orderid}") + public double getOrderPrice(@PathVariable Integer orderid) { + return orderDetailBO.getOrderPrice(orderid); + } +} diff --git a/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java new file mode 100644 index 0000000000..cfae15f4e9 --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Customer.java @@ -0,0 +1,24 @@ +package com.baeldung.multiplecachemanager.entity; + +public class Customer { + + private int customerId; + + private String customerName; + + public int getCustomerId() { + return customerId; + } + + public void setCustomerId(int customerId) { + this.customerId = customerId; + } + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } +} diff --git a/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java new file mode 100644 index 0000000000..4131464981 --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Item.java @@ -0,0 +1,34 @@ +package com.baeldung.multiplecachemanager.entity; + +public class Item { + + private int itemId; + + private String itemDesc; + + private double itemPrice; + + public int getItemId() { + return itemId; + } + + public void setItemId(int itemId) { + this.itemId = itemId; + } + + public String getItemDesc() { + return itemDesc; + } + + public void setItemDesc(String itemDesc) { + this.itemDesc = itemDesc; + } + + public double getItemPrice() { + return itemPrice; + } + + public void setItemPrice(double itemPrice) { + this.itemPrice = itemPrice; + } +} diff --git a/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java new file mode 100644 index 0000000000..15da60d6ea --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/entity/Order.java @@ -0,0 +1,44 @@ +package com.baeldung.multiplecachemanager.entity; + +public class Order { + + private int orderId; + + private int itemId; + + private int quantity; + + private int customerId; + + public int getOrderId() { + return orderId; + } + + public void setOrderId(int orderId) { + this.orderId = orderId; + } + + public int getItemId() { + return itemId; + } + + public void setItemId(int itemId) { + this.itemId = itemId; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public int getCustomerId() { + return customerId; + } + + public void setCustomerId(int customerId) { + this.customerId = customerId; + } +} diff --git a/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java new file mode 100644 index 0000000000..aab011427d --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/CustomerDetailRepository.java @@ -0,0 +1,49 @@ +package com.baeldung.multiplecachemanager.repository; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.stereotype.Repository; + +import com.baeldung.multiplecachemanager.entity.Customer; +import com.baeldung.multiplecachemanager.entity.Order; + +@Repository +public class CustomerDetailRepository { + + @Autowired + private JdbcTemplate jdbcTemplate; + + public Customer getCustomerDetail(Integer customerId) { + String customerQuery = "select * from customer where customerid = ? "; + Customer customer = new Customer(); + jdbcTemplate.query(customerQuery, new Object[] { customerId }, new RowCallbackHandler() { + public void processRow(ResultSet rs) throws SQLException { + customer.setCustomerId(rs.getInt("customerid")); + customer.setCustomerName(rs.getString("customername")); + } + }); + return customer; + } + + public List getCustomerOrders(Integer customerId) { + String customerOrderQuery = "select * from orderdetail where customerid = ? "; + List orders = new ArrayList(); + jdbcTemplate.query(customerOrderQuery, new Object[] { customerId }, new RowCallbackHandler() { + public void processRow(ResultSet rs) throws SQLException { + Order order = new Order(); + order.setCustomerId(rs.getInt("customerid")); + order.setItemId(rs.getInt("orderid")); + order.setOrderId(rs.getInt("orderid")); + order.setQuantity(rs.getInt("quantity")); + orders.add(order); + } + }); + return orders; + } +} diff --git a/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java new file mode 100644 index 0000000000..58c0968e48 --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/multiplecachemanager/repository/OrderDetailRepository.java @@ -0,0 +1,53 @@ +package com.baeldung.multiplecachemanager.repository; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.stereotype.Repository; + +import com.baeldung.multiplecachemanager.entity.Item; +import com.baeldung.multiplecachemanager.entity.Order; + +@Repository +public class OrderDetailRepository { + + @Autowired + private JdbcTemplate jdbcTemplate; + + public Order getOrderDetail(Integer orderId) { + String orderDetailQuery = "select * from orderdetail where orderid = ? "; + Order order = new Order(); + jdbcTemplate.query(orderDetailQuery, new Object[] { orderId }, new RowCallbackHandler() { + public void processRow(ResultSet rs) throws SQLException { + order.setCustomerId(rs.getInt("customerid")); + order.setOrderId(rs.getInt("orderid")); + order.setItemId(rs.getInt("itemid")); + order.setQuantity(rs.getInt("quantity")); + } + }); + return order; + } + + public double getOrderPrice(Integer orderId) { + + String orderItemJoinQuery = "select * from ( select * from orderdetail where orderid = ? ) o left join item on o.itemid = ITEM.itemid"; + Order order = new Order(); + Item item = new Item(); + + jdbcTemplate.query(orderItemJoinQuery, new Object[] { orderId }, new RowCallbackHandler() { + public void processRow(ResultSet rs) throws SQLException { + order.setCustomerId(rs.getInt("customerid")); + order.setOrderId(rs.getInt("orderid")); + order.setItemId(rs.getInt("itemid")); + order.setQuantity(rs.getInt("quantity")); + item.setItemDesc("itemdesc"); + item.setItemId(rs.getInt("itemid")); + item.setItemPrice(rs.getDouble("price")); + } + }); + return order.getQuantity() * item.getItemPrice(); + } +} diff --git a/spring-caching/src/main/resources/application.properties b/spring-caching/src/main/resources/application.properties new file mode 100644 index 0000000000..ee7b5e62c0 --- /dev/null +++ b/spring-caching/src/main/resources/application.properties @@ -0,0 +1,8 @@ +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= + +# Enabling H2 Console +spring.h2.console.enabled=true +spring.h2.console.path=/h2 diff --git a/spring-caching/src/main/resources/data.sql b/spring-caching/src/main/resources/data.sql new file mode 100644 index 0000000000..e4165ae71f --- /dev/null +++ b/spring-caching/src/main/resources/data.sql @@ -0,0 +1,7 @@ +INSERT INTO CUSTOMER VALUES(1001,'BAELDUNG'); + +INSERT INTO ITEM VALUES(10001,'ITEM1',50.0); +INSERT INTO ITEM VALUES(10002,'ITEM2',100.0); + +INSERT INTO ORDERDETAIL VALUES(300001,1001,10001,2); +INSERT INTO ORDERDETAIL VALUES(300002,1001,10002,5); \ No newline at end of file diff --git a/spring-caching/src/main/resources/schema.sql b/spring-caching/src/main/resources/schema.sql new file mode 100644 index 0000000000..5862499bc0 --- /dev/null +++ b/spring-caching/src/main/resources/schema.sql @@ -0,0 +1,19 @@ +CREATE TABLE CUSTOMER( + CUSTOMERID INT PRIMARY KEY, + CUSTOMERNAME VARCHAR(250) NOT NULL +); + +CREATE TABLE ITEM( +ITEMID INT PRIMARY KEY, +ITEMDESC VARCHAR(250), +PRICE DOUBLE +); + +CREATE TABLE ORDERDETAIL( +ORDERID INT PRIMARY KEY, +CUSTOMERID INT NOT NULL, +ITEMID INT NOT NULL, +QUANTITY INT, +FOREIGN KEY (customerid) references CUSTOMER(customerid), +FOREIGN KEY (itemid) references ITEM(itemid) +); \ No newline at end of file diff --git a/spring-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationUnitTest.java b/spring-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationUnitTest.java new file mode 100644 index 0000000000..e02e5da246 --- /dev/null +++ b/spring-caching/src/test/java/com/baeldung/multiplecachemanager/MultipleCacheManagerIntegrationUnitTest.java @@ -0,0 +1,64 @@ +package com.baeldung.multiplecachemanager; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.util.Assert; + +import com.baeldung.multiplecachemanager.bo.OrderDetailBO; +import com.baeldung.multiplecachemanager.entity.Order; +import com.baeldung.multiplecachemanager.repository.OrderDetailRepository; + +@SpringBootApplication +@SpringBootTest +public class MultipleCacheManagerIntegrationUnitTest { + + @MockBean + private OrderDetailRepository orderDetailRepository; + + @Autowired + private OrderDetailBO orderDetailBO; + + @Autowired + private CacheManager cacheManager; + + @Autowired + private CacheManager alternateCacheManager; + + @Test + public void givenCacheResolverIsConfigured_whenCallGetOrderDetail_thenDataShouldBeInCaffieneCacheManager() { + Integer key = 30001; + cacheManager.getCache("orders") + .evict(key); + Order order = new Order(); + order.setCustomerId(1001); + order.setItemId(10001); + order.setOrderId(30001); + order.setQuantity(2); + Mockito.when(orderDetailRepository.getOrderDetail(key)) + .thenReturn(order); + orderDetailBO.getOrderDetail(key); + org.springframework.cache.caffeine.CaffeineCache cache = (CaffeineCache) cacheManager.getCache("orders"); + Assert.notNull(cache.get(key) + .get(), "caffieneCache should have had the data"); + } + + @Test + public void givenCacheResolverIsConfigured_whenCallGetOrderPrice_thenDataShouldBeInAlternateCacheManager() { + Integer key = 30001; + alternateCacheManager.getCache("orderprice") + .evict(key); + Mockito.when(orderDetailRepository.getOrderPrice(key)) + .thenReturn(500.0); + orderDetailBO.getOrderPrice(key); + Cache cache = alternateCacheManager.getCache("orderprice"); + Assert.notNull(cache.get(key) + .get(), "alternateCache should have had the data"); + } +} From 0f851a1d84ed31d8bf4f047d61f420ab7dfc1382 Mon Sep 17 00:00:00 2001 From: "amit.pandey" Date: Sat, 18 Apr 2020 20:57:13 +0530 Subject: [PATCH 173/194] update source code to sync with article --- .../baeldung/optional/OptionalUnitTest.java | 9 ++++ .../spring-boot-runtime/pom.xml | 4 +- .../com/baeldung/web/log/app/Application.java | 23 +--------- .../log/config/CustomWebAppInitializer.java | 25 ++++++++++ ....java => MyWebApplicationInitializer.java} | 7 +-- ...lesWithMavenPropertiesIntegrationTest.java | 2 +- .../mockito/MockitoAnnotationUnitTest.java | 46 +++++++++++++++++++ 7 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/CustomWebAppInitializer.java rename spring-core-2/src/main/java/com/baeldung/spring/config/{MainWebAppInitializer.java => MyWebApplicationInitializer.java} (81%) diff --git a/core-java-modules/core-java-optional/src/test/java/com/baeldung/optional/OptionalUnitTest.java b/core-java-modules/core-java-optional/src/test/java/com/baeldung/optional/OptionalUnitTest.java index e5c4319bf7..de16e9b635 100644 --- a/core-java-modules/core-java-optional/src/test/java/com/baeldung/optional/OptionalUnitTest.java +++ b/core-java-modules/core-java-optional/src/test/java/com/baeldung/optional/OptionalUnitTest.java @@ -86,6 +86,15 @@ public class OptionalUnitTest { Optional opt = Optional.ofNullable(null); String name = opt.get(); } + + @Test + public void givenAnEmptyOptional_thenIsEmptyBehavesAsExpected() { + Optional opt = Optional.of("Baeldung"); + assertTrue(opt.isPresent()); + + opt = Optional.ofNullable(null); + assertFalse(opt.isPresent()); + } // Conditional Return With filter() @Test diff --git a/spring-boot-modules/spring-boot-runtime/pom.xml b/spring-boot-modules/spring-boot-runtime/pom.xml index df45537940..4de604f664 100644 --- a/spring-boot-modules/spring-boot-runtime/pom.xml +++ b/spring-boot-modules/spring-boot-runtime/pom.xml @@ -14,11 +14,11 @@ ../../parent-boot-2 - + diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/Application.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/Application.java index f20fba737a..40f5341e29 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/Application.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/app/Application.java @@ -1,43 +1,22 @@ package com.baeldung.web.log.app; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; -import org.springframework.web.context.ContextLoaderListener; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; import org.springframework.context.annotation.PropertySource; import com.baeldung.web.log.config.CustomeRequestLoggingFilter; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; - @EnableAutoConfiguration @ComponentScan("com.baeldung.web.log") @PropertySource("application-log.properties") @SpringBootApplication -public class Application extends SpringBootServletInitializer { +public class Application { public static void main(final String[] args) { SpringApplication.run(Application.class, args); } - - @Override - public void onStartup(ServletContext container) throws ServletException { - - AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - context.setConfigLocation("com.baeldung.web.log"); - container.addListener(new ContextLoaderListener(context)); - - ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(context)); - dispatcher.setLoadOnStartup(1); - dispatcher.addMapping("/"); - - container.addFilter("customRequestLoggingFilter", CustomeRequestLoggingFilter.class).addMappingForServletNames(null, false, "dispatcher"); - } } \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/CustomWebAppInitializer.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/CustomWebAppInitializer.java new file mode 100644 index 0000000000..f51bb52990 --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/web/log/config/CustomWebAppInitializer.java @@ -0,0 +1,25 @@ +package com.baeldung.web.log.config; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; +import org.springframework.web.WebApplicationInitializer; + +public class CustomWebAppInitializer implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext container) throws ServletException { + + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setConfigLocation("com.baeldung.web.log"); + container.addListener(new ContextLoaderListener(context)); + + ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(context)); + dispatcher.setLoadOnStartup(1); + dispatcher.addMapping("/"); + + container.addFilter("customRequestLoggingFilter", CustomeRequestLoggingFilter.class).addMappingForServletNames(null, false, "dispatcher"); + } +} \ No newline at end of file diff --git a/spring-core-2/src/main/java/com/baeldung/spring/config/MainWebAppInitializer.java b/spring-core-2/src/main/java/com/baeldung/spring/config/MyWebApplicationInitializer.java similarity index 81% rename from spring-core-2/src/main/java/com/baeldung/spring/config/MainWebAppInitializer.java rename to spring-core-2/src/main/java/com/baeldung/spring/config/MyWebApplicationInitializer.java index dd396a653f..034386ade9 100644 --- a/spring-core-2/src/main/java/com/baeldung/spring/config/MainWebAppInitializer.java +++ b/spring-core-2/src/main/java/com/baeldung/spring/config/MyWebApplicationInitializer.java @@ -6,15 +6,12 @@ import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; -import org.springframework.context.support.GenericApplicationContext; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.ContextLoaderListener; -import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; -import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; -public class MainWebAppInitializer implements WebApplicationInitializer +public class MyWebApplicationInitializer implements WebApplicationInitializer { /** @@ -22,7 +19,7 @@ public class MainWebAppInitializer implements WebApplicationInitializer */ @Override public void onStartup(final ServletContext sc) throws ServletException { - System.out.println("MainWebAppInitializer.onStartup()"); + System.out.println("MyWebApplicationInitializer.onStartup()"); // Create the 'root' Spring application context final AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); diff --git a/spring-core-2/src/test/java/com/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java b/spring-core-2/src/test/java/com/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java index 60e9499d4b..1380e34ebd 100644 --- a/spring-core-2/src/test/java/com/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java +++ b/spring-core-2/src/test/java/com/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java @@ -16,7 +16,7 @@ public class SpringProfilesWithMavenPropertiesIntegrationTest { DatasourceConfig datasourceConfig; @Test - public void testSpringProfiles() { + public void setupDatasource() { Assert.assertTrue(datasourceConfig instanceof DevDatasourceConfig); } } \ No newline at end of file diff --git a/testing-modules/mockito/src/test/java/com/baeldung/mockito/MockitoAnnotationUnitTest.java b/testing-modules/mockito/src/test/java/com/baeldung/mockito/MockitoAnnotationUnitTest.java index 731183bae2..27e3258efb 100644 --- a/testing-modules/mockito/src/test/java/com/baeldung/mockito/MockitoAnnotationUnitTest.java +++ b/testing-modules/mockito/src/test/java/com/baeldung/mockito/MockitoAnnotationUnitTest.java @@ -75,7 +75,53 @@ public class MockitoAnnotationUnitTest { Mockito.doReturn(100).when(spiedList).size(); assertEquals(100, spiedList.size()); } + + @Test + public void whenSpyingOnList_thenCorrect() { + List list = new ArrayList(); + List spyList = Mockito.spy(list); + + spyList.add("one"); + spyList.add("two"); + + Mockito.verify(spyList).add("one"); + Mockito.verify(spyList).add("two"); + + assertEquals(2, spyList.size()); + } + @Test + public void whenUsingTheSpyAnnotation_thenObjectIsSpied() { + spiedList.add("one"); + spiedList.add("two"); + + Mockito.verify(spiedList).add("one"); + Mockito.verify(spiedList).add("two"); + + assertEquals(2, spiedList.size()); + } + + @Test + public void whenStubASpy_thenStubbed() { + List list = new ArrayList(); + List spyList = Mockito.spy(list); + + assertEquals(0, spyList.size()); + + Mockito.doReturn(100).when(spyList).size(); + assertEquals(100, spyList.size()); + } + + @Test + public void whenCreateSpy_thenCreate() { + List spyList = Mockito.spy(new ArrayList<>()); + + spyList.add("one"); + Mockito.verify(spyList).add("one"); + + assertEquals(1, spyList.size()); + } + @Test public void whenNotUseCaptorAnnotation_thenCorrect() { final List mockList = Mockito.mock(List.class); From c540674c1845b569b6675e167bced64944f04c2d Mon Sep 17 00:00:00 2001 From: "amit.pandey" Date: Sat, 18 Apr 2020 21:00:01 +0530 Subject: [PATCH 174/194] update source code to sync with article --- spring-boot-modules/spring-boot-runtime/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-boot-modules/spring-boot-runtime/pom.xml b/spring-boot-modules/spring-boot-runtime/pom.xml index 4de604f664..df45537940 100644 --- a/spring-boot-modules/spring-boot-runtime/pom.xml +++ b/spring-boot-modules/spring-boot-runtime/pom.xml @@ -14,11 +14,11 @@ ../../parent-boot-2 - + From 7186e90e46ea4c65d3a26f4c4b9ead06586a913d Mon Sep 17 00:00:00 2001 From: kwoyke Date: Sat, 18 Apr 2020 18:04:17 +0200 Subject: [PATCH 175/194] BAEL-4003: Add byte-buddy dependency (#9134) --- spring-boot-rest/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index 10dacf99e8..a8500d50f2 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -79,6 +79,11 @@ modelmapper ${modelmapper.version} + + net.bytebuddy + byte-buddy + ${byte-buddy.version} + From 32461d70ed11d3f4249f933fe0a2983069c244d5 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Sat, 18 Apr 2020 22:26:54 +0530 Subject: [PATCH 176/194] JAVA-918: Migrate jjwt to parent-boot-2 --- jjwt/pom.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/jjwt/pom.xml b/jjwt/pom.xml index 073f12a922..aa238fafb5 100644 --- a/jjwt/pom.xml +++ b/jjwt/pom.xml @@ -10,9 +10,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -30,6 +30,11 @@ org.springframework.boot spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + io.jsonwebtoken From 591c168f247d80ce0c128e22161dd8b2e89cb96b Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Sat, 18 Apr 2020 21:08:53 +0300 Subject: [PATCH 177/194] BAEL-3908_http2_client_in_jetty (#8981) * BAEL-3908 http2 in jetty - initial commit * BAEL-3908 - HTTP2 client in jetty * BAEL-3908 - http2 in jetty - code cleanup * BAEL-3908 - fixed indentation --- libraries-server/pom.xml | 42 +++++++++- libraries-server/src/main/config/jetty.xml | 79 ++++++++++++++++++ .../jetty/http2/Http2JettyServlet.java | 29 +++++++ .../src/main/resources/keystore.jks | Bin 0 -> 2206 bytes .../src/main/resources/truststore.jks | Bin 0 -> 916 bytes .../src/main/webapp/WEB-INF/web.xml | 33 ++++++++ libraries-server/src/main/webapp/http2.html | 14 ++++ .../images/homepage-latest_articles.jpg | Bin 0 -> 18501 bytes .../images/homepage-rest_with_spring.jpg | Bin 0 -> 18891 bytes .../webapp/images/homepage-weekly_reviews.jpg | Bin 0 -> 20814 bytes libraries-server/src/main/webapp/index.html | 12 +++ 11 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 libraries-server/src/main/config/jetty.xml create mode 100644 libraries-server/src/main/java/com/baeldung/jetty/http2/Http2JettyServlet.java create mode 100644 libraries-server/src/main/resources/keystore.jks create mode 100644 libraries-server/src/main/resources/truststore.jks create mode 100644 libraries-server/src/main/webapp/WEB-INF/web.xml create mode 100644 libraries-server/src/main/webapp/http2.html create mode 100644 libraries-server/src/main/webapp/images/homepage-latest_articles.jpg create mode 100644 libraries-server/src/main/webapp/images/homepage-rest_with_spring.jpg create mode 100644 libraries-server/src/main/webapp/images/homepage-weekly_reviews.jpg create mode 100644 libraries-server/src/main/webapp/index.html diff --git a/libraries-server/pom.xml b/libraries-server/pom.xml index a849708cd8..eb9cb61e56 100644 --- a/libraries-server/pom.xml +++ b/libraries-server/pom.xml @@ -5,6 +5,7 @@ libraries-server 0.0.1-SNAPSHOT libraries-server + war com.baeldung @@ -105,12 +106,51 @@ + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty.version} + + 8888 + quit + + -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/alpn/alpn-boot/${alpn.version}/alpn-boot-${alpn.version}.jar + + ${basedir}/src/main/config/jetty.xml + + / + + + + + org.eclipse.jetty.http2 + http2-server + ${jetty.version} + + + org.eclipse.jetty + jetty-alpn-openjdk8-server + ${jetty.version} + + + org.eclipse.jetty + jetty-servlets + ${jetty.version} + + + + + 3.6.2 4.5.3 - 9.4.8.v20171121 + 9.4.27.v20200227 4.1.20.Final + 8.1.11.v20170118 8.5.24 4.3.1 1.2.0 diff --git a/libraries-server/src/main/config/jetty.xml b/libraries-server/src/main/config/jetty.xml new file mode 100644 index 0000000000..fd4a50382b --- /dev/null +++ b/libraries-server/src/main/config/jetty.xml @@ -0,0 +1,79 @@ + + + + + + + src/main/resources/keystore.jks + storepwd + src/main/resources/truststore.jks + storepwd + TLSv1.2 + + + + + + + + + + + + + + + + + http/1.1 + + + + + + + + + + + + 8443 + + + + + + + + + + + + + + + + + + alpn + + + + + h2,h2-17 + + + + + + + + + + + + 8444 + + + + \ No newline at end of file diff --git a/libraries-server/src/main/java/com/baeldung/jetty/http2/Http2JettyServlet.java b/libraries-server/src/main/java/com/baeldung/jetty/http2/Http2JettyServlet.java new file mode 100644 index 0000000000..56b75c45d3 --- /dev/null +++ b/libraries-server/src/main/java/com/baeldung/jetty/http2/Http2JettyServlet.java @@ -0,0 +1,29 @@ +package com.baeldung.jetty.http2; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class Http2JettyServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.addHeader("Cache-control", "no-store, no-cache, must-revalidate"); + response.addDateHeader("Last-Modified", 0); + response.addDateHeader("Expires", 0); + + String requestPath = request.getRequestURI(); + InputStream input = getServletContext().getResourceAsStream(requestPath); + OutputStream output = response.getOutputStream(); + byte[] buffer = new byte[1024]; + int read; + while ((read = input.read(buffer)) >= 0) { + output.write(buffer, 0, read); + } + } + +} diff --git a/libraries-server/src/main/resources/keystore.jks b/libraries-server/src/main/resources/keystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..428ba54776ede2fdcdeedd879edb927c2abd9953 GIT binary patch literal 2206 zcmcgt`9Bkm8{cNkoMUp6gmShKn!AQX*(l6Nj(i=TnQPOKYtv{*Wg>ItE=Q!pRYH8a z$Sp#S#2lYw#aw;$y9u4T}83H*%lp zAKZay0sy=q1Qoo85aAQh;$ zD(c2EIN#D7WwYDLKUg!CotQPD@dp;5FR#bgaace(^x$6g5frD~(_b(MI^J&*A2DRp zf5Q2onfE(zvUb9|9C`66)YFRNM6~xrz4;iVbU=P|*YT2eWHFJJtr+M@zt2qPm)K~rRcqcs=LM12)PX0TT%QO zlf*xkqD3}7l)1J`5W(>=9nR0e6j-<79<11v3ZuXXcQpoCsqY~n`$FN+S}hcVm5Y>G zXnD{@DYs1@{S0z(lW+?86LWKtku$$-(khsh>0qRUXn=84`GRn?77M^_JY`durnN;KE zW#OJ`h<6xcB{I))ekGpc*Ylt}0cx4|OMBDPQvx4`r`}4Ze5_ipdObGMTi3bZHd5PC zcY0;?uBWu$PSvjJeb87nY7ghNv?%M@SoDl6IWt`bQCosfSh$#D6$ea~QhKM^ud2Ut z+9PYJuVpoELmN-A`F$BicO{BSYg@#tS%avVfb}DxL)|NanJ)#zB!2~?#Ot%H7--9N zU$bs0fS5G!m5M4&WK3#a|H|Tgw*?X-;H+Lu@kwA>qSR~7UC7b)7MJXTn6PG>n@8jP zW+}F^X$$c;U~4ryqRF; z>`j!tbLMK4ZGyY643|~?%Mu#fm!l%wAKjBDmd+VYmp3S#$scD$~bxbf|z#)hShN0*AhRaPDcmqrftGlHq4^54MM$Xfy(2> zH8QYVMzmn_oHbvJCB`IN~E&{1*h&0gEM{e zKvWvzp(!BqMX8`t#)~0nq}Wa zr6>FRPyp;AAB&)1$5@;r$23J{K&~>TWjZf7V$wFzmGM95CXhFG1cJNVAXks}C+&2- zbf9Qn*D8N}Afd2kpwDxns3%1uaFhAqDV8ksWiWY|quuLGZ0)SqrJ!Y8yX}@}IyC$C zQ3rCUsn}#>F#D8%D?q~ySy4j&he%Bs{{7V%rl!ui`@KQP?NTi+_iN{cwom&9RaMRR zB~z!hz|0HAgB9_Ijvpe-zr#jLbckJsc>vmo{+im?t8lA;N#fD4?{lb&J0V8Gocq%; f1ihv=QIDh{M_<9V+45Z2{KE4_qW}V3B0uV%GgrOJ literal 0 HcmV?d00001 diff --git a/libraries-server/src/main/resources/truststore.jks b/libraries-server/src/main/resources/truststore.jks new file mode 100644 index 0000000000000000000000000000000000000000..839cb8c35151c2b7c64afca24b6b72caad070a05 GIT binary patch literal 916 zcmezO_TO6u1_mY|W(3o$xs} zE~X|%Muz1J{3AIFGbaABoD&*5saD@gH|APIn|qhRGl}gsUzm=o9G*UXZaLfkb^*)o zjA*-gTf)`m_MQJYE&gJ}p^PHkrj!4^W|XX5a=N7A{;n#yaON&k_bHloe-^*hm?Z91 zlB>xeD=<(C>yn{9D54u}krkl}HQ(Uscha(++qf!T9y+xaEfnXd1O zi0)T?voO%;QH9LK;*_O3mBblqm)!31vU@hm;^%>mh5U@y3R%l0gzi`2yxH!+?kPOi zt!Tnsz1x9B3U2~8STZp)GB6^C5HPs_Lx_=~O<3xi>MmQ;D_g$D<_pdct`+TyzWTQ= zW5Finm(sGEe;ty^>vg$!cV)t>;H#Mev23$*WWBpyJ}Ir;RW+Htrt6{Pk&qz&-XG2@ z8@{&Lu%DX7m47Uny+-3w`=4V611q#Ub(U`xZCtSK^2LO^3(s|HW&N14dV4@A&(kX% z*S_eUPs-bSWRp>avt;CP@7K+G&3=b&1eO-s3f`;Cf91p#$)FW&xME3L8sEBQQDVCvfG>mdwqnk+GXd2ihXqpv z;usF(WoYYmu8DZZa4%1z=+hI+*gpkUykAy5tj#grb*gH!M6TqIcifYBGVe^&T#-2O K*=+x>r_BKeJV|!| literal 0 HcmV?d00001 diff --git a/libraries-server/src/main/webapp/WEB-INF/web.xml b/libraries-server/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..75d7e11c64 --- /dev/null +++ b/libraries-server/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,33 @@ + + + + + http2Jetty + com.baeldung.jetty.http2.Http2JettyServlet + + + http2Jetty + /images/* + + + + push + org.eclipse.jetty.servlets.PushCacheFilter + + ports + 8444 + + + maxAssociations + 32 + + + + push + /* + + + \ No newline at end of file diff --git a/libraries-server/src/main/webapp/http2.html b/libraries-server/src/main/webapp/http2.html new file mode 100644 index 0000000000..4563945a5e --- /dev/null +++ b/libraries-server/src/main/webapp/http2.html @@ -0,0 +1,14 @@ + + + + Baeldung HTTP/2 Client in Jetty + + +

HTTP/2 Demo

+
+ latest articles + rest with spring + weekly reviews +
+ + \ No newline at end of file diff --git a/libraries-server/src/main/webapp/images/homepage-latest_articles.jpg b/libraries-server/src/main/webapp/images/homepage-latest_articles.jpg new file mode 100644 index 0000000000000000000000000000000000000000..59e78e456022f41f7f6167157d4a4dc08e944e27 GIT binary patch literal 18501 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 BH~s(s literal 0 HcmV?d00001 diff --git a/libraries-server/src/main/webapp/images/homepage-rest_with_spring.jpg b/libraries-server/src/main/webapp/images/homepage-rest_with_spring.jpg new file mode 100644 index 0000000000000000000000000000000000000000..43d9221e85f9186b8bbf9e12e5924421462ed04c GIT binary patch literal 18891 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

gHIi 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

  • Dt2>W6b5o~w4CE5}?a6-m+1MpfWN;B- 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 literal 0 HcmV?d00001 diff --git a/libraries-server/src/main/webapp/index.html b/libraries-server/src/main/webapp/index.html new file mode 100644 index 0000000000..2497893d82 --- /dev/null +++ b/libraries-server/src/main/webapp/index.html @@ -0,0 +1,12 @@ + + + + Baeldung: HTTP2 Client in Jetty + + +

    HTTP/1.1

    +
    +

    HTTP/2 Push

    +
    + + \ No newline at end of file From ffe8422ca234cbfac5c019137723f9dca643be89 Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Sat, 18 Apr 2020 21:15:05 -0500 Subject: [PATCH 178/194] BAEL-3908: Update README file (#9141) * BAEL-3336 BAEL-3058 add links * BAEL-3319: add link * BAEL-3284: add link * BAEL-3198: add link to article * BAEL-3479: add link to article * BAEL-3485: add article link * SCALA-38: move to new package and add link back to article * SCALA-38: add imports back into unit test * BAEL-3908: add link back to article --- libraries-server/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries-server/README.md b/libraries-server/README.md index d9e6b8b206..7e41f33a0c 100644 --- a/libraries-server/README.md +++ b/libraries-server/README.md @@ -13,3 +13,4 @@ This module contains articles about server libraries. - [MQTT Client in Java](https://www.baeldung.com/java-mqtt-client) - [Guide to XMPP Smack Client](https://www.baeldung.com/xmpp-smack-chat-client) - [A Guide to NanoHTTPD](https://www.baeldung.com/nanohttpd) +- [HTTP/2 in Jetty](https://www.baeldung.com/jetty-http-2) From 87ac7a74bedb559899383bea777a59670389f45d Mon Sep 17 00:00:00 2001 From: Yavuz Tas <12643010+yavuztas@users.noreply.github.com> Date: Sun, 19 Apr 2020 16:18:58 +0200 Subject: [PATCH 179/194] Update code base for BAEL-3872 (#9032) * resolve an sql syntax error for H2 version 1.4.200 * update spring and spring-data-jpa version to latest migrate spring-data-jpa Sort initializations to Sort.by static factory methods to fix compile errors * update hibernate version to latest * cleanup code * show how to get a bean object from factory bean as shown in the section 4 * update mysql version and fix tests under persistence.service * clean up code --- .../spring-persistence-simple/pom.xml | 15 +++++--- .../baeldung/config/PersistenceConfig.java | 24 +++++-------- .../baeldung/config/PersistenceJPAConfig.java | 15 ++++---- .../com/baeldung/jpa/dao/AbstractJpaDAO.java | 7 ++-- .../src/main/resources/hibernate5Config.xml | 2 +- .../src/main/resources/jdbc/schema.sql | 2 +- .../resources/persistence-mysql.properties | 4 +-- .../jpaquery/UserRepositoryCommon.java | 35 ++++++++----------- 8 files changed, 46 insertions(+), 58 deletions(-) diff --git a/persistence-modules/spring-persistence-simple/pom.xml b/persistence-modules/spring-persistence-simple/pom.xml index 8a03310048..878c4592f9 100644 --- a/persistence-modules/spring-persistence-simple/pom.xml +++ b/persistence-modules/spring-persistence-simple/pom.xml @@ -24,7 +24,11 @@ spring-context ${org.springframework.version} - + + org.springframework + spring-aspects + ${org.springframework.version} + org.hibernate @@ -128,12 +132,13 @@ - 5.1.6.RELEASE + 5.2.5.RELEASE - 5.4.2.Final - 6.0.6 - 2.1.6.RELEASE + 5.4.13.Final + 8.0.19 + 1.4.200 + 2.2.6.RELEASE 9.0.0.M26 1.1 4.2.1 diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceConfig.java index 569971e311..80f3ff14c5 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceConfig.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceConfig.java @@ -1,9 +1,7 @@ package com.baeldung.config; -import java.util.Properties; - -import javax.sql.DataSource; - +import com.baeldung.persistence.service.FooService; +import com.google.common.base.Preconditions; import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -23,16 +21,15 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; -import com.baeldung.hibernate.dao.FooDao; -import com.baeldung.jpa.dao.IFooDao; -import com.google.common.base.Preconditions; +import javax.sql.DataSource; +import java.util.Properties; @Configuration @EnableTransactionManagement @EnableJpaRepositories(basePackages = { "com.baeldung.hibernate.dao" }, transactionManagerRef = "jpaTransactionManager") @EnableJpaAuditing @PropertySource({ "classpath:persistence-mysql.properties" }) -@ComponentScan({ "com.baeldung.persistence", "com.baeldung.hibernate.dao" }) +@ComponentScan(basePackages = { "com.baeldung.persistence.dao", "com.baeldung.jpa.dao" }) public class PersistenceConfig { @Autowired @@ -46,7 +43,7 @@ public class PersistenceConfig { public LocalSessionFactoryBean sessionFactory() { final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); sessionFactory.setDataSource(restDataSource()); - sessionFactory.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + sessionFactory.setPackagesToScan("com.baeldung.persistence.model"); sessionFactory.setHibernateProperties(hibernateProperties()); return sessionFactory; @@ -56,7 +53,7 @@ public class PersistenceConfig { public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(restDataSource()); - emf.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + emf.setPackagesToScan("com.baeldung.persistence.model"); final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); emf.setJpaVendorAdapter(vendorAdapter); @@ -96,18 +93,15 @@ public class PersistenceConfig { } @Bean - public IFooDao fooHibernateDao() { - return new FooDao(); + public FooService fooService() { + return new FooService(); } private final Properties hibernateProperties() { final Properties hibernateProperties = new Properties(); hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); - hibernateProperties.setProperty("hibernate.show_sql", "true"); - // hibernateProperties.setProperty("hibernate.format_sql", "true"); - // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); // Envers properties hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix")); diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceJPAConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceJPAConfig.java index 7d3a881827..06cae493c9 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceJPAConfig.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/config/PersistenceJPAConfig.java @@ -1,10 +1,6 @@ package com.baeldung.config; -import java.util.Properties; - -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; - +import com.google.common.base.Preconditions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -21,7 +17,8 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; -import com.google.common.base.Preconditions; +import javax.sql.DataSource; +import java.util.Properties; @Configuration @EnableTransactionManagement @@ -43,7 +40,7 @@ public class PersistenceJPAConfig { public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); - em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + em.setPackagesToScan("com.baeldung.persistence.model"); final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); @@ -64,9 +61,9 @@ public class PersistenceJPAConfig { } @Bean - public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) { + public PlatformTransactionManager transactionManager() { final JpaTransactionManager transactionManager = new JpaTransactionManager(); - transactionManager.setEntityManagerFactory(emf); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); return transactionManager; } diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/AbstractJpaDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/AbstractJpaDAO.java index 4fbc8464bb..a6542c5cb1 100644 --- a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/AbstractJpaDAO.java +++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/jpa/dao/AbstractJpaDAO.java @@ -1,16 +1,15 @@ package com.baeldung.jpa.dao; -import java.io.Serializable; -import java.util.List; - import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; +import java.io.Serializable; +import java.util.List; public abstract class AbstractJpaDAO { private Class clazz; - @PersistenceContext + @PersistenceContext(unitName = "entityManagerFactory") private EntityManager entityManager; public final void setClazz(final Class clazzToSet) { diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml index bbb61cb3e0..55546a862a 100644 --- a/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml +++ b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml @@ -21,7 +21,7 @@ - + diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/schema.sql b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/schema.sql index c86d35cdae..ef4460e267 100644 --- a/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/schema.sql +++ b/persistence-modules/spring-persistence-simple/src/main/resources/jdbc/schema.sql @@ -3,5 +3,5 @@ CREATE TABLE EMPLOYEE ID int NOT NULL PRIMARY KEY, FIRST_NAME varchar(255), LAST_NAME varchar(255), - ADDRESS varchar(255), + ADDRESS varchar(255) ); \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties index b3cfd31f46..9ba4f7602a 100644 --- a/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties +++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties @@ -1,7 +1,7 @@ # jdbc.X jdbc.driverClassName=com.mysql.cj.jdbc.Driver -jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate5_01?createDatabaseIfNotExist=true -jdbc.eventGeneratedId=tutorialuser +jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate5_01?createDatabaseIfNotExist=true&serverTimezone=UTC +jdbc.user=tutorialuser jdbc.pass=tutorialmy5ql # hibernate.X diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/jpaquery/UserRepositoryCommon.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/jpaquery/UserRepositoryCommon.java index 69ddbb9b9f..5874b3c643 100644 --- a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/jpaquery/UserRepositoryCommon.java +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/spring/data/persistence/jpaquery/UserRepositoryCommon.java @@ -1,25 +1,6 @@ package com.baeldung.spring.data.persistence.jpaquery; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Stream; - -import javax.persistence.EntityManager; -import javax.persistence.Query; - import com.baeldung.spring.data.persistence.config.PersistenceConfig; -import com.baeldung.spring.data.persistence.jpaquery.UserRepository; import com.baeldung.spring.data.persistence.model.User; import org.junit.After; import org.junit.Test; @@ -36,6 +17,16 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; import org.springframework.transaction.annotation.Transactional; +import javax.persistence.EntityManager; +import javax.persistence.Query; +import java.time.LocalDate; +import java.util.*; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.*; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) @@ -283,7 +274,7 @@ public class UserRepositoryCommon { userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); - List usersSortByName = userRepository.findAll(new Sort(Sort.Direction.ASC, "name")); + List usersSortByName = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name")); assertThat(usersSortByName.get(0) .getName()).isEqualTo(USER_NAME_ADAM); @@ -295,7 +286,7 @@ public class UserRepositoryCommon { userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); - userRepository.findAll(new Sort(Sort.Direction.ASC, "name")); + userRepository.findAll(Sort.by(Sort.Direction.ASC, "name")); List usersSortByNameLength = userRepository.findAll(Sort.by("LENGTH(name)")); @@ -459,6 +450,8 @@ public class UserRepositoryCommon { userRepository.save(usr01); userRepository.save(usr02); + System.out.println(TimeZone.getDefault()); + List users = userRepository.findUsersWithGmailAddress(); assertEquals(1, users.size()); assertEquals(usr02, users.get(0)); From 647a6dc798f3674e6072e88ad158d41534cba232 Mon Sep 17 00:00:00 2001 From: Krzysiek Date: Sun, 19 Apr 2020 18:54:43 +0200 Subject: [PATCH 180/194] JAVA-1130: Update the x509 mutual authentication codebase --- .../spring-security-x509/keystore/Makefile | 92 ------------------ .../keystore/keystore.jks | Bin 9310 -> 0 bytes .../src/main/resources/application.properties | 2 +- .../x509/X509AuthenticationServer.java | 8 +- .../src/main/resources/application.properties | 4 +- .../src/main/resources/keystore.jks | Bin 9310 -> 0 bytes .../spring-security-x509/store/clientBob.p12 | Bin 0 -> 4024 bytes .../spring-security-x509/store/keystore.jks | Bin 0 -> 3718 bytes .../spring-security-x509/store/rootCA.crt | 30 ++++++ .../spring-security-x509/store/truststore.jks | Bin 0 -> 1358 bytes 10 files changed, 39 insertions(+), 97 deletions(-) delete mode 100644 spring-security-modules/spring-security-x509/keystore/Makefile delete mode 100644 spring-security-modules/spring-security-x509/keystore/keystore.jks delete mode 100644 spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/keystore.jks create mode 100644 spring-security-modules/spring-security-x509/store/clientBob.p12 create mode 100644 spring-security-modules/spring-security-x509/store/keystore.jks create mode 100644 spring-security-modules/spring-security-x509/store/rootCA.crt create mode 100644 spring-security-modules/spring-security-x509/store/truststore.jks diff --git a/spring-security-modules/spring-security-x509/keystore/Makefile b/spring-security-modules/spring-security-x509/keystore/Makefile deleted file mode 100644 index 2cd7c55c5b..0000000000 --- a/spring-security-modules/spring-security-x509/keystore/Makefile +++ /dev/null @@ -1,92 +0,0 @@ -PASSWORD=changeit -KEYSTORE=keystore.jks -HOSTNAME=localhost -CLIENTNAME=cid -CLIENT_PRIVATE_KEY="${CLIENTNAME}_pk" - -# CN = Common Name -# OU = Organization Unit -# O = Organization Name -# L = Locality Name -# ST = State Name -# C = Country (2-letter Country Code) -# E = Email -DNAME_CA='CN=Baeldung CA,OU=baeldung.com,O=Baeldung,L=SomeCity,ST=SomeState,C=CC' -# For server certificates, the Common Name (CN) must be the hostname -DNAME_HOST='CN=$(HOSTNAME),OU=baeldung.com,O=Baeldung,L=SomeCity,ST=SomeState,C=CC' -DNAME_CLIENT='CN=$(CLIENTNAME),OU=baeldung.com,O=Baeldung,L=SomeCity,ST=SomeState,C=CC' -TRUSTSTORE=truststore.jks - -all: clean create-keystore add-host create-truststore add-client - -create-keystore: - # Generate a certificate authority (CA) - keytool -genkey -alias ca -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \ - -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \ - -validity 3650 -dname $(DNAME_CA) \ - -keystore $(KEYSTORE) -storepass $(PASSWORD) - -add-host: - # Generate a host certificate - keytool -genkey -alias $(HOSTNAME) -ext san=dns:localhost,ip:127.0.0.1 \ - -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \ - -validity 3650 -dname $(DNAME_HOST) \ - -keystore $(KEYSTORE) -storepass $(PASSWORD) - # Generate a host certificate signing request - keytool -certreq -alias $(HOSTNAME) -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \ - -keyalg RSA -keysize 4096 -sigalg SHA512withRSA \ - -validity 3650 -file "$(HOSTNAME).csr" \ - -keystore $(KEYSTORE) -storepass $(PASSWORD) - # Generate signed certificate with the certificate authority - keytool -gencert -alias ca -ext san=dns:localhost,ip:127.0.0.1 \ - -validity 3650 -sigalg SHA512withRSA \ - -infile "$(HOSTNAME).csr" -outfile "$(HOSTNAME).crt" -rfc \ - -keystore $(KEYSTORE) -storepass $(PASSWORD) - # Import signed certificate into the keystore - keytool -import -trustcacerts -alias $(HOSTNAME) -ext san=dns:localhost,ip:127.0.0.1 \ - -file "$(HOSTNAME).crt" \ - -keystore $(KEYSTORE) -storepass $(PASSWORD) - -export-authority: - # Export certificate authority - keytool -export -alias ca -ext san=dns:localhost,ip:127.0.0.1 -file ca.crt -rfc \ - -keystore $(KEYSTORE) -storepass $(PASSWORD) - - -create-truststore: export-authority - # Import certificate authority into a new truststore - keytool -import -trustcacerts -noprompt -alias ca -ext san=dns:localhost,ip:127.0.0.1 -file ca.crt \ - -keystore $(TRUSTSTORE) -storepass $(PASSWORD) - -add-client: - # Generate client certificate - keytool -genkey -alias $(CLIENT_PRIVATE_KEY) -ext san=dns:localhost,ip:127.0.0.1 \ - -keyalg RSA -keysize 4096 -sigalg SHA512withRSA -keypass $(PASSWORD) \ - -validity 3650 -dname $(DNAME_CLIENT) \ - -keystore $(TRUSTSTORE) -storepass $(PASSWORD) - # Generate a host certificate signing request - keytool -certreq -alias $(CLIENT_PRIVATE_KEY) -ext san=dns:localhost,ip:127.0.0.1 -ext BC=ca:true \ - -keyalg RSA -keysize 4096 -sigalg SHA512withRSA \ - -validity 3650 -file "$(CLIENTNAME).csr" \ - -keystore $(TRUSTSTORE) -storepass $(PASSWORD) - # Generate signed certificate with the certificate authority - keytool -gencert -alias ca -ext san=dns:localhost,ip:127.0.0.1 \ - -validity 3650 -sigalg SHA512withRSA \ - -infile "$(CLIENTNAME).csr" -outfile "$(CLIENTNAME).crt" -rfc \ - -keystore $(KEYSTORE) -storepass $(PASSWORD) - # Import signed certificate into the truststore - keytool -import -trustcacerts -alias $(CLIENTNAME) -ext san=dns:localhost,ip:127.0.0.1 \ - -file "$(CLIENTNAME).crt" \ - -keystore $(TRUSTSTORE) -storepass $(PASSWORD) - # Export private certificate for importing into a browser - keytool -importkeystore -srcalias $(CLIENT_PRIVATE_KEY) -ext san=dns:localhost,ip:127.0.0.1 \ - -srckeystore $(TRUSTSTORE) -srcstorepass $(PASSWORD) \ - -destkeystore "$(CLIENTNAME).p12" -deststorepass $(PASSWORD) \ - -deststoretype PKCS12 - # Delete client private key as truststore should not contain any private keys - keytool -delete -alias $(CLIENT_PRIVATE_KEY) \ - -keystore $(TRUSTSTORE) -storepass $(PASSWORD) - -clean: - # Remove generated artifacts - find . \( -name "$(CLIENTNAME)*" -o -name "$(HOSTNAME)*" -o -name "$(KEYSTORE)" -o -name "$(TRUSTSTORE)" -o -name ca.crt \) -type f -exec rm -f {} \; diff --git a/spring-security-modules/spring-security-x509/keystore/keystore.jks b/spring-security-modules/spring-security-x509/keystore/keystore.jks deleted file mode 100644 index 044a820c39524f1ef3c470105dbaa82b63af0493..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9310 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 DeRHq; diff --git a/spring-security-modules/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties b/spring-security-modules/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties index 53dfe9976a..208cc90b47 100644 --- a/spring-security-modules/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties +++ b/spring-security-modules/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties @@ -1,4 +1,4 @@ -server.ssl.key-store=keystore/keystore.jks +server.ssl.key-store=store/keystore.jks server.ssl.key-store-password=changeit server.ssl.key-alias=localhost server.ssl.key-password=changeit diff --git a/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java b/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java index 050423238e..18bbfba835 100644 --- a/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java +++ b/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/java/com/baeldung/spring/security/x509/X509AuthenticationServer.java @@ -23,7 +23,11 @@ public class X509AuthenticationServer extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests().anyRequest().authenticated().and().x509().subjectPrincipalRegex("CN=(.*?)(?:,|$)").userDetailsService(userDetailsService()); + http.authorizeRequests().anyRequest().authenticated() + .and() + .x509() + .subjectPrincipalRegex("CN=(.*?)(?:,|$)") + .userDetailsService(userDetailsService()); } @Bean @@ -31,7 +35,7 @@ public class X509AuthenticationServer extends WebSecurityConfigurerAdapter { return new UserDetailsService() { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - if (username.equals("cid")) { + if (username.equals("Bob")) { return new User(username, "", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); } throw new UsernameNotFoundException("User not found!"); diff --git a/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties b/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties index 743c9c4582..b841a37916 100644 --- a/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties +++ b/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties @@ -1,4 +1,4 @@ -server.ssl.key-store=../keystore/keystore.jks +server.ssl.key-store=store/keystore.jks server.ssl.key-store-password=changeit server.ssl.key-alias=localhost server.ssl.key-password=changeit @@ -6,6 +6,6 @@ server.ssl.enabled=true server.port=8443 spring.security.user.name=Admin spring.security.user.password=admin -server.ssl.trust-store=../keystore/truststore.jks +server.ssl.trust-store=store/truststore.jks server.ssl.trust-store-password=changeit server.ssl.client-auth=need \ No newline at end of file diff --git a/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/keystore.jks b/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/keystore.jks deleted file mode 100644 index 044a820c39524f1ef3c470105dbaa82b63af0493..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9310 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 DeRHq; diff --git a/spring-security-modules/spring-security-x509/store/clientBob.p12 b/spring-security-modules/spring-security-x509/store/clientBob.p12 new file mode 100644 index 0000000000000000000000000000000000000000..e5d6dbcefbfaffa2502b1ed9613bc1cb2f9ce573 GIT binary patch literal 4024 zcmY+GWmFW5v&MIqZh-}s7H}zvr9qICkdS6+q@+>cl?GwSrBgz>Te<`!q@`hLWC7`J z$?JR0z4w3bhdFc3^UTc0-#jn`Nj(UN0Yi{@W8-m#DurGV0dasi2oeWO1c}XG*%F4p z^7xO1orA!#{VQ34fPlZv-MCSZy*pZAOL{{Bb*WK z+Q7<^IQ0>{dto8^GS#!m3iTTR@sErIAjrY_ZaD&Xt9_WL>)htDtg>Y6i~!Q_bZTmEa}l>d})jt@Dbhav#Be0ycXDcBFecnmQuV&%6NFb+V1* z^;0ZEheC>1x$N9e>YrUX^z*}mW9f;g%!%YkYrF}^`i$6HvgwaD#kht=&FSMX*(PLu zUX}j3X@&-Y9uNC^I#iMEner`-6qB8^4_~qqP3Eexx=)fjW=^(JV=K>!Bv@ykMkCQd zmFfP$!t-{d4b~H`A?;lz!}my*%(?oFS5-emg3s0R{HSWyvvKrd-xGBY#Hzq^3TLj> z2i4b1Pb>ftI%T=j&?}bx&`vFVO!p>znntW0<)vMexnSQU%rdWH_+g?%s<0q8?B*R$ zK1>((*+%)q;75B?llfXlzi43L+bu~OJ7;Jzy4BEALQ0Q^v)l%{=kkxC7h%MW@I-E+ zas7bTC&Eo86o!PKDJ^8Lg=pR}B_)SaaX@opyQ|Zn78LX?GrXv_03T!HUUSrKK(EDg zNpfJT8Q0{LvAtmUXSj>GCJEPWY?9k1iARi#Hqr*Pw2TieWwyd@Vsd$*mZTIiBOCfV zR!+_Q8ay58pv+qHq1SQGTuHpj4GrKP1jL_>wJmF$WV_}!!yK%((lQlcCtmqU4s(Tk zyTtMF^VjbnY_p$?JheGW;tI3hr@PW)!u_4-$^0DL3Ih8Se-JX7YR9$@AJ~=X{z~p{ z?dM#}<~xJiD|VgmX_+N!5K|)6ejpGKZLszEp_Ctr7wNh6d-{3it6+@#jN`cyL882k zHJx6G4hDbd#7Ml=oC{>}DP2E3+9qA6VNsoI(gUr5O4A4&K|6I~U&@t3b4qceKJW`&G=^e zusODCXOd*Svc0$f3&$`amP6@{^K3l);Ze*Amuj4*QH5-Sce#k;>Udac-@W{geXT*^ z-Pg#167Pd;X9*S`Bx_w9nWvbQ7IZ~-SewYlN>M!1@ZNp#g(_B|jgNX?b06Sq7&lo58{KPxFAs7=NOm=bxYFW4w_rYR~sp{?a{jJ@8P56x1F z@*6VN43*j*Sqd{OJ$ui-z~gm58oU0wDN2K$X~aSz*7ndX2!G#k+Sl-5;dGE!B(K!8 zv;TOxr)ev%=c67w!K60+%M6Ma7tsw|i{82%l5rPJ^-E-)`Y(|W1+~h|cNB+N(>BV# zB!C|d#rM+M8Js*4EX^#O1QTL@~r3?kDe{1D(M9n0&nC005%7KH-m}5oA@h_{H;N3g8#uSJ`nWR zbp9*a|33<2{7c~mg#xvGe_-vu6#l!e6bvLu#UXVUi}F(vpJuK80F_S=!C-+*5}K@e z3pnjhzZR2bJu>{lhNnGr07!i9Wg$?CYTrR^!lWV`gO=@GzA=uPu+zok&19rACQWG! zzQrUt3x}j|b8D3GQndh??&ne)Zs<-vEm0TKipkF6-6y84n)X-M&gTg91&P*=Rnl0e zmSY~@kl}8dDPN8k%|!&kKhbokP&m*mSW_+&W&2Dp9sM)t)u8zFX}o*Tz~+@>N7vKE z`LwTxw8qZnltj=o?TSl%e9p;>GQ}pz5%T4!;U3&miwZSu2Apjw;y6YIjAZhjAqSoq zrk`hvL25}nQ4EsAUq+Cp^x6sYbE!%!KOo|qG~D@7eWO$wiN{@$DGSFql4jK0a5|9oK9-LwjaR zSTed;ZOPRex3`E1+1lrkFW~;Z+lcp4ov0reLDGrMBVEzIXKHr5drL4DM2R;3j(Heu zAgkl8r~t|Eg|qR|)rkHmaQ+$=G9v2T6~{S>UFW;ue(`ZU&PFkYbg`K0j}|S(SOu*r z$fwIYQ2~tC>u#WVbmAnn^tS&`D;TeeOfG&=#hKWsxBgFS>~o)6gL9+CG8RVzBOfzKta6@gy9Wyoy)aM_x=(#?-JsH*gKeLSaP~kd+A|n+aRy@=!f3e-kH4*V4Kdj@`PevuI*n z5U-0?86K}2DxdL~`TcHwB%e}?wrgIO6&$5DkRmtJWYKQBBYvK5T5V-)Lt)r5JpXl5 z+kk%QUF@$cK?PtcL8NUmXXdS~fkHG`p?AvAsBIlx`KJcGHHLB>mWdyWPFWmX0J`&d2R z3Y^5`Iay|gIeCW~`hH1gRK>gR=b3a6?U2`bP9V$sbmP1lY< zkG)1({kKW@n>bPqz};2~S))A>t=>-wQD&(^jY35)rlzRuMEI30&yue7GwRT*&orD3 zSy62EfSW7hI~QBikUjlC_64CQF}T61@4SzLUspw-)>`e-UU17RR9wiv4G4&oz3&$h zexvtNM+<%GK##Y1DB;TGF2viN+gmc(XC9P_gx9D&3O0eIiGywJBI-+iU~o=syk^kU z?xc@abmN!OabI@b(5O=Ne@_O9VMqgM#6+dKq|?Jrs!(Rcv#G{M+XvPAL`bq0MpHlvM@Ls{R6`#$9%_D zPD#%ytxNUI6QWa!DaJ5WhEq1jOSEzcMz7mWjC{Q_G7^<&784i2)~bC|&u^0qKH))0 zNpv=4EuqPKaIoSXJT8v7c6AdG>mI6{N>o0jE-pf=W2-j$X!+%P?rN6I_u2d5sq<8R zqhZL5)3S?;siTP;)~d&;TO02Y+bg;imI-Fnb{e<1!WG*NjXDi;+`n%oS+-2R=-{Ws zhi>Yp>$;McXtjgMtI9VWpYG*@7=uWkeF%SryJ(q|ZX=2*O}BfNE8x-&-`Q3sXG0aF z&%34UjY}?5FmmEWR@3DR3r6!r+_zDtk3ux$l<7%AOMVIQ&VX&Ym%tvBg6zPD^IKt2 zg?tBRe0Jd$)%dA7%kvuqFW}<*B&=4>p>EKb`%5Tp97G!8n$``))c$>2q+uS-=EPXFXf_e8cRTdwN8k;~nJg>MXyJ&bkEe%isWB$9`MG83C? zk&Pt5+fV_6$xBpkl>5X%is7bGnbrpf3r=K>MxRVCtG4xh-M1YSWS+PuXl|5K5HP@^ z@1Kf-e$3_x@K?T6-L)J=`5lTA$0yJNbYyE$nlSfd3IXhJXU~cRT#VcK*e&4)YczYKNkox) zb?O4~`{d|?5e6T{nCNG`B`t%Y$MHQaOuW(tBiUG-iPeny$DOi)I1l5Fgiz*~;Y(s0 z45NkdVCQnV5X%bV*8U+(-;uK_t+j`x+X%NJbrUjddB#>Fv7{^S zM36(oNsVphOg}ykVgPeAKW(@w-;wwZ6?(o3Ja}}i7>P!`JpQ`Fa;YY*s?ex+Crk<) z5nc^!KyA~i9#s_19;bCJvC&mELU;!|}ImmJ8#ohgG`+9>T;Nm5|6`9fs SChlA@P5Y@C!_vP&?!N$UlZxN~ literal 0 HcmV?d00001 diff --git a/spring-security-modules/spring-security-x509/store/keystore.jks b/spring-security-modules/spring-security-x509/store/keystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..8650651a1e0a884555a4219049340ce2314315cb GIT binary patch literal 3718 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 kxy)FR?K>|cBR4C9fw-ZlfiN3$C<`+Wk5gi5 zPD*KBx?XaAu7R95uaSX)iJ_&TnW34HMU*(NF^Fpp<>J=Z#H5652_q{5a}yIk1JGSu zOifIT49BM$^W7KtHD8{=CFWDwpFN*~jdU}7-`?18;<3|VO_vGD;VNb<+qW>AuXi$d z+oJIE)#-n`7izGno#5qty|q-+Pj^c!t5xPwt8FLS9Hi=PSA_?At#G$8^7(OTna9h| zU(*}v$}+D{xY!uv$o}!{!5pDUs)di5K5kjHEJR_(dAEf^p9QM-s5QNnDbY_8xtY14 ze!I&QbG^RL{d}_;m7|jnojABZ_RRSUl0hOS|L+8GPPIH${aC)WCOYZOTt~J`+Zx`v ztz#^&C$$!4y6MDMqL)gMoDi10a{ZzWX*Q8hF{?3UT-ajz-#M3b0%0(^X%jQz9 z(*yYS1gA(^+|%v*vt@(bb5C#m zqr1t9XZfFGFE&lnR$O%ml^CD z{o;x)T|blmM)~@se4iVSxWE5ot?8ft;N1Ti&QlKZ*s0xjVYUz0WGb8PGuz)oclE_t z3I!RT`y}!exvDpQUOri8a{s@3i;6{Rnm(@Ceb17c?{Bijs=xeyWd9n^_u8{|(slmd z`c=PJWtWE(8cY9e{TReJS2gx-OMJZeOF<@PMh3>k!3Kc_vcPmF%f}+dBJxQvl(Soo z=TPMDBWBa5xaB_Hp0vY29we>IB4HrbfL#GUNP#dT<9`-b17;wFoa}&U8<^}E8Pay; zebn#TwpV0c<<~9w^A_inu9@Bce!`dTz>_cDuzh;BWJe-bVHkJR^}E^gmn&{;WLWoL z=YyY9->QqOczDVCG3(*_sdj%nxGxn4#EB?QJhkkWuNxZ!|D1)ozi%GBU%N~2gvZ;M zYSlOf>+?yq*YDh&_v*{xX~Nw~>-svkta}=n{{GD#;jiq@(O);bXJxQh?wJ(Icy6(T zJR{?r4qs#K)+&R~#fi%%&gkfg+L^P8S8TSjj3&Q)!(BcRu5z}ms?ullcl}Xv&C)N< z@S3}Rf~>WXOOo6b?x(W*5A{kO-**E-gD3D1RFrm1-CeZKbAvKgL{4}&FC*7<$6{b(+^U$i;;V4Pmt zv=YHOzmC{4^Q{*|w<&tR_Lz90PnLUW66Z^n8$VZW(21SmsiDp~hdeXV-epP%lLX{{Pt~YuAkgeTRL%j-Pav1UuxNS z9G07G_!P#)_@z?sMs=5H(tpdsH0#^(y3D_O{F^7Y9jblszw$@S4hKVfYpsuWzDC@Z zySMI8(u4W>yZHG%nwAAWDG8X{u^;1It literal 0 HcmV?d00001 From 7b0c9d508f38ceb812bae691606755c53b897870 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Mon, 20 Apr 2020 12:00:03 +0300 Subject: [PATCH 181/194] Update README.md --- libraries-data-2/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries-data-2/README.md b/libraries-data-2/README.md index 24618b5e37..f96fab5120 100644 --- a/libraries-data-2/README.md +++ b/libraries-data-2/README.md @@ -11,4 +11,7 @@ This module contains articles about libraries for data processing in Java. - [Guide to JMapper](https://www.baeldung.com/jmapper) - [An Introduction to SuanShu](https://www.baeldung.com/suanshu) - [Intro to Derive4J](https://www.baeldung.com/derive4j) -More articles: [[<-- prev]](/../libraries-data) \ No newline at end of file +More articles: [[<-- prev]](/../libraries-data) + +#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. From f55d344629d3a148ed5fce139bf3fc688cf8962c Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Mon, 20 Apr 2020 12:01:27 +0300 Subject: [PATCH 182/194] Update README.md --- libraries-data-2/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries-data-2/README.md b/libraries-data-2/README.md index f96fab5120..f992186bd9 100644 --- a/libraries-data-2/README.md +++ b/libraries-data-2/README.md @@ -13,5 +13,5 @@ This module contains articles about libraries for data processing in Java. - [Intro to Derive4J](https://www.baeldung.com/derive4j) More articles: [[<-- prev]](/../libraries-data) -#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. +##### 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. From 8da24b4abe906ab8dae62e007a0f13b1d097c50b Mon Sep 17 00:00:00 2001 From: Vikas Rajput Date: Mon, 20 Apr 2020 19:01:55 +0300 Subject: [PATCH 183/194] BAEL-3557: Completed a simple web application in spring boot and groovy (#9152) Co-authored-by: Vikas Ramsingh Rajput --- spring-boot-groovy/pom.xml | 83 ++++++++++++++++ .../app/SpringBootGroovyApplication.groovy | 13 +++ .../app/controller/TodoController.groovy | 48 +++++++++ .../com/baeldung/app/entity/Todo.groovy | 23 +++++ .../app/repository/TodoRepository.groovy | 9 ++ .../baeldung/app/service/TodoService.groovy | 16 +++ .../app/service/impl/TodoServiceImpl.groovy | 40 ++++++++ .../src/main/resources/application.properties | 5 + .../com/baeldung/app/TodoAppUnitTest.groovy | 97 +++++++++++++++++++ 9 files changed, 334 insertions(+) create mode 100644 spring-boot-groovy/pom.xml create mode 100644 spring-boot-groovy/src/main/groovy/com/baeldung/app/SpringBootGroovyApplication.groovy create mode 100644 spring-boot-groovy/src/main/groovy/com/baeldung/app/controller/TodoController.groovy create mode 100644 spring-boot-groovy/src/main/groovy/com/baeldung/app/entity/Todo.groovy create mode 100644 spring-boot-groovy/src/main/groovy/com/baeldung/app/repository/TodoRepository.groovy create mode 100644 spring-boot-groovy/src/main/groovy/com/baeldung/app/service/TodoService.groovy create mode 100644 spring-boot-groovy/src/main/groovy/com/baeldung/app/service/impl/TodoServiceImpl.groovy create mode 100644 spring-boot-groovy/src/main/resources/application.properties create mode 100644 spring-boot-groovy/src/test/groovy/com/baeldung/app/TodoAppUnitTest.groovy diff --git a/spring-boot-groovy/pom.xml b/spring-boot-groovy/pom.xml new file mode 100644 index 0000000000..f61398c5d6 --- /dev/null +++ b/spring-boot-groovy/pom.xml @@ -0,0 +1,83 @@ + + + + 4.0.0 + com.baeldung.app + spring-boot-groovy + spring-boot-groovy + war + Spring Boot Todo Application with Groovy + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + org.codehaus.groovy + groovy + + + + org.springframework.boot + spring-boot-starter-test + test + + + com.h2database + h2 + runtime + + + net.bytebuddy + byte-buddy-dep + 1.10.9 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.codehaus.gmavenplus + gmavenplus-plugin + 1.9.0 + + + + addSources + addTestSources + generateStubs + compile + generateTestStubs + compileTests + removeStubs + removeTestStubs + + + + + + + + + com.baeldung.app.SpringBootGroovyApplication + + + diff --git a/spring-boot-groovy/src/main/groovy/com/baeldung/app/SpringBootGroovyApplication.groovy b/spring-boot-groovy/src/main/groovy/com/baeldung/app/SpringBootGroovyApplication.groovy new file mode 100644 index 0000000000..226a2ff53d --- /dev/null +++ b/spring-boot-groovy/src/main/groovy/com/baeldung/app/SpringBootGroovyApplication.groovy @@ -0,0 +1,13 @@ +package com.baeldung.app + +import org.springframework.boot.SpringApplication +import org.springframework.boot.autoconfigure.SpringBootApplication + +import com.baeldung.app.SpringBootGroovyApplication + +@SpringBootApplication +class SpringBootGroovyApplication { + static void main(String[] args) { + SpringApplication.run SpringBootGroovyApplication, args + } +} diff --git a/spring-boot-groovy/src/main/groovy/com/baeldung/app/controller/TodoController.groovy b/spring-boot-groovy/src/main/groovy/com/baeldung/app/controller/TodoController.groovy new file mode 100644 index 0000000000..02f6d0223b --- /dev/null +++ b/spring-boot-groovy/src/main/groovy/com/baeldung/app/controller/TodoController.groovy @@ -0,0 +1,48 @@ +package com.baeldung.app.controller + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.web.bind.annotation.DeleteMapping +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.PutMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestMethod +import org.springframework.web.bind.annotation.RestController + +import com.baeldung.app.entity.Todo +import com.baeldung.app.service.TodoService + +@RestController +@RequestMapping('todo') +public class TodoController { + + @Autowired + TodoService todoService + + @GetMapping + List getAllTodoList(){ + todoService.findAll() + } + + @PostMapping + Todo saveTodo(@RequestBody Todo todo){ + todoService.saveTodo todo + } + + @PutMapping + Todo updateTodo(@RequestBody Todo todo){ + todoService.updateTodo todo + } + + @DeleteMapping('/{todoId}') + deleteTodo(@PathVariable Integer todoId){ + todoService.deleteTodo todoId + } + + @GetMapping('/{todoId}') + Todo getTodoById(@PathVariable Integer todoId){ + todoService.findById todoId + } +} \ No newline at end of file diff --git a/spring-boot-groovy/src/main/groovy/com/baeldung/app/entity/Todo.groovy b/spring-boot-groovy/src/main/groovy/com/baeldung/app/entity/Todo.groovy new file mode 100644 index 0000000000..9f1253c5b3 --- /dev/null +++ b/spring-boot-groovy/src/main/groovy/com/baeldung/app/entity/Todo.groovy @@ -0,0 +1,23 @@ +package com.baeldung.app.entity + +import javax.persistence.Column +import javax.persistence.Entity +import javax.persistence.GeneratedValue +import javax.persistence.GenerationType +import javax.persistence.Id +import javax.persistence.Table + +@Entity +@Table(name = 'todo') +class Todo { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + Integer id + + @Column + String task + + @Column + Boolean isCompleted + +} diff --git a/spring-boot-groovy/src/main/groovy/com/baeldung/app/repository/TodoRepository.groovy b/spring-boot-groovy/src/main/groovy/com/baeldung/app/repository/TodoRepository.groovy new file mode 100644 index 0000000000..c0b35cc37d --- /dev/null +++ b/spring-boot-groovy/src/main/groovy/com/baeldung/app/repository/TodoRepository.groovy @@ -0,0 +1,9 @@ +package com.baeldung.app.repository + +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +import com.baeldung.app.entity.Todo + +@Repository +interface TodoRepository extends JpaRepository {} \ No newline at end of file diff --git a/spring-boot-groovy/src/main/groovy/com/baeldung/app/service/TodoService.groovy b/spring-boot-groovy/src/main/groovy/com/baeldung/app/service/TodoService.groovy new file mode 100644 index 0000000000..0a59d93330 --- /dev/null +++ b/spring-boot-groovy/src/main/groovy/com/baeldung/app/service/TodoService.groovy @@ -0,0 +1,16 @@ +package com.baeldung.app.service + +import com.baeldung.app.entity.Todo + +interface TodoService { + + List findAll() + + Todo findById(Integer todoId) + + Todo saveTodo(Todo todo) + + Todo updateTodo(Todo todo) + + Todo deleteTodo(Integer todoId) +} diff --git a/spring-boot-groovy/src/main/groovy/com/baeldung/app/service/impl/TodoServiceImpl.groovy b/spring-boot-groovy/src/main/groovy/com/baeldung/app/service/impl/TodoServiceImpl.groovy new file mode 100644 index 0000000000..6d0ee03a9f --- /dev/null +++ b/spring-boot-groovy/src/main/groovy/com/baeldung/app/service/impl/TodoServiceImpl.groovy @@ -0,0 +1,40 @@ +package com.baeldung.app.service.impl + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service + +import com.baeldung.app.entity.Todo +import com.baeldung.app.repository.TodoRepository +import com.baeldung.app.service.TodoService + +@Service +class TodoServiceImpl implements TodoService { + + @Autowired + TodoRepository todoRepository + + @Override + List findAll() { + todoRepository.findAll() + } + + @Override + Todo findById(Integer todoId) { + todoRepository.findById todoId get() + } + + @Override + Todo saveTodo(Todo todo){ + todoRepository.save todo + } + + @Override + Todo updateTodo(Todo todo){ + todoRepository.save todo + } + + @Override + Todo deleteTodo(Integer todoId){ + todoRepository.deleteById todoId + } +} diff --git a/spring-boot-groovy/src/main/resources/application.properties b/spring-boot-groovy/src/main/resources/application.properties new file mode 100644 index 0000000000..8d53a190bb --- /dev/null +++ b/spring-boot-groovy/src/main/resources/application.properties @@ -0,0 +1,5 @@ +spring.datasource.url=jdbc:h2:mem:todo +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=sa +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/spring-boot-groovy/src/test/groovy/com/baeldung/app/TodoAppUnitTest.groovy b/spring-boot-groovy/src/test/groovy/com/baeldung/app/TodoAppUnitTest.groovy new file mode 100644 index 0000000000..faf2d64ba7 --- /dev/null +++ b/spring-boot-groovy/src/test/groovy/com/baeldung/app/TodoAppUnitTest.groovy @@ -0,0 +1,97 @@ +package com.baeldung.app + +import static org.junit.jupiter.api.Assertions.assertEquals +import static org.junit.jupiter.api.Assertions.assertTrue + +import org.junit.BeforeClass +import org.junit.Test +import org.junit.runner.RunWith +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.test.context.event.annotation.BeforeTestClass +import org.springframework.test.context.junit4.SpringRunner + +import com.baeldung.app.entity.Todo + +import io.restassured.RestAssured +import io.restassured.response.Response + +class TodoAppUnitTest { + static API_ROOT = 'http://localhost:8081/todo' + static readingTodoId + static writingTodoId + + @BeforeClass + static void populateDummyData() { + Todo readingTodo = new Todo(task: 'Reading', isCompleted: false) + Todo writingTodo = new Todo(task: 'Writing', isCompleted: false) + + final Response readingResponse = + RestAssured.given() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(readingTodo).post(API_ROOT) + + Todo cookingTodoResponse = readingResponse.as Todo.class + readingTodoId = cookingTodoResponse.getId() + + final Response writingResponse = + RestAssured.given() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(writingTodo).post(API_ROOT) + + Todo writingTodoResponse = writingResponse.as Todo.class + writingTodoId = writingTodoResponse.getId() + } + + @Test + void whenGetAllTodoList_thenOk(){ + final Response response = RestAssured.get(API_ROOT) + + assertEquals HttpStatus.OK.value(),response.getStatusCode() + assertTrue response.as(List.class).size() > 0 + } + + @Test + void whenGetTodoById_thenOk(){ + final Response response = + RestAssured.get("$API_ROOT/$readingTodoId") + + assertEquals HttpStatus.OK.value(),response.getStatusCode() + Todo todoResponse = response.as Todo.class + assertEquals readingTodoId,todoResponse.getId() + } + + @Test + void whenUpdateTodoById_thenOk(){ + Todo todo = new Todo(id:readingTodoId, isCompleted: true) + final Response response = + RestAssured.given() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(todo).put(API_ROOT) + + assertEquals HttpStatus.OK.value(),response.getStatusCode() + Todo todoResponse = response.as Todo.class + assertTrue todoResponse.getIsCompleted() + } + + @Test + void whenDeleteTodoById_thenOk(){ + final Response response = + RestAssured.given() + .delete("$API_ROOT/$writingTodoId") + + assertEquals HttpStatus.OK.value(),response.getStatusCode() + } + + @Test + void whenSaveTodo_thenOk(){ + Todo todo = new Todo(task: 'Blogging', isCompleted: false) + final Response response = + RestAssured.given() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(todo).post(API_ROOT) + + assertEquals HttpStatus.OK.value(),response.getStatusCode() + } +} \ No newline at end of file From 6dcb364fe7ca11aab44ddb190227fb5a9cc0946a Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 20 Apr 2020 22:42:22 +0530 Subject: [PATCH 184/194] JAVA-917: Migrate jhipster-5 to parent-boot-2 --- jhipster-5/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jhipster-5/pom.xml b/jhipster-5/pom.xml index cebbe25d8b..2a5132e50e 100644 --- a/jhipster-5/pom.xml +++ b/jhipster-5/pom.xml @@ -9,10 +9,10 @@ pom - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 From fd318eb47615796d28901386aa158b51212db0fb Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 20 Apr 2020 23:15:30 +0530 Subject: [PATCH 185/194] JAVA-919: Migrate jmeter to parent-boot-2 --- jmeter/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jmeter/pom.xml b/jmeter/pom.xml index 64642695ff..945210edd7 100644 --- a/jmeter/pom.xml +++ b/jmeter/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 From 4fe86bb104b27cbb2601b0aac5f81a295fba0402 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Mon, 20 Apr 2020 23:42:21 +0530 Subject: [PATCH 186/194] JAVA-920: Migrate libraries-security to parent-boot-2 --- libraries-security/pom.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries-security/pom.xml b/libraries-security/pom.xml index e287de4527..e02f766141 100644 --- a/libraries-security/pom.xml +++ b/libraries-security/pom.xml @@ -8,9 +8,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -23,7 +23,9 @@ org.springframework.security.oauth spring-security-oauth2 + ${spring-boot.version} + org.springframework spring-web From 34d94a78f0639095029abfc7acd3a85b0c6dabc7 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Tue, 21 Apr 2020 11:33:15 +0530 Subject: [PATCH 187/194] JAVA-920: Copied missing artifact so that live test runs ok --- .../src/main/resources/Baeldung.p12 | Bin 0 -> 2502 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 libraries-security/src/main/resources/Baeldung.p12 diff --git a/libraries-security/src/main/resources/Baeldung.p12 b/libraries-security/src/main/resources/Baeldung.p12 new file mode 100644 index 0000000000000000000000000000000000000000..65ec8bc8fec33120b2c11276883dde5dad7a3ea6 GIT binary patch literal 2502 zcmY+Ec{CJ^8pg-W7-KiSAxm~&AvE}qeFbou@HKRX#MCzW*R!0LL7Y% z7)Sr`m+g30_7yeFjs-&~fCI+{-yx;|%9MeT2(tgQ10!G4XA2 zkG>wSErwX=^nQsIu&jb*uF4fhJf{o`c{-h8IOQJ-3P1FiZj0wRF6K9 z8mc&Zv?tvBj9P!Y^4uoj2G=6#18%wBeI!8jBRU|{P+P>0Aj=k375X=>QV+%oS!bk}+lJ+=1;z2pF||>sP$r3Brd~; zK)4%I2x>Ka+<;kKSK~)>L|uxGz&8_NxTGL2SC%Ui58tY=@-RCRhmrcaiO=Kg3VLao zL4POxN4d@n*d5|D3|P>OiNs!L2y3}V91S9g=+MPm2z2B)8SfIlps2SxADFc?et7bp zX$NVVRh<~4WzxjUvYD%W)wYw9O8Brp^L0RcbZ~X#P4;$ zj@d^cTmNv5A?VBUvx?k4kPIs2@lgJ*dzk-y`e;r~_tMcguyihj(WZx;W7st6eU1^p zA%3;BP+|V=UsgnMaP2xR9K?kLwyMXM~nWS!589aEx|ZivtPE+FCig}|Cv7n z4X_Xg-u#7*)&HXc=rv2DY6l{514xv{C2smp+M* z0HVF+G4qecX9^nOQ_20k2BM02$9dQ593Rq`jJUz%jTp%B$M|BdRc91;W`+2m}mmXL+cwS z-&0lg5an|f6il`kXk#vPZhK2Z{$$;;@;0;b_10a*B5Rf5vKBR^@uJW`WS*}TZ=JLU zrj7F9)-nOh*HW4C!Otz_FqYnEa!4nC@x0Wy?`_DN=c%fjkhTs@U^UB&)l0w$4n{K* zxd;D}W@$I_F{l@h(sB)s*Iz+sw{FOEa8& z#EfydGU+EgJ3m#S4b&`TTCBfC)eJ1M>U(%yKc+7F3lI-0X##xff#=dtmj;cWs@*(1 zZXS(tbGXP@?braN#P>=GxwN^xFqQBRSvZbJniMWr*lo`MXc=JWLQ&?yr)-$(Q$h^t zmmrKH?`t%wDk~pX1aJ^CbU%HXCAh@rR6?f`m^|7yVOF)+`(Y=4B-tto(B<>E=#QYq z&@RDn^M$lUwdx-1I4h;lvzUX6)HqThjqi4SlgM#nYG;nAtd-nO%TPn)KA9c{jep;9 zv79sQ{V`P{aJuEBb+8(|yi8}R z6hXIAFE*35l(toZR?k^d;kDRbp0Bi3D0P+;?`sW)yZdU2IS(8r-PlbgD6J2GLhODl zx^Ea$kiSoZQ1qd#$ zrw<*y{e#y|n++B0#ujM&wp!KoH<8hT7JB{RiW`47kpL%2BP;hRkV5E^;HN+5b za*HI=nMx7`*nucDb(iCuuCi`KplQ=xzr^Ya{l%oz=!5s?{M_rv@Zq3;FGnmok06!C z!iZ>7b}M(R4R=#t|6J8 Date: Wed, 22 Apr 2020 15:42:16 +0530 Subject: [PATCH 188/194] JAVA-921: Migrate mesos-marathon to parent-boot-2 --- mesos-marathon/README.md | 2 +- mesos-marathon/pom.xml | 4 ++-- .../java/com/baeldung/DemoApplicationIntegrationTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mesos-marathon/README.md b/mesos-marathon/README.md index 65b2361698..8e5b8e4974 100644 --- a/mesos-marathon/README.md +++ b/mesos-marathon/README.md @@ -6,4 +6,4 @@ This module contains articles about Marathon and Mesos. - [Simple Jenkins Pipeline with Marathon and Mesos](https://www.baeldung.com/jenkins-pipeline-with-marathon-mesos) - To run the pipeline, please modify the dockerise.sh file with your own useranema and password for docker login. + To run the pipeline, please modify the dockerise.sh file with your own username and password for docker login. diff --git a/mesos-marathon/pom.xml b/mesos-marathon/pom.xml index 4fb819c434..42798bb209 100644 --- a/mesos-marathon/pom.xml +++ b/mesos-marathon/pom.xml @@ -7,9 +7,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 diff --git a/mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java b/mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java index 85331516f9..dfe944a316 100644 --- a/mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java +++ b/mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java @@ -3,8 +3,8 @@ package com.baeldung; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.context.embedded.LocalServerPort; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.client.RestTemplate; From 0cf5e3662336102b3ce4a3ef045c27dadcdace76 Mon Sep 17 00:00:00 2001 From: sampadawagde Date: Wed, 22 Apr 2020 17:44:28 +0530 Subject: [PATCH 189/194] JAVA-922: Migrate flyway to parent-boot-2 --- persistence-modules/flyway/pom.xml | 6 +++--- .../flyway/src/main/resources/application.properties | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/persistence-modules/flyway/pom.xml b/persistence-modules/flyway/pom.xml index 01b3dab6ee..f2e393abbf 100644 --- a/persistence-modules/flyway/pom.xml +++ b/persistence-modules/flyway/pom.xml @@ -9,9 +9,9 @@ com.baeldung - parent-boot-1 + parent-boot-2 0.0.1-SNAPSHOT - ../../parent-boot-1 + ../../parent-boot-2 @@ -63,7 +63,7 @@ - 5.0.2 + 5.2.3 5.0.2 diff --git a/persistence-modules/flyway/src/main/resources/application.properties b/persistence-modules/flyway/src/main/resources/application.properties index 4d339eca5c..cee75fa4d9 100644 --- a/persistence-modules/flyway/src/main/resources/application.properties +++ b/persistence-modules/flyway/src/main/resources/application.properties @@ -1 +1 @@ -#flyway.enabled=false \ No newline at end of file +#spring.flyway.enabled=false \ No newline at end of file From 17d9e00dc3dd1cd6d6fb1a03d376a4c6c6e7e6b1 Mon Sep 17 00:00:00 2001 From: Sampada <46674082+sampada07@users.noreply.github.com> Date: Wed, 22 Apr 2020 20:21:36 +0530 Subject: [PATCH 190/194] BAEL-3988: Calling a SOAP web service in Java (#9166) --- jee-7/pom.xml | 23 ++++ .../soap/ws/client/generated/Country.java | 129 ++++++++++++++++++ .../ws/client/generated/CountryService.java | 34 +++++ .../generated/CountryServiceImplService.java | 91 ++++++++++++ .../soap/ws/client/generated/Currency.java | 37 +++++ .../ws/client/generated/ObjectFactory.java | 38 ++++++ .../ws/client/generated/package-info.java | 2 + .../com/baeldung/soap/ws/server/Country.java | 41 ++++++ .../soap/ws/server/CountryRepository.java | 43 ++++++ .../soap/ws/server/CountryService.java | 15 ++ .../soap/ws/server/CountryServiceImpl.java | 15 ++ .../ws/server/CountryServicePublisher.java | 19 +++ .../com/baeldung/soap/ws/server/Currency.java | 15 ++ jee-7/src/main/resources/country.wsdl | 40 ++++++ jee-7/src/main/resources/country.xsd | 21 +++ .../soap/ws/client/CountryClientLiveTest.java | 39 ++++++ 16 files changed, 602 insertions(+) create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Country.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/server/Country.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/server/CountryRepository.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/server/CountryService.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServiceImpl.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServicePublisher.java create mode 100644 jee-7/src/main/java/com/baeldung/soap/ws/server/Currency.java create mode 100644 jee-7/src/main/resources/country.wsdl create mode 100644 jee-7/src/main/resources/country.xsd create mode 100644 jee-7/src/test/java/com/baeldung/soap/ws/client/CountryClientLiveTest.java diff --git a/jee-7/pom.xml b/jee-7/pom.xml index a2593e46a5..7352c6550a 100644 --- a/jee-7/pom.xml +++ b/jee-7/pom.xml @@ -242,6 +242,29 @@ + + + org.codehaus.mojo + jaxws-maven-plugin + 2.6 + + + wsimport-from-jdk + + wsimport + + + + + src/main/resources + + country.wsdl + + true + com.baeldung.soap.ws.client.generated + src/main/java + + diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Country.java b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Country.java new file mode 100644 index 0000000000..6a810b9afa --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Country.java @@ -0,0 +1,129 @@ + +package com.baeldung.soap.ws.client.generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + +/** + *

    Java class for country complex type. + * + *

    The following schema fragment specifies the expected content contained within this class. + * + *

    + * <complexType name="country">
    + *   <complexContent>
    + *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
    + *       <sequence>
    + *         <element name="capital" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
    + *         <element name="currency" type="{http://server.ws.soap.baeldung.com/}currency" minOccurs="0"/>
    + *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
    + *         <element name="population" type="{http://www.w3.org/2001/XMLSchema}int"/>
    + *       </sequence>
    + *     </restriction>
    + *   </complexContent>
    + * </complexType>
    + * 
    + * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "country", propOrder = { "capital", "currency", "name", "population" }) +public class Country { + + protected String capital; + @XmlSchemaType(name = "string") + protected Currency currency; + protected String name; + protected int population; + + /** + * Gets the value of the capital property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCapital() { + return capital; + } + + /** + * Sets the value of the capital property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCapital(String value) { + this.capital = value; + } + + /** + * Gets the value of the currency property. + * + * @return + * possible object is + * {@link Currency } + * + */ + public Currency getCurrency() { + return currency; + } + + /** + * Sets the value of the currency property. + * + * @param value + * allowed object is + * {@link Currency } + * + */ + public void setCurrency(Currency value) { + this.currency = value; + } + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the population property. + * + */ + public int getPopulation() { + return population; + } + + /** + * Sets the value of the population property. + * + */ + public void setPopulation(int value) { + this.population = value; + } + +} diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java new file mode 100644 index 0000000000..bda4a305a5 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java @@ -0,0 +1,34 @@ + +package com.baeldung.soap.ws.client.generated; + +import javax.jws.WebMethod; +import javax.jws.WebParam; +import javax.jws.WebResult; +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.ws.Action; + +/** + * This class was generated by the JAX-WS RI. + * JAX-WS RI 2.3.2 + * Generated source version: 2.2 + * + */ +@WebService(name = "CountryService", targetNamespace = "http://server.ws.soap.baeldung.com/") +@SOAPBinding(style = SOAPBinding.Style.RPC) +@XmlSeeAlso({ ObjectFactory.class }) +public interface CountryService { + + /** + * + * @param arg0 + * @return + * returns com.baeldung.soap.ws.client.generated.Country + */ + @WebMethod + @WebResult(partName = "return") + @Action(input = "http://server.ws.soap.baeldung.com/CountryService/findByNameRequest", output = "http://server.ws.soap.baeldung.com/CountryService/findByNameResponse") + public Country findByName(@WebParam(name = "arg0", partName = "arg0") String arg0); + +} diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java new file mode 100644 index 0000000000..09f4c29202 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java @@ -0,0 +1,91 @@ + +package com.baeldung.soap.ws.client.generated; + +import java.net.MalformedURLException; +import java.net.URL; +import javax.xml.namespace.QName; +import javax.xml.ws.Service; +import javax.xml.ws.WebEndpoint; +import javax.xml.ws.WebServiceClient; +import javax.xml.ws.WebServiceException; +import javax.xml.ws.WebServiceFeature; + +/** + * This class was generated by the JAX-WS RI. + * JAX-WS RI 2.3.2 + * Generated source version: 2.2 + * + */ +@WebServiceClient(name = "CountryServiceImplService", targetNamespace = "http://server.ws.soap.baeldung.com/", wsdlLocation = "file:src/main/resources/country.wsdl") +public class CountryServiceImplService extends Service { + + private final static URL COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION; + private final static WebServiceException COUNTRYSERVICEIMPLSERVICE_EXCEPTION; + private final static QName COUNTRYSERVICEIMPLSERVICE_QNAME = new QName("http://server.ws.soap.baeldung.com/", "CountryServiceImplService"); + + static { + URL url = null; + WebServiceException e = null; + try { + url = new URL("file:src/main/resources/country.wsdl"); + } catch (MalformedURLException ex) { + e = new WebServiceException(ex); + } + COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION = url; + COUNTRYSERVICEIMPLSERVICE_EXCEPTION = e; + } + + public CountryServiceImplService() { + super(__getWsdlLocation(), COUNTRYSERVICEIMPLSERVICE_QNAME); + } + + public CountryServiceImplService(WebServiceFeature... features) { + super(__getWsdlLocation(), COUNTRYSERVICEIMPLSERVICE_QNAME, features); + } + + public CountryServiceImplService(URL wsdlLocation) { + super(wsdlLocation, COUNTRYSERVICEIMPLSERVICE_QNAME); + } + + public CountryServiceImplService(URL wsdlLocation, WebServiceFeature... features) { + super(wsdlLocation, COUNTRYSERVICEIMPLSERVICE_QNAME, features); + } + + public CountryServiceImplService(URL wsdlLocation, QName serviceName) { + super(wsdlLocation, serviceName); + } + + public CountryServiceImplService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) { + super(wsdlLocation, serviceName, features); + } + + /** + * + * @return + * returns CountryService + */ + @WebEndpoint(name = "CountryServiceImplPort") + public CountryService getCountryServiceImplPort() { + return super.getPort(new QName("http://server.ws.soap.baeldung.com/", "CountryServiceImplPort"), CountryService.class); + } + + /** + * + * @param features + * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the features parameter will have their default values. + * @return + * returns CountryService + */ + @WebEndpoint(name = "CountryServiceImplPort") + public CountryService getCountryServiceImplPort(WebServiceFeature... features) { + return super.getPort(new QName("http://server.ws.soap.baeldung.com/", "CountryServiceImplPort"), CountryService.class, features); + } + + private static URL __getWsdlLocation() { + if (COUNTRYSERVICEIMPLSERVICE_EXCEPTION != null) { + throw COUNTRYSERVICEIMPLSERVICE_EXCEPTION; + } + return COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION; + } + +} diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java new file mode 100644 index 0000000000..8b9355edc5 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java @@ -0,0 +1,37 @@ + +package com.baeldung.soap.ws.client.generated; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlType; + +/** + *

    Java class for currency. + * + *

    The following schema fragment specifies the expected content contained within this class. + *

    + *

    + * <simpleType name="currency">
    + *   <restriction base="{http://www.w3.org/2001/XMLSchema}string">
    + *     <enumeration value="EUR"/>
    + *     <enumeration value="INR"/>
    + *     <enumeration value="USD"/>
    + *   </restriction>
    + * </simpleType>
    + * 
    + * + */ +@XmlType(name = "currency") +@XmlEnum +public enum Currency { + + EUR, INR, USD; + + public String value() { + return name(); + } + + public static Currency fromValue(String v) { + return valueOf(v); + } + +} diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java new file mode 100644 index 0000000000..241debe758 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java @@ -0,0 +1,38 @@ + +package com.baeldung.soap.ws.client.generated; + +import javax.xml.bind.annotation.XmlRegistry; + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the com.baeldung.soap.ws.client.generated package. + *

    An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.baeldung.soap.ws.client.generated + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link Country } + * + */ + public Country createCountry() { + return new Country(); + } + +} diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java new file mode 100644 index 0000000000..6df70b70f1 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java @@ -0,0 +1,2 @@ +@javax.xml.bind.annotation.XmlSchema(namespace = "http://server.ws.soap.baeldung.com/", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) +package com.baeldung.soap.ws.client.generated; diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/server/Country.java b/jee-7/src/main/java/com/baeldung/soap/ws/server/Country.java new file mode 100644 index 0000000000..62ea4a22ed --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/server/Country.java @@ -0,0 +1,41 @@ +package com.baeldung.soap.ws.server; + +public class Country { + protected String name; + protected int population; + protected String capital; + protected Currency currency; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getPopulation() { + return population; + } + + public void setPopulation(int population) { + this.population = population; + } + + public String getCapital() { + return capital; + } + + public void setCapital(String capital) { + this.capital = capital; + } + + public Currency getCurrency() { + return currency; + } + + public void setCurrency(Currency currency) { + this.currency = currency; + } + +} \ No newline at end of file diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryRepository.java b/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryRepository.java new file mode 100644 index 0000000000..558f7c1293 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryRepository.java @@ -0,0 +1,43 @@ +package com.baeldung.soap.ws.server; + +import java.util.HashMap; +import java.util.Map; + +public class CountryRepository { + + private static final Map countries = new HashMap<>(); + + { + initData(); + } + + private final static void initData() { + Country usa = new Country(); + usa.setName("USA"); + usa.setCapital("Washington D.C."); + usa.setCurrency(Currency.USD); + usa.setPopulation(323947000); + + countries.put(usa.getName(), usa); + + Country india = new Country(); + india.setName("India"); + india.setCapital("New Delhi"); + india.setCurrency(Currency.INR); + india.setPopulation(1295210000); + + countries.put(india.getName(), india); + + Country france = new Country(); + france.setName("France"); + france.setCapital("Paris"); + france.setCurrency(Currency.EUR); + france.setPopulation(66710000); + + countries.put(france.getName(), france); + } + + public Country findCountry(String name) { + return countries.get(name); + } +} diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryService.java b/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryService.java new file mode 100644 index 0000000000..e3f68a4e59 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryService.java @@ -0,0 +1,15 @@ +package com.baeldung.soap.ws.server; + +import javax.jws.WebMethod; +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; +import javax.jws.soap.SOAPBinding.Style; + +@WebService +@SOAPBinding(style=Style.RPC) +public interface CountryService { + + @WebMethod + Country findByName(String name); + +} diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServiceImpl.java b/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServiceImpl.java new file mode 100644 index 0000000000..a8c6250354 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServiceImpl.java @@ -0,0 +1,15 @@ +package com.baeldung.soap.ws.server; + +import javax.jws.WebService; + +@WebService(endpointInterface = "com.baeldung.soap.ws.server.CountryService") +public class CountryServiceImpl implements CountryService { + + private CountryRepository countryRepository = new CountryRepository(); + + @Override + public Country findByName(String name) { + return countryRepository.findCountry(name); + } + +} diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServicePublisher.java b/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServicePublisher.java new file mode 100644 index 0000000000..e7c1c480f4 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServicePublisher.java @@ -0,0 +1,19 @@ +package com.baeldung.soap.ws.server; + +import javax.xml.ws.Endpoint; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class CountryServicePublisher { + + private static final Logger logger = LoggerFactory.getLogger(CountryServicePublisher.class); + + public static void main(String[] args) { + Endpoint endpoint = Endpoint.create(new CountryServiceImpl()); + endpoint.publish("http://localhost:8888/ws/country"); + + logger.info("Country web service ready to consume requests!"); + } +} \ No newline at end of file diff --git a/jee-7/src/main/java/com/baeldung/soap/ws/server/Currency.java b/jee-7/src/main/java/com/baeldung/soap/ws/server/Currency.java new file mode 100644 index 0000000000..d1b25a26c6 --- /dev/null +++ b/jee-7/src/main/java/com/baeldung/soap/ws/server/Currency.java @@ -0,0 +1,15 @@ +package com.baeldung.soap.ws.server; + +public enum Currency { + + EUR, INR, USD; + + public String value() { + return name(); + } + + public static Currency fromValue(String v) { + return valueOf(v); + } + +} diff --git a/jee-7/src/main/resources/country.wsdl b/jee-7/src/main/resources/country.wsdl new file mode 100644 index 0000000000..4d41fce322 --- /dev/null +++ b/jee-7/src/main/resources/country.wsdl @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/jee-7/src/main/resources/country.xsd b/jee-7/src/main/resources/country.xsd new file mode 100644 index 0000000000..c94b6047f9 --- /dev/null +++ b/jee-7/src/main/resources/country.xsd @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/jee-7/src/test/java/com/baeldung/soap/ws/client/CountryClientLiveTest.java b/jee-7/src/test/java/com/baeldung/soap/ws/client/CountryClientLiveTest.java new file mode 100644 index 0000000000..ae423f9bdd --- /dev/null +++ b/jee-7/src/test/java/com/baeldung/soap/ws/client/CountryClientLiveTest.java @@ -0,0 +1,39 @@ +package com.baeldung.soap.ws.client; + +import static org.junit.Assert.assertEquals; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.soap.ws.client.generated.CountryService; +import com.baeldung.soap.ws.client.generated.CountryServiceImplService; +import com.baeldung.soap.ws.client.generated.Currency; + +//Ensure that com.baeldung.soap.ws.server.CountryServicePublisher is running before executing this test +public class CountryClientLiveTest { + + private static CountryService countryService; + + @BeforeClass + public static void setup() { + CountryServiceImplService service = new CountryServiceImplService(); + countryService = service.getCountryServiceImplPort(); + } + + @Test + public void givenCountryService_whenCountryIndia_thenCapitalIsNewDelhi() { + assertEquals("New Delhi", countryService.findByName("India").getCapital()); + } + + @Test + public void givenCountryService_whenCountryFrance_thenPopulationCorrect() { + assertEquals(66710000, countryService.findByName("France").getPopulation()); + } + + @Test + public void givenCountryService_whenCountryUSA_thenCurrencyUSD() { + assertEquals(Currency.USD, countryService.findByName("USA").getCurrency()); + } + + +} From 28de9f499781531a65d71041ebd5101f1401793c Mon Sep 17 00:00:00 2001 From: Mona Mohamadinia Date: Wed, 22 Apr 2020 20:37:18 +0430 Subject: [PATCH 191/194] Added Log Group Sample (#9112) --- .../baeldung/group/LogGroupApplication.java | 26 +++++++++++++++++++ .../application-log-group.properties | 1 + 2 files changed, 27 insertions(+) create mode 100644 spring-boot-modules/spring-boot-logging-log4j2/src/main/java/com/baeldung/group/LogGroupApplication.java create mode 100644 spring-boot-modules/spring-boot-logging-log4j2/src/main/resources/application-log-group.properties diff --git a/spring-boot-modules/spring-boot-logging-log4j2/src/main/java/com/baeldung/group/LogGroupApplication.java b/spring-boot-modules/spring-boot-logging-log4j2/src/main/java/com/baeldung/group/LogGroupApplication.java new file mode 100644 index 0000000000..021f27bd98 --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-log4j2/src/main/java/com/baeldung/group/LogGroupApplication.java @@ -0,0 +1,26 @@ +package com.baeldung.group; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@SpringBootApplication +@ActiveProfiles("log-group") +public class LogGroupApplication { + + private static final Logger LOGGER = LoggerFactory.getLogger(LogGroupApplication.class); + + @RequestMapping("/log-group") + public void justLog() { + LOGGER.debug("Received a request"); + } + + public static void main(String[] args) { + SpringApplication.run(LogGroupApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-logging-log4j2/src/main/resources/application-log-group.properties b/spring-boot-modules/spring-boot-logging-log4j2/src/main/resources/application-log-group.properties new file mode 100644 index 0000000000..6dfe11724e --- /dev/null +++ b/spring-boot-modules/spring-boot-logging-log4j2/src/main/resources/application-log-group.properties @@ -0,0 +1 @@ +logging.level.web=debug \ No newline at end of file From b2af9262a218ada40a62a3abeddfe0ae0a763a50 Mon Sep 17 00:00:00 2001 From: Krzysiek Date: Wed, 22 Apr 2020 18:15:29 +0200 Subject: [PATCH 192/194] JAVA-1130: Improvements after review --- .../spring-security-x509/README.md | 7 +++ .../src/main/resources/application.properties | 2 +- .../src/main/resources/application.properties | 4 +- .../spring-security-x509/store/clientBob.p12 | Bin 4024 -> 4024 bytes .../spring-security-x509/store/keystore.jks | Bin 3718 -> 3793 bytes .../spring-security-x509/store/localhost.ext | 5 ++ .../spring-security-x509/store/rootCA.crt | 56 +++++++++--------- .../spring-security-x509/store/truststore.jks | Bin 1358 -> 1358 bytes 8 files changed, 43 insertions(+), 31 deletions(-) create mode 100644 spring-security-modules/spring-security-x509/store/localhost.ext diff --git a/spring-security-modules/spring-security-x509/README.md b/spring-security-modules/spring-security-x509/README.md index b1eb0debf5..da431d862c 100644 --- a/spring-security-modules/spring-security-x509/README.md +++ b/spring-security-modules/spring-security-x509/README.md @@ -4,3 +4,10 @@ This module contains articles about X.509 authentication with Spring Security ### Relevant Articles: - [X.509 Authentication in Spring Security](https://www.baeldung.com/x-509-authentication-in-spring-security) + +###### Note for the [X.509 Authentication in Spring Security](https://www.baeldung.com/x-509-authentication-in-spring-security): +All the ready to use certificates are located in the [store](store) directory. The application is already configured to use these files. +This means the app works out of the box. + +However, it's highly recommended that you follow the article step by step and generate all the needed files by yourself. +This will let you understand the topic more deeply. \ No newline at end of file diff --git a/spring-security-modules/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties b/spring-security-modules/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties index 208cc90b47..0ba5fa1b8c 100644 --- a/spring-security-modules/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties +++ b/spring-security-modules/spring-security-x509/spring-security-x509-basic-auth/src/main/resources/application.properties @@ -1,4 +1,4 @@ -server.ssl.key-store=store/keystore.jks +server.ssl.key-store=../store/keystore.jks server.ssl.key-store-password=changeit server.ssl.key-alias=localhost server.ssl.key-password=changeit diff --git a/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties b/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties index b841a37916..fc2fc89396 100644 --- a/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties +++ b/spring-security-modules/spring-security-x509/spring-security-x509-client-auth/src/main/resources/application.properties @@ -1,4 +1,4 @@ -server.ssl.key-store=store/keystore.jks +server.ssl.key-store=../store/keystore.jks server.ssl.key-store-password=changeit server.ssl.key-alias=localhost server.ssl.key-password=changeit @@ -6,6 +6,6 @@ server.ssl.enabled=true server.port=8443 spring.security.user.name=Admin spring.security.user.password=admin -server.ssl.trust-store=store/truststore.jks +server.ssl.trust-store=../store/truststore.jks server.ssl.trust-store-password=changeit server.ssl.client-auth=need \ No newline at end of file diff --git a/spring-security-modules/spring-security-x509/store/clientBob.p12 b/spring-security-modules/spring-security-x509/store/clientBob.p12 index e5d6dbcefbfaffa2502b1ed9613bc1cb2f9ce573..b5de8ab129d23828273dd98f929290facba95900 100644 GIT binary patch delta 3873 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 delta 3873 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 diff --git a/spring-security-modules/spring-security-x509/store/keystore.jks b/spring-security-modules/spring-security-x509/store/keystore.jks index 8650651a1e0a884555a4219049340ce2314315cb..c317c1d5ba5ba67fe18af77ec98ce6085616a2f6 100644 GIT binary patch delta 3702 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 diff --git a/spring-security-modules/spring-security-x509/store/localhost.ext b/spring-security-modules/spring-security-x509/store/localhost.ext new file mode 100644 index 0000000000..45324cc75a --- /dev/null +++ b/spring-security-modules/spring-security-x509/store/localhost.ext @@ -0,0 +1,5 @@ +authorityKeyIdentifier=keyid,issuer +basicConstraints=CA:FALSE +subjectAltName = @alt_names +[alt_names] +DNS.1 = localhost diff --git a/spring-security-modules/spring-security-x509/store/rootCA.crt b/spring-security-modules/spring-security-x509/store/rootCA.crt index 12677eb99f..b2ab681744 100644 --- a/spring-security-modules/spring-security-x509/store/rootCA.crt +++ b/spring-security-modules/spring-security-x509/store/rootCA.crt @@ -1,30 +1,30 @@ -----BEGIN CERTIFICATE----- -MIIFDzCCAvegAwIBAgIUHBIbl/8i0uLnPD8BuNHninzcqEMwDQYJKoZIhvcNAQEL -BQAwFzEVMBMGA1UEAwwMQmFlbGR1bmcuY29tMB4XDTIwMDQxOTE2MTYyOFoXDTMw -MDQxNzE2MTYyOFowFzEVMBMGA1UEAwwMQmFlbGR1bmcuY29tMIICIjANBgkqhkiG -9w0BAQEFAAOCAg8AMIICCgKCAgEAx5UzDt8Q+p8fAERc8mb8vPJTMi1oTe3YsMjj -QsMpRJBjVyQ2BLe0AzevQjDthCD56sv+u6EoBibIDQ3rtXUpTi20XQU6aaU6tsmG -QBp/PapXU0qoRzoyTPjSpkjp8/VngH52adeQ0YFSQQfxzcFsEpIlceKC8bSqplQg -mM9GoRLzEHu8JoLtHHQvZhTZabB/t0SUNy6O848OmoEjW2PCyMG/XczP0BlSFDT/ -3FIJlTnKe+MfhXxbYuydQQbStoDuRqkHxprjRaCT/PXeEuW68FahyiTgeKL5Ite9 -NI0k37mRsO/gMPIMgJDU0Soz0zcaRZdQDrxTZBk43i2O/LSwPtcpxvOy5JCLJSP7 -Ff6yx6BkkIAxLrWZGIQ0DiL4L+XocjEy3WMhzQ/ka6M1Zi0JxCRBOPpV2yO1GE7U -NUVvHaHijiJlXGZ/YGzplkLGaPIPGLHRsJFf9+IDepyJ9+E2mKD1rXAYXrcGW/Hk -Is1A2Je0iH4IjYTrieMSuHG4Jb0fytMAPoFOXnLS18xv7CPX0m9M2OIL9/kFfI+f -4M7/mEOUwQw+Jt9EAz9QsjUdZ0ybT0gtq9GaIHBo844YbyEKe7Hzp5Msk4/+3qJz -FHyC8ay73jkLDv1jOKr9D/wd/TOfSrytktcP+y96+gUdp1RxMxv9hfFSAZ0lXd2E -X18X6RECAwEAAaNTMFEwHQYDVR0OBBYEFPIRVQmLHgzCWfvENpeURm3jt2K4MB8G -A1UdIwQYMBaAFPIRVQmLHgzCWfvENpeURm3jt2K4MA8GA1UdEwEB/wQFMAMBAf8w -DQYJKoZIhvcNAQELBQADggIBAGa6bvEvira9FJ559bRvnqNsdaybj++Q9ItRyejs -BvLupLhhCnFWC1rX3WufpyGxgQCu4Lng+ZXtJxSo4dJL4wXDf5U+/EgL0nNQXhQh -kcqm2k1GBgAPnKEt+9nF3326EchI7Vx7JV4AO89ifdfc3Z7q9MOWE4siro6JtK7l -WWfv7LwT9QdDW/Ww7wUAOKdJYlUBzqMYHwEBnIhNMyuFejDzc2GmkZiIjFq5bKoN -FpsjHCkPH4DdDhQKdwa1JRvML7r8IkVqL3NoSp2vkB07MkRiHtQL5R2/wI/WhiK2 -19YPeEP2fQc5NduFAqyz8VaxwskwtjCjUxJHKpEzUTa1n53X+0jx6yw7bmDnE4SW -JEq9563apphJWeFTGCSuTvc98TcZvxWDW8FeLoaWdBF+Tohddje10BW2IUvrSJHI -jh0LpWIJ6QTY+amwLF2USSgnBZwPZT34PS81FYmA1bn/Sa6uWc/dPZg9lvwKU6ta -Z9K4loc8OF+FXQHruV+3tqzXybR9dZG3fvW4RPR9BgxApzSw8lYKAfR5Lth7ihVi -/zlxZjvbXy0D+4xPg5OGwn3g/3n4XLhAMT87KvHc9VjbHt6uwmLgny+6Dw9JXuTC -R004LuQe3wfUye4x9WmQD5Zlg1dENvezCG8l9z5LRUDF+Rh0qXPMpUCaCuT3TvEN -clOH +MIIFDzCCAvegAwIBAgIUDmhG1yLlF83ydOWPit8/MYNbaC8wDQYJKoZIhvcNAQEL +BQAwFzEVMBMGA1UEAwwMQmFlbGR1bmcuY29tMB4XDTIwMDQyMjE1MzEyMFoXDTMw +MDQyMDE1MzEyMFowFzEVMBMGA1UEAwwMQmFlbGR1bmcuY29tMIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEAmkOSeQRQBQdoJio7Odm19kKVm4Y1ju1zscGM +LBWQ4GU8d3Y5AiOVzHtYUbKyJvmmUSYOH/mYdQ8F5nKKaXhTz92LIMnSXnusAqdD +YSvKa+mBoMLsd4Gl9lljipTvRwkkPlPXGVBDEVzXPf32l+5YxpGZzyVyj0WYT1cP +sZyThbOwue4h6gwer4SZ0HNPSts8TG7oiA4UTZSN5hhhbJmRBc87Xz+hJOMayZp6 +HA3tGTlrTkP/Vc3nii/G9tBeydmTTKj+BGFQW4qzDG6nJVvYyB4iri4ActREREGD +ycPS7SVXqEcA4rvSMR7DYoHVLkOg0uiQDWtj4zYcN9qgWVjcnIlUSPxrCgdJbakl +lRzrVpbkdlOC3hFSytoOBmCPS56gJ5npeLFh6IoPPdoXJwIXIJ1twCWtKzvlvlzb +DkMDytRVk2LYjh7IvtAWPTz5QofRdd2fW6iAWPdWbwcnq1xjO5BT8uGj+zOiA19/ +T2YebwD+pLAUM2w0ykLm+bH+DiSRa76wpKxuo6sSUefkeEt8Avojwh8nNbEOvXhf +El4zyimwTlfUYnaKEllUjRWVPhQPGCeCBHe1ES8UFf8hqGS2LRjKAZK70OcFdLyd +18sas/EXkNbd+Mpgata/zO9Oy/3h+xY426T5bPAt+wU38yMUaE+z5BS84m2GOtuQ +nC3a/HcCAwEAAaNTMFEwHQYDVR0OBBYEFFyRjr/LWlOZHv7JU7kQ1g76nq4SMB8G +A1UdIwQYMBaAFFyRjr/LWlOZHv7JU7kQ1g76nq4SMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQELBQADggIBAJWjUR/HBw5f7ogfyCVK/5fJutOFIIHqzNhExvDe +5wu9msPRAj+5ruGHtMWwOKm5qT82gZKJnAVct8XZXTIHU8mKS5Lbk02hu3e2tR/0 +RCzH4TCCD3fDJaW/jAZyU3oPtvcCaSmPwibG7SvDXtUvSSwCW8Omg7WqhnSWGUOn +WH3105lw8UKRTg57CaNu0GunqO4r0GcrgVShNKjCvNv7nGcP3+KWouZekBdn/iY5 +3Q8llL8WUMOHRwH6Raa6CV+vckCthUSpJdBAgGN44QtkA0iL/afVuE7VuTqsnCBA +nbOz/ssZOP0TUVYwoRiDN50gJdB8IKMHZu9Px2m7fJuGgZ7QDe56+tePypgM9KDq +yx4MKMP3Qc5xLE4pGM9SI1sGo+waW0+gPShNECHY4z8fOHw5bn+J1mrEWQbHfMGg +Z/352qps5Hd6PljLAHmWAJL2nXS2zlXbccdYuv4ZtNIeDUT8eX/9NuJdXrITq9QQ +oSBmyzH1bUJi2/mULcFy0Ibcu+OY/r8t67NrGKwLPLyozScwnFQE9SZR9d2cu6sC +yxQtcd68vdvAIEDTk4DcSldeT44HIJ7RYQuBNZ5NU3SngMLDleec/3AZSUXTExFW +TrbMTb+djM+XcTkRyO0wO0MYpjKGqN3sAGfppx0G9kgmJ9HB38nZfvqj3G1L9YFQ +6kSA -----END CERTIFICATE----- diff --git a/spring-security-modules/spring-security-x509/store/truststore.jks b/spring-security-modules/spring-security-x509/store/truststore.jks index 56654d8894466a86807235b65167f49f0a4b5a1d..1d0d20058040144717dadcfbc0560b85a0e9a284 100644 GIT binary patch delta 1196 zcmV;d1XKIY3eF0U7zCn`0jiN48Wav_M%Nf4Kpw>G%_$TH8U|XFp-fvf0{#*c?3`e2WTcLJ2~04_Cl4LhBc1ubFsmUEESO8 zWjuFwIRYb<%zIc-va%-mrcoviANiPd4+Z9OifMRL&)th4$4Bia z?012s_E}?!lx=kPT~N<2D>O+Mrojf83mjR7m`53I|DTsU?*h>sFTJc2k1h5mL(94hCS4OP-)7 zndx}3Vd#nvJ=zy10v8~iZNMe1D?8=BT-y#q1IpA@lVaG89>~7X7Ck)qLWj|H-Je^i zfLQldZwDue;mcuRZ&`Xj<0CpEDSy?9>|UNg!muufOhVs?rWSyYV`l|B>?7$<@RceN2O6czs= zsARS+7|H>XyU^zabiAF{%Nn!s7m(K7_{v~v*1yc}PRsq_`xZFcr1@;{E&ByG^CJ{! zPqX9{yy9(!I@^$(O)c8|cLDUqf$GfIM8@#m=L@}>!_fjixvt@dw8gMEskx~?Hi43foCRFB#o1jl z2UE$4OOo4@O`*GYwzVJhL@dYQFoF+v!zHD^j0SR3dJneu0%<9a!Y0P;E5lyZFG(x{ zTf?S)0uGbLXl1mdkLd%&}*lt?kmt|D}hv@G^oP7+xwhn58vXJ zqUK(Z7iaz^Io%H>l)n~G!-q!!`bDO?316>rK&^#DsU^@rfMa;!3uFUGi~Xn7xK7o% zI;@-^K%KL*{>vFS{S#4EFrgTOH=Q6Q(0m}H2WIb2$7#EKn}&aZp3n{MdivLo%9srF zpz6yW3@F3*LC$e3PAM4AQX^XiqwE@6PoO<0O%Ng2<3Arbd^v7^iPmbwSq8^^!JudT z`P!;%1r6fJSyyuI7N zAVAZTfZR$~UQdn(AfC}-3xPGBO;dEIfWpI-=bZm=8A(Oc6A@NUw#-exos7?yaXAsl z?Jzq-7^X6YsNL)UXX&RM2KGoMC(*&*$=QDTqugyv^??{r>O_FH=7mnG%+_ZHZe9bIFXS%f5(+G4&M;^pC153T=Hi8yz)~rEoe>c*s#dsLc=LU zkYiUQHUzh{12?ZiFztjO`RdF5yP+rsCdds9>$P<$PA#-u1v+V^I=0D%KpKBNs#jA= zs7E?7O!(5KNa^$SXMlcoY1fd^fl@&S@y)?(5|Slx;)3zCs-{#Rn9oL`e-iT$d%Pxs z?HqJ3W)#_Juz$Bils7Jp^N$Xifg@XE!pOnDUChtW8B!E9|J+gul{w0L;~#~5TVm{; zK?c&cfbK@A2gaJ?MWB=X_1+TYy6{$^$|T@;qWL1%y)=y^-?@>n@8B@<41kc-(JC|3 zHyTBkP!7CPWEnW#Esp%Of3QB+DaP}%6SvqXz~vjvC*)R zU-#kzdYp;(;Wn6{^{sFiUbhBY@#G@SK-ibGh<*r-gzJgp61Z`=e z($~yy>?7CGZ%o+Y3-|d2e2<^t&i|N0l)(%>Cf`H@KTxtY9cN6NPe?7R(V8G|X!DL3 zZy^eMvGb>sER&D^-lB69e1h?;yWTkq4*g>|s{IfA9sM((O1!O-*AM$Idin(&r&Mt> z8~ugxQURSMUEPFVO`D}{P6^K)UQ zk(h{#TDfeh4Hlat94QYUfZYxh3U>yzB^%5yy8I$VYAi$Hno4Bo!9$F@#`!*ZeZsV zgq9>qz2~jkrkF`t;ZqnSu1@zo@i!U26@y#BUM_}~bP;||h+TF!wa^u|AxrB>k;sl6 z3#DQS=>*vMsjw_vlu0Nj1)L9MJ@`E@H5G|~)w%ykuC7_n-94B+mi!7+t6FE$xR!@J zIA4Wb0qeP6x3+(**U7Yfb&gHX@M8)j?l^w{ From 8bd69814b04b55c54fb7da0c80682b5b84d2e742 Mon Sep 17 00:00:00 2001 From: Benjamin Caure Date: Thu, 23 Apr 2020 07:23:11 +0200 Subject: [PATCH 193/194] BAEL-3964 HTML emails with Thymeleaf and FreeMarker (#9119) --- spring-mvc-basics-2/README.md | 1 + .../ApplicationConfiguration.java | 30 +----- .../configuration/EmailConfiguration.java | 89 ++++++++++++++++++ .../spring/configuration/WebInitializer.java | 1 + .../spring/controller/MailController.java | 80 ++++++++++++---- .../baeldung/spring/domain/MailObject.java | 29 ++++++ .../baeldung/spring/mail/EmailService.java | 20 +++- .../spring/mail/EmailServiceImpl.java | 84 ++++++++++++++--- .../src/main/resources/mail-logo.png | Bin 0 -> 7391 bytes .../main/resources/mailMessages.properties | 5 + .../resources/mailMessages_fr_FR.properties | 5 + .../src/main/webapp/WEB-INF/views/emails.jsp | 7 +- .../webapp/WEB-INF/views/mail/sendHtml.jsp | 73 ++++++++++++++ .../views/mail/template-freemarker.ftl | 15 +++ .../views/mail/template-thymeleaf.html | 15 +++ .../java/com/baeldung/SpringContextTest.java | 3 +- .../rss/ArticleRssIntegrationTest.java | 4 +- 17 files changed, 396 insertions(+), 65 deletions(-) create mode 100644 spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java create mode 100644 spring-mvc-basics-2/src/main/resources/mail-logo.png create mode 100644 spring-mvc-basics-2/src/main/resources/mailMessages.properties create mode 100644 spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties create mode 100644 spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp create mode 100644 spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-freemarker.ftl create mode 100644 spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-thymeleaf.html diff --git a/spring-mvc-basics-2/README.md b/spring-mvc-basics-2/README.md index 9d1402a210..e52459bd6e 100644 --- a/spring-mvc-basics-2/README.md +++ b/spring-mvc-basics-2/README.md @@ -9,6 +9,7 @@ This module contains articles about Spring MVC - [Servlet Redirect vs Forward](https://www.baeldung.com/servlet-redirect-forward) - [Apache Tiles Integration with Spring MVC](https://www.baeldung.com/spring-mvc-apache-tiles) - [Guide to Spring Email](https://www.baeldung.com/spring-email) +- [Using ThymeLeaf and FreeMarker Emails Templates with Spring](https://www.baeldung.com/thymeleaf-freemarker-email) - [Request Method Not Supported (405) in Spring](https://www.baeldung.com/spring-request-method-not-supported-405) - [Spring @RequestParam Annotation](https://www.baeldung.com/spring-request-param) - More articles: [[more -->]](/spring-mvc-basics-3) diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java index 941a984684..e70e801577 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java @@ -2,7 +2,6 @@ package com.baeldung.spring.configuration; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -10,9 +9,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.feed.RssChannelHttpMessageConverter; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.web.accept.ContentNegotiationManager; import org.springframework.web.multipart.MultipartResolver; import org.springframework.web.multipart.commons.CommonsMultipartResolver; @@ -65,29 +61,5 @@ public class ApplicationConfiguration implements WebMvcConfigurer { converters.add(new RssChannelHttpMessageConverter()); converters.add(new JsonChannelHttpMessageConverter()); } - - @Bean - public SimpleMailMessage templateSimpleMessage() { - SimpleMailMessage message = new SimpleMailMessage(); - message.setText("This is the test email template for your email:\n%s\n"); - return message; - } - - @Bean - public JavaMailSender getJavaMailSender() { - JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); - mailSender.setHost("smtp.gmail.com"); - mailSender.setPort(587); - - mailSender.setUsername("my.gmail@gmail.com"); - mailSender.setPassword("password"); - - Properties props = mailSender.getJavaMailProperties(); - props.put("mail.transport.protocol", "smtp"); - props.put("mail.smtp.auth", "true"); - props.put("mail.smtp.starttls.enable", "true"); - props.put("mail.debug", "true"); - - return mailSender; - } + } diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java new file mode 100644 index 0000000000..1bbbc51304 --- /dev/null +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java @@ -0,0 +1,89 @@ +package com.baeldung.spring.configuration; + +import java.util.Properties; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; +import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver; +import org.thymeleaf.spring4.SpringTemplateEngine; +import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver; + +@Configuration +@ComponentScan(basePackages = { "com.baeldung.spring.mail" }) +public class EmailConfiguration { + + @Bean + public JavaMailSender getJavaMailSender() { + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + + mailSender.setHost("smtp.gmail.com"); + mailSender.setPort(587); + + mailSender.setUsername("my.gmail@gmail.com"); + mailSender.setPassword("password"); + + Properties props = mailSender.getJavaMailProperties(); + props.put("mail.transport.protocol", "smtp"); + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.starttls.enable", "false"); + props.put("mail.debug", "true"); + + return mailSender; + } + + @Bean + public SimpleMailMessage templateSimpleMessage() { + SimpleMailMessage message = new SimpleMailMessage(); + message.setText("This is the test email template for your email:\n%s\n"); + return message; + } + + @Bean + public SpringTemplateEngine thymeleafTemplateEngine() { + SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.setTemplateResolver(thymeleafTemplateResolver()); + templateEngine.setTemplateEngineMessageSource(emailMessageSource()); + return templateEngine; + } + + @Bean + public SpringResourceTemplateResolver thymeleafTemplateResolver() { + SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); + templateResolver.setPrefix("/WEB-INF/views/mail/"); + templateResolver.setSuffix(".html"); + templateResolver.setTemplateMode("HTML"); + templateResolver.setCharacterEncoding("UTF-8"); + return templateResolver; + } + + @Bean + public FreeMarkerConfigurer freemarkerConfig() { + FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer(); + freeMarkerConfigurer.setTemplateLoaderPath("/WEB-INF/views/mail"); + return freeMarkerConfigurer; + } + + @Bean + public FreeMarkerViewResolver freemarkerViewResolver() { + FreeMarkerViewResolver resolver = new FreeMarkerViewResolver(); + resolver.setCache(true); + resolver.setPrefix(""); + resolver.setSuffix(".ftl"); + return resolver; + } + + + @Bean + public ResourceBundleMessageSource emailMessageSource() { + final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setBasename("/mailMessages"); + return messageSource; + } + +} diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java index 74094a11c7..4d43549440 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java @@ -20,6 +20,7 @@ public class WebInitializer implements WebApplicationInitializer { // ctx.register(GroovyConfiguration.class); // ctx.register(JadeTemplateConfiguration.class); // ctx.register(PushConfiguration.class); + ctx.register(EmailConfiguration.class); // ctx.setServletContext(container); //ctx.register(TilesApplicationConfiguration.class); diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java index 16d1202eef..b6e19a4c39 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java @@ -1,10 +1,17 @@ package com.baeldung.spring.controller; -import com.baeldung.spring.mail.EmailServiceImpl; -import com.baeldung.spring.domain.MailObject; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import javax.mail.MessagingException; +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.mail.SimpleMailMessage; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.Errors; @@ -12,26 +19,21 @@ import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; +import com.baeldung.spring.domain.MailObject; +import com.baeldung.spring.mail.EmailService; + +import freemarker.template.TemplateException; @Controller @RequestMapping("/mail") public class MailController { @Autowired - public EmailServiceImpl emailService; + public EmailService emailService; @Value("${attachment.invoice}") private String attachmentPath; - @Autowired - public SimpleMailMessage template; - private static final Map> labels; static { @@ -46,7 +48,7 @@ public class MailController { //Email with template props = new HashMap<>(); - props.put("headerText", "Send Email Using Template"); + props.put("headerText", "Send Email Using Text Template"); props.put("messageLabel", "Template Parameter"); props.put("additionalInfo", "The parameter value will be added to the following message template:
    " + @@ -60,6 +62,7 @@ public class MailController { props.put("messageLabel", "Message"); props.put("additionalInfo", "To make sure that you send an attachment with this email, change the value for the 'attachment.invoice' in the application.properties file to the path to the attachment."); labels.put("sendAttachment", props); + } @RequestMapping(method = RequestMethod.GET) @@ -85,6 +88,7 @@ public class MailController { return "mail/send"; } + @RequestMapping(value = "/send", method = RequestMethod.POST) public String createMail(Model model, @ModelAttribute("mailObject") @Valid MailObject mailObject, @@ -95,7 +99,7 @@ public class MailController { emailService.sendSimpleMessage(mailObject.getTo(), mailObject.getSubject(), mailObject.getText()); - return "redirect:/home"; + return "emails"; } @RequestMapping(value = "/sendTemplate", method = RequestMethod.POST) @@ -107,10 +111,9 @@ public class MailController { } emailService.sendSimpleMessageUsingTemplate(mailObject.getTo(), mailObject.getSubject(), - template, mailObject.getText()); - return "redirect:/home"; + return "redirect:/mail"; } @RequestMapping(value = "/sendAttachment", method = RequestMethod.POST) @@ -127,6 +130,47 @@ public class MailController { attachmentPath ); - return "redirect:/home"; + return "redirect:/mail"; + } + + + @RequestMapping(value = {"/sendHtml"}, method = RequestMethod.GET) + public String getHtmlMailView(Model model, + HttpServletRequest request) { + + Map templateEngines = new HashMap<>(); + templateEngines.put("Thymeleaf", "Thymeleaf"); + templateEngines.put("Freemarker", "Freemarker"); + model.addAttribute("mailObject", new MailObject()); + model.addAttribute("templateEngines", templateEngines); + return "mail/sendHtml"; + } + + @RequestMapping(value = "/sendHtml", method = RequestMethod.POST) + public String createHtmlMail(Model model, + @ModelAttribute("mailObject") @Valid MailObject mailObject, + Errors errors) throws IOException, MessagingException, TemplateException { + if (errors.hasErrors()) { + return "mail/send"; + } + + Map templateModel = new HashMap<>(); + templateModel.put("recipientName", mailObject.getRecipientName()); + templateModel.put("text", mailObject.getText()); + templateModel.put("senderName", mailObject.getSenderName()); + + if (mailObject.getTemplateEngine().equalsIgnoreCase("thymeleaf")) { + emailService.sendMessageUsingThymeleafTemplate( + mailObject.getTo(), + mailObject.getSubject(), + templateModel); + } else { + emailService.sendMessageUsingFreemarkerTemplate( + mailObject.getTo(), + mailObject.getSubject(), + templateModel); + } + + return "redirect:/mail"; } } diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java index aceaf685fa..d425ca9a26 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java @@ -12,8 +12,11 @@ public class MailObject { @NotNull @Size(min = 1, message = "Please, set an email address to send the message to it") private String to; + private String recipientName; private String subject; private String text; + private String senderName; + private String templateEngine; public String getTo() { return to; @@ -38,4 +41,30 @@ public class MailObject { public void setText(String text) { this.text = text; } + + public String getRecipientName() { + return recipientName; + } + + public void setRecipientName(String recipientName) { + this.recipientName = recipientName; + } + + public String getSenderName() { + return senderName; + } + + public void setSenderName(String senderName) { + this.senderName = senderName; + } + + public String getTemplateEngine() { + return templateEngine; + } + + public void setTemplateEngine(String templateEngine) { + this.templateEngine = templateEngine; + } + + } diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java index 43d7378227..b7d5be09c8 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java @@ -1,6 +1,11 @@ package com.baeldung.spring.mail; -import org.springframework.mail.SimpleMailMessage; +import java.io.IOException; +import java.util.Map; + +import javax.mail.MessagingException; + +import freemarker.template.TemplateException; /** * Created by Olga on 8/22/2016. @@ -11,10 +16,19 @@ public interface EmailService { String text); void sendSimpleMessageUsingTemplate(String to, String subject, - SimpleMailMessage template, - String ...templateArgs); + String ...templateModel); void sendMessageWithAttachment(String to, String subject, String text, String pathToAttachment); + + void sendMessageUsingThymeleafTemplate(String to, + String subject, + Map templateModel) + throws IOException, MessagingException; + + void sendMessageUsingFreemarkerTemplate(String to, + String subject, + Map templateModel) + throws IOException, TemplateException, MessagingException; } diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java index 039b970d8e..0592415ab5 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java +++ b/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java @@ -1,26 +1,49 @@ package com.baeldung.spring.mail; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.FileSystemResource; -import org.springframework.mail.MailException; -import org.springframework.mail.SimpleMailMessage; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.MimeMessageHelper; -import org.springframework.stereotype.Component; - import java.io.File; +import java.io.IOException; +import java.util.Map; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.mail.MailException; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; +import org.thymeleaf.context.Context; +import org.thymeleaf.spring4.SpringTemplateEngine; + +import freemarker.template.Template; +import freemarker.template.TemplateException; + /** * Created by Olga on 7/15/2016. */ -@Component +@Service("EmailService") public class EmailServiceImpl implements EmailService { @Autowired public JavaMailSender emailSender; + + @Autowired + public SimpleMailMessage template; + + @Autowired + private SpringTemplateEngine thymeleafTemplateEngine; + + @Autowired + private FreeMarkerConfigurer freemarkerConfigurer; + + @Value("classpath:/mail-logo.png") + Resource resourceFile; public void sendSimpleMessage(String to, String subject, String text) { try { @@ -38,9 +61,8 @@ public class EmailServiceImpl implements EmailService { @Override public void sendSimpleMessageUsingTemplate(String to, String subject, - SimpleMailMessage template, - String ...templateArgs) { - String text = String.format(template.getText(), templateArgs); + String ...templateModel) { + String text = String.format(template.getText(), templateModel); sendSimpleMessage(to, subject, text); } @@ -66,4 +88,42 @@ public class EmailServiceImpl implements EmailService { e.printStackTrace(); } } + + + @Override + public void sendMessageUsingThymeleafTemplate( + String to, String subject, Map templateModel) + throws MessagingException { + + Context thymeleafContext = new Context(); + thymeleafContext.setVariables(templateModel); + + String htmlBody = thymeleafTemplateEngine.process("template-thymeleaf.html", thymeleafContext); + + sendHtmlMessage(to, subject, htmlBody); + } + + @Override + public void sendMessageUsingFreemarkerTemplate( + String to, String subject, Map templateModel) + throws IOException, TemplateException, MessagingException { + + Template freemarkerTemplate = freemarkerConfigurer.createConfiguration().getTemplate("template-freemarker.ftl"); + String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerTemplate, templateModel); + + sendHtmlMessage(to, subject, htmlBody); + } + + private void sendHtmlMessage(String to, String subject, String htmlBody) throws MessagingException { + + MimeMessage message = emailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(htmlBody, true); + helper.addInline("attachment.png", resourceFile); + emailSender.send(message); + + } + } diff --git a/spring-mvc-basics-2/src/main/resources/mail-logo.png b/spring-mvc-basics-2/src/main/resources/mail-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..edb83efbe3d4f083363fea616d5c0e2df6e1fe03 GIT binary patch literal 7391 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 TggyZsN(>c6O@%LVmf`;o*#$Af literal 0 HcmV?d00001 diff --git a/spring-mvc-basics-2/src/main/resources/mailMessages.properties b/spring-mvc-basics-2/src/main/resources/mailMessages.properties new file mode 100644 index 0000000000..46f7a80ed3 --- /dev/null +++ b/spring-mvc-basics-2/src/main/resources/mailMessages.properties @@ -0,0 +1,5 @@ +greetings=Hi {0}, +subscriptions=Please find below your current subscriptions to our forum: +regards=Regards, +unsubscribe=Unsubscribe from these emails here +signature={0} at Baeldung \ No newline at end of file diff --git a/spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties b/spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties new file mode 100644 index 0000000000..6f300a9ab7 --- /dev/null +++ b/spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties @@ -0,0 +1,5 @@ +greetings=Bonjour {0}, +subscriptions=Voici vos différentes souscriptions sur notre forum : +regards=Cordialement, +unsubscribe=Se désinscrire de ces emails ici +signature={0} à Baeldung \ No newline at end of file diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp index 63351bbf3a..dafa71cbb0 100644 --- a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp +++ b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp @@ -26,7 +26,7 @@ - + @@ -34,6 +34,11 @@ + + + + + diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp new file mode 100644 index 0000000000..f91a8826d1 --- /dev/null +++ b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp @@ -0,0 +1,73 @@ +<%-- + User: Benjamin CAURE + Date: 4/14/2020 +--%> +<%@ page pageEncoding="UTF-8" contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + + Send HTML Email + + +

    +

    Send Email Using Text Template

    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Enter email address
    + +
    + Enter the recipient name
    + +
    + Enter the subject
    + +
    + +
    + Enter the sender name
    + +
    + Select the template engine
    + +
    + +
    +
    +
    +
    +
    + + diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-freemarker.ftl b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-freemarker.ftl new file mode 100644 index 0000000000..066fc0302c --- /dev/null +++ b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-freemarker.ftl @@ -0,0 +1,15 @@ + + + + + + +

    Hi ${recipientName}

    +

    ${text}

    +

    Regards,

    +

    + ${senderName} at Baeldung
    + +

    + + diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-thymeleaf.html b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-thymeleaf.html new file mode 100644 index 0000000000..b255b5dee5 --- /dev/null +++ b/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-thymeleaf.html @@ -0,0 +1,15 @@ + + + + + + +

    +

    +

    +

    +
    + +

    + + diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java index ab0b23c4a5..5c276254d3 100644 --- a/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java @@ -7,10 +7,11 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import com.baeldung.spring.configuration.ApplicationConfiguration; +import com.baeldung.spring.configuration.EmailConfiguration; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes={ApplicationConfiguration.class}) +@ContextConfiguration(classes={ApplicationConfiguration.class, EmailConfiguration.class}) @WebAppConfiguration public class SpringContextTest { diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java index fe7aeeb570..2ed70489c0 100644 --- a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java +++ b/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java @@ -1,6 +1,8 @@ package com.baeldung.controller.rss; import com.baeldung.spring.configuration.ApplicationConfiguration; +import com.baeldung.spring.configuration.EmailConfiguration; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -13,7 +15,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@SpringJUnitWebConfig(ApplicationConfiguration.class) +@SpringJUnitWebConfig(classes={ApplicationConfiguration.class, EmailConfiguration.class}) public class ArticleRssIntegrationTest { public static final String APPLICATION_RSS_XML = "application/rss+xml"; public static final String APPLICATION_RSS_JSON = "application/rss+json"; From 7367f3b0ba099d02f98b78599ca6c860047595b8 Mon Sep 17 00:00:00 2001 From: Usman Mohyuddin Date: Thu, 23 Apr 2020 22:54:55 +0500 Subject: [PATCH 194/194] add code files for "How to determine the data type in Groovy" (#9123) * add code files for "How to groovy data types" add code files for "How to groovy data types" * added Tests in example * Update pom.xml change tab into spaces --- core-groovy-2/determine-datatype/pom.xml | 40 ++++++++++++++ .../groovy/determine/datatype/Person.groovy | 14 +++++ .../determine/datatype/PersonTest.groovy | 55 +++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 core-groovy-2/determine-datatype/pom.xml create mode 100644 core-groovy-2/determine-datatype/src/com/baeldung/groovy/determine/datatype/Person.groovy create mode 100644 core-groovy-2/determine-datatype/src/com/baeldung/groovy/determine/datatype/PersonTest.groovy diff --git a/core-groovy-2/determine-datatype/pom.xml b/core-groovy-2/determine-datatype/pom.xml new file mode 100644 index 0000000000..0bcef4e5d8 --- /dev/null +++ b/core-groovy-2/determine-datatype/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + com.baeldung.groovy + determine-datatype + 0.0.1-SNAPSHOT + + src + + + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + + org.codehaus.gmaven + groovy-maven-plugin + + + org.codehaus.groovy + groovy-all + 2.0.6 + + + + + + + + + org.junit + junit5-engine + 5.0.0-ALPHA + + + \ No newline at end of file diff --git a/core-groovy-2/determine-datatype/src/com/baeldung/groovy/determine/datatype/Person.groovy b/core-groovy-2/determine-datatype/src/com/baeldung/groovy/determine/datatype/Person.groovy new file mode 100644 index 0000000000..1a89dce435 --- /dev/null +++ b/core-groovy-2/determine-datatype/src/com/baeldung/groovy/determine/datatype/Person.groovy @@ -0,0 +1,14 @@ +package com.baeldung.groovy.determine.datatype + +class Person { + + private int ageAsInt + private Double ageAsDouble + private String ageAsString + + Person() {} + Person(int ageAsInt) { this.ageAsInt = ageAsInt} + Person(Double ageAsDouble) { this.ageAsDouble = ageAsDouble} + Person(String ageAsString) { this.ageAsString = ageAsString} +} +class Student extends Person {} diff --git a/core-groovy-2/determine-datatype/src/com/baeldung/groovy/determine/datatype/PersonTest.groovy b/core-groovy-2/determine-datatype/src/com/baeldung/groovy/determine/datatype/PersonTest.groovy new file mode 100644 index 0000000000..56095a3f1b --- /dev/null +++ b/core-groovy-2/determine-datatype/src/com/baeldung/groovy/determine/datatype/PersonTest.groovy @@ -0,0 +1,55 @@ +package com.baeldung.groovy.determine.datatype; + +import org.junit.Assert +import org.junit.Test; + +public class PersonTest { + + @Test + public void givenWhenParameterTypeIsInteger_thenReturnTrue() { + Person personObj = new Person(10) + Assert.assertTrue(personObj.ageAsInt instanceof Integer); + } + + @Test + public void givenWhenParameterTypeIsDouble_thenReturnTrue() { + Person personObj = new Person(10.0) + Assert.assertTrue((personObj.ageAsDouble).getClass() == Double) + } + + @Test + public void givenWhenParameterTypeIsString_thenReturnTrue() { + Person personObj = new Person("10 years") + Assert.assertTrue(personObj.ageAsString.class == String) + } + + @Test + public void givenClassName_WhenParameterIsInteger_thenReturnTrue() { + Assert.assertTrue(Person.class.getDeclaredField('ageAsInt').type == int.class) + } + + @Test + public void givenWhenObjectIsInstanceOfType_thenReturnTrue() { + Person personObj = new Person() + Assert.assertTrue(personObj instanceof Person) + } + + @Test + public void givenWhenInstanceIsOfSubtype_thenReturnTrue() { + Student studentObj = new Student() + Assert.assertTrue(studentObj in Person) + } + + @Test + public void givenGroovyList_WhenFindClassName_thenReturnTrue() { + def ageList = ['ageAsString','ageAsDouble', 10] + Assert.assertTrue(ageList.class == ArrayList) + Assert.assertTrue(ageList.getClass() == ArrayList) + } + + @Test + public void givenGrooyMap_WhenFindClassName_thenReturnTrue() { + def ageMap = [ageAsString: '10 years', ageAsDouble: 10.0] + Assert.assertFalse(ageMap.class == LinkedHashMap) + } +} \ No newline at end of file